From 00fe8a7b2317f11bff754c73a87b69445fe0b33d Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 28 Jun 2009 03:18:59 +0000 Subject: Merged revisions 72912,72920,72940 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r72912 | benjamin.peterson | 2009-05-25 08:13:44 -0500 (Mon, 25 May 2009) | 5 lines add a SETUP_WITH opcode It speeds up the with statement and correctly looks up the special methods involved. ........ r72920 | benjamin.peterson | 2009-05-25 15:12:57 -0500 (Mon, 25 May 2009) | 1 line take into account the fact that SETUP_WITH pushes a finally block ........ r72940 | benjamin.peterson | 2009-05-26 07:49:59 -0500 (Tue, 26 May 2009) | 1 line teach the peepholer about SETUP_WITH ........ --- Python/ceval.c | 70 ++++++++++++++++++++++++++++++++++++++++++----- Python/compile.c | 73 ++++++------------------------------------------- Python/import.c | 3 +- Python/opcode_targets.h | 2 +- Python/peephole.c | 3 ++ 5 files changed, 78 insertions(+), 73 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index b5b5c27272..b689f3de28 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -119,6 +119,7 @@ static int import_all_from(PyObject *, PyObject *); static void format_exc_check_arg(PyObject *, const char *, PyObject *); static PyObject * unicode_concatenate(PyObject *, PyObject *, PyFrameObject *, unsigned char *); +static PyObject * special_lookup(PyObject *, char *, PyObject **); #define NAME_ERROR_MSG \ "name '%.200s' is not defined" @@ -2455,6 +2456,33 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) STACK_LEVEL()); DISPATCH(); + TARGET(SETUP_WITH) + { + static PyObject *exit, *enter; + w = TOP(); + x = special_lookup(w, "__exit__", &exit); + if (!x) + break; + SET_TOP(x); + u = special_lookup(w, "__enter__", &enter); + Py_DECREF(w); + if (!u) { + x = NULL; + break; + } + x = PyObject_CallFunctionObjArgs(u, NULL); + Py_DECREF(u); + if (!x) + break; + /* Setup the finally block before pushing the result + of __enter__ on the stack. */ + PyFrame_BlockSetup(f, SETUP_FINALLY, INSTR_OFFSET() + oparg, + STACK_LEVEL()); + + PUSH(x); + DISPATCH(); + } + TARGET(WITH_CLEANUP) { /* At the top of the stack are 1-3 values indicating @@ -2479,17 +2507,36 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) should still be resumed.) */ - PyObject *exit_func = POP(); + PyObject *exit_func; u = TOP(); if (u == Py_None) { + POP(); + exit_func = TOP(); + SET_TOP(u); v = w = Py_None; } else if (PyLong_Check(u)) { + POP(); + switch(PyLong_AsLong(u)) { + case WHY_RETURN: + case WHY_CONTINUE: + /* Retval in TOP. */ + exit_func = SECOND(); + SET_SECOND(TOP()); + SET_TOP(u); + break; + default: + exit_func = TOP(); + SET_TOP(u); + break; + } u = v = w = Py_None; } else { - v = SECOND(); + v = SECOND(); w = THIRD(); + exit_func = stack_pointer[-7]; + stack_pointer[-7] = NULL; } /* XXX Not the fastest way to call it... */ x = PyObject_CallFunctionObjArgs(exit_func, u, v, w, @@ -2509,11 +2556,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) else if (err > 0) { err = 0; /* There was an exception and a True return */ - STACKADJ(-2); - SET_TOP(PyLong_FromLong((long) WHY_SILENCED)); - Py_DECREF(u); - Py_DECREF(v); - Py_DECREF(w); + PUSH(PyLong_FromLong((long) WHY_SILENCED)); } PREDICT(END_FINALLY); break; @@ -3194,6 +3237,19 @@ fail: /* Jump here from prelude on failure */ } +static PyObject * +special_lookup(PyObject *o, char *meth, PyObject **cache) +{ + PyObject *res; + res = _PyObject_LookupSpecial(o, meth, cache); + if (res == NULL && !PyErr_Occurred()) { + PyErr_SetObject(PyExc_AttributeError, *cache); + return NULL; + } + return res; +} + + /* Logic for the raise statement (too complicated for inlining). This *consumes* a reference count to each of its arguments. */ static enum why_code diff --git a/Python/compile.c b/Python/compile.c index c78949d887..490137f3db 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -761,6 +761,8 @@ opcode_stack_effect(int opcode, int oparg) return -1; case BREAK_LOOP: return 0; + case SETUP_WITH: + return 7; case WITH_CLEANUP: return -1; /* XXX Sometimes more */ case STORE_LOCALS: @@ -3085,85 +3087,31 @@ expr_constant(expr_ty e) static int compiler_with(struct compiler *c, stmt_ty s) { - static identifier enter_attr, exit_attr; basicblock *block, *finally; - identifier tmpvalue = NULL, tmpexit = NULL; assert(s->kind == With_kind); - if (!enter_attr) { - enter_attr = PyUnicode_InternFromString("__enter__"); - if (!enter_attr) - return 0; - } - if (!exit_attr) { - exit_attr = PyUnicode_InternFromString("__exit__"); - if (!exit_attr) - return 0; - } - block = compiler_new_block(c); finally = compiler_new_block(c); if (!block || !finally) return 0; - 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); - } - tmpexit = compiler_new_tmpname(c); - if (tmpexit == NULL) - return 0; - PyArena_AddPyObject(c->c_arena, tmpexit); - /* Evaluate EXPR */ VISIT(c, expr, s->v.With.context_expr); + ADDOP_JREL(c, SETUP_WITH, finally); - /* Squirrel away context.__exit__ by stuffing it under context */ - 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); - + /* SETUP_WITH pushes a finally block. */ 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); + VISIT(c, expr, s->v.With.optional_vars); + } + else { + /* Discard result from context.__enter__() */ + ADDOP(c, POP_TOP); } /* BLOCK code */ @@ -3181,9 +3129,6 @@ compiler_with(struct compiler *c, stmt_ty s) /* Finally block starts; context.__exit__ is on the stack under the exception or return information. Just issue our magic opcode. */ - if (!compiler_nameop(c, tmpexit, Load) || - !compiler_nameop(c, tmpexit, Del)) - return 0; ADDOP(c, WITH_CLEANUP); /* Finally block ends. */ diff --git a/Python/import.c b/Python/import.c index bccb9711fb..23dd7b4d08 100644 --- a/Python/import.c +++ b/Python/import.c @@ -89,9 +89,10 @@ typedef unsigned short mode_t; change LIST_APPEND and SET_ADD, add MAP_ADD) Python 3.1a0: 3150 (optimize conditional branches: introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE) + Python 3.2a0: 3160 (add SETUP_WITH) */ -#define MAGIC (3150 | ((long)'\r'<<16) | ((long)'\n'<<24)) +#define MAGIC (3160 | ((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. */ diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 043e42a30a..deaf0a31b7 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -142,8 +142,8 @@ static void *opcode_targets[256] = { &&TARGET_CALL_FUNCTION_VAR, &&TARGET_CALL_FUNCTION_KW, &&TARGET_CALL_FUNCTION_VAR_KW, + &&TARGET_SETUP_WITH, &&TARGET_EXTENDED_ARG, - &&_unknown_opcode, &&TARGET_LIST_APPEND, &&TARGET_SET_ADD, &&TARGET_MAP_ADD, diff --git a/Python/peephole.c b/Python/peephole.c index de1b2aca0d..23735b0a31 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -251,6 +251,7 @@ markblocks(unsigned char *code, Py_ssize_t len) case SETUP_LOOP: case SETUP_EXCEPT: case SETUP_FINALLY: + case SETUP_WITH: j = GETJUMPTGT(code, i); blocks[j] = 1; break; @@ -566,6 +567,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, case SETUP_LOOP: case SETUP_EXCEPT: case SETUP_FINALLY: + case SETUP_WITH: tgt = GETJUMPTGT(codestr, i); /* Replace JUMP_* to a RETURN into just a RETURN */ if (UNCONDITIONAL_JUMP(opcode) && @@ -648,6 +650,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, case SETUP_LOOP: case SETUP_EXCEPT: case SETUP_FINALLY: + case SETUP_WITH: j = addrmap[GETARG(codestr, i) + i + 3] - addrmap[i] - 3; SETARG(codestr, i, j); break; -- cgit v1.2.1 From 9f99de518802706f84183a88f1b12a779757619e Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 28 Jun 2009 15:40:50 +0000 Subject: correctly rearrange the stack in the exception case of WITH_CLEANUP --- Python/ceval.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index b689f3de28..24e41689ad 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2533,10 +2533,21 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) u = v = w = Py_None; } else { + PyObject *tp, *exc, *tb; + PyTryBlock *block; v = SECOND(); w = THIRD(); + tp = FOURTH(); + exc = stack_pointer[-5]; + tb = stack_pointer[-6]; exit_func = stack_pointer[-7]; - stack_pointer[-7] = NULL; + stack_pointer[-7] = tb; + stack_pointer[-6] = exc; + stack_pointer[-5] = tp; + FOURTH() = NULL; + block = &f->f_blockstack[f->f_iblock - 1]; + assert(block->b_type == EXCEPT_HANDLER); + block->b_level--; } /* XXX Not the fastest way to call it... */ x = PyObject_CallFunctionObjArgs(exit_func, u, v, w, -- cgit v1.2.1 From 087c4b37e2d8c2e108c700564e1f13e8b87952fa Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 28 Jun 2009 15:55:46 +0000 Subject: update comments --- Python/ceval.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 24e41689ad..a42a66559b 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2491,20 +2491,23 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) - (TOP, SECOND) = (WHY_{RETURN,CONTINUE}), retval - TOP = WHY_*; no retval below it - (TOP, SECOND, THIRD) = exc_info() + (FOURTH, FITH, SIXTH) = previous exception for EXCEPT_HANDLER Below them is EXIT, the context.__exit__ bound method. In the last case, we must call EXIT(TOP, SECOND, THIRD) otherwise we must call EXIT(None, None, None) - In all cases, we remove EXIT from the stack, leaving - the rest in the same order. + In the first two cases, we remove EXIT from the + stack, leaving the rest in the same order. In the + third case, we shift the bottom 3 values of the + stack down, and replace the empty spot with NULL. 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.) + push WHY_SILENCED onto the stack. END_FINALLY will + then not re-raise the exception. (But non-local + gotos should still be resumed.) */ PyObject *exit_func; @@ -2544,7 +2547,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) stack_pointer[-7] = tb; stack_pointer[-6] = exc; stack_pointer[-5] = tp; + /* UNWIND_EXCEPT_BLOCK will pop this off. */ FOURTH() = NULL; + /* We just shifted the stack down, so we have + to tell the except handler block that the + values are lower than it expects. */ block = &f->f_blockstack[f->f_iblock - 1]; assert(block->b_type == EXCEPT_HANDLER); block->b_level--; -- cgit v1.2.1 From 3d33d96fe953038fa99e571aebd6e9fca27b74b0 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 28 Jun 2009 16:03:15 +0000 Subject: this is better written as an assertion --- Python/ceval.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index a42a66559b..3ca972a697 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1823,15 +1823,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) created when the exception was caught, otherwise the stack will be in an inconsistent state. */ PyTryBlock *b = PyFrame_BlockPop(f); - if (b->b_type != EXCEPT_HANDLER) { - PyErr_SetString(PyExc_SystemError, - "popped block is not an except handler"); - why = WHY_EXCEPTION; - } - else { - UNWIND_EXCEPT_HANDLER(b); - why = WHY_NOT; - } + assert(b->b_type == EXCEPT_HANDLER); + UNWIND_EXCEPT_HANDLER(b); + why = WHY_NOT; } } else if (PyExceptionClass_Check(v)) { -- cgit v1.2.1 From 07c154a20ea737e72e6d220c2f7ded37c0dcfdbe Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 28 Jun 2009 16:17:34 +0000 Subject: Merged revisions 73614-73615 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r73614 | benjamin.peterson | 2009-06-28 11:08:02 -0500 (Sun, 28 Jun 2009) | 1 line add two generic macros for peeking and setting in the stack ........ r73615 | benjamin.peterson | 2009-06-28 11:14:07 -0500 (Sun, 28 Jun 2009) | 1 line use stack macros ........ --- Python/ceval.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 3ca972a697..a5d465cff2 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -919,10 +919,12 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) #define SECOND() (stack_pointer[-2]) #define THIRD() (stack_pointer[-3]) #define FOURTH() (stack_pointer[-4]) +#define PEEK(n) (stack_pointer[-(n)]) #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 SET_VALUE(n, v) (stack_pointer[-(n)] = (v)) #define BASIC_STACKADJ(n) (stack_pointer += n) #define BASIC_PUSH(v) (*stack_pointer++ = (v)) #define BASIC_POP() (*--stack_pointer) @@ -1548,7 +1550,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) TARGET(LIST_APPEND) w = POP(); - v = stack_pointer[-oparg]; + v = PEEK(oparg); err = PyList_Append(v, w); Py_DECREF(w); if (err == 0) { @@ -1909,7 +1911,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) } } else if (unpack_iterable(v, oparg, -1, stack_pointer + oparg)) { - stack_pointer += oparg; + STACKADJ(oparg); } else { /* unpack_iterable() raised an exception */ why = WHY_EXCEPTION; -- cgit v1.2.1 From 42959ea2e970746e0b848efac8877a4a616159fa Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 28 Jun 2009 16:21:52 +0000 Subject: use stack altering macros here --- Python/ceval.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index a5d465cff2..6141c13d00 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2537,14 +2537,14 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) v = SECOND(); w = THIRD(); tp = FOURTH(); - exc = stack_pointer[-5]; - tb = stack_pointer[-6]; - exit_func = stack_pointer[-7]; - stack_pointer[-7] = tb; - stack_pointer[-6] = exc; - stack_pointer[-5] = tp; + exc = PEEK(5); + tb = PEEK(6); + exit_func = PEEK(7); + SET_VALUE(7, tb); + SET_VALUE(6, exc); + SET_VALUE(5, tp); /* UNWIND_EXCEPT_BLOCK will pop this off. */ - FOURTH() = NULL; + SET_FOURTH(NULL); /* We just shifted the stack down, so we have to tell the except handler block that the values are lower than it expects. */ -- cgit v1.2.1 From 4506d5bfb7ba4ce67acadb33e5b3ea4f18937be6 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 28 Jun 2009 17:22:03 +0000 Subject: Merged revisions 73004,73439,73496,73509,73529,73564,73576-73577,73595-73596,73605 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r73004 | jeffrey.yasskin | 2009-05-28 22:44:31 -0500 (Thu, 28 May 2009) | 5 lines Fix nearly all compilation warnings under Apple gcc-4.0. Tested with OPT="-g -Wall -Wstrict-prototypes -Werror" in both --with-pydebug mode and --without. There's still a batch of non-prototype warnings in Xlib.h that I don't know how to fix. ........ r73439 | benjamin.peterson | 2009-06-15 19:29:31 -0500 (Mon, 15 Jun 2009) | 1 line don't mask encoding errors when decoding a string #6289 ........ r73496 | vinay.sajip | 2009-06-21 12:37:27 -0500 (Sun, 21 Jun 2009) | 1 line Issue #6314: logging.basicConfig() performs extra checks on the "level" argument. ........ r73509 | amaury.forgeotdarc | 2009-06-22 14:33:48 -0500 (Mon, 22 Jun 2009) | 2 lines #4490 Fix sample code run by "python -m xml.sax.xmlreader" ........ r73529 | r.david.murray | 2009-06-23 13:02:46 -0500 (Tue, 23 Jun 2009) | 4 lines Fix issue 5230 by having pydoc's safeimport check to see if the import error was thrown from itself in order to decide if the module can't be found. Thanks to Lucas Prado Melo for collaborating on the fix and tests. ........ r73564 | amaury.forgeotdarc | 2009-06-25 17:29:29 -0500 (Thu, 25 Jun 2009) | 6 lines #2016 Fix a crash in function call when the **kwargs dictionary is mutated during the function call setup. This even gives a slight speedup, probably because tuple allocation is faster than PyMem_NEW. ........ r73576 | benjamin.peterson | 2009-06-26 18:37:06 -0500 (Fri, 26 Jun 2009) | 1 line document is_declared_global() ........ r73577 | benjamin.peterson | 2009-06-27 09:16:23 -0500 (Sat, 27 Jun 2009) | 1 line link to extensive generator docs in the reference manual ........ r73595 | ezio.melotti | 2009-06-27 18:45:39 -0500 (Sat, 27 Jun 2009) | 1 line stmt and setup can contain multiple statements, see #5896 ........ r73596 | ezio.melotti | 2009-06-27 19:07:45 -0500 (Sat, 27 Jun 2009) | 1 line Fixed a wrong apostrophe ........ r73605 | georg.brandl | 2009-06-28 07:10:18 -0500 (Sun, 28 Jun 2009) | 1 line Remove stray pychecker directive. ........ --- Python/compile.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'Python') diff --git a/Python/compile.c b/Python/compile.c index 490137f3db..f048743701 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -551,18 +551,6 @@ compiler_exit_scope(struct compiler *c) } -/* 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 PyUnicode_FromString(tmpname); -} - /* Allocate a new block and return a pointer to it. Returns NULL on error. */ -- cgit v1.2.1 From fdeceae09c9611b47d4b7b031b6b602c38913e88 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 28 Jun 2009 19:19:51 +0000 Subject: Merged revisions 73376,73393,73398,73400,73404-73405,73409,73419-73421,73432,73457,73460,73485-73486,73488-73489,73501-73502,73513-73514 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r73376 | benjamin.peterson | 2009-06-11 17:29:23 -0500 (Thu, 11 Jun 2009) | 1 line remove check for case handled in sub-function ........ r73393 | alexandre.vassalotti | 2009-06-12 13:56:57 -0500 (Fri, 12 Jun 2009) | 2 lines Clear reference to the static PyExc_RecursionErrorInst in _PyExc_Fini. ........ r73398 | alexandre.vassalotti | 2009-06-12 15:57:12 -0500 (Fri, 12 Jun 2009) | 3 lines Add const qualifier to PyErr_SetFromErrnoWithFilename and to PyErr_SetFromErrnoWithUnicodeFilename. ........ r73400 | alexandre.vassalotti | 2009-06-12 16:43:47 -0500 (Fri, 12 Jun 2009) | 2 lines Delete outdated make file for building the parser with MSVC 6. ........ r73404 | benjamin.peterson | 2009-06-12 20:40:00 -0500 (Fri, 12 Jun 2009) | 1 line keep the slice.step field as NULL if no step expression is given ........ r73405 | benjamin.peterson | 2009-06-12 22:46:30 -0500 (Fri, 12 Jun 2009) | 1 line prevent import statements from assigning to None ........ r73409 | benjamin.peterson | 2009-06-13 08:06:21 -0500 (Sat, 13 Jun 2009) | 1 line allow importing from a module named None if it has an 'as' clause ........ r73419 | benjamin.peterson | 2009-06-13 11:19:19 -0500 (Sat, 13 Jun 2009) | 1 line set Print.values to NULL if there are no values ........ r73420 | benjamin.peterson | 2009-06-13 12:08:53 -0500 (Sat, 13 Jun 2009) | 1 line give a better error message when deleting () ........ r73421 | benjamin.peterson | 2009-06-13 15:23:33 -0500 (Sat, 13 Jun 2009) | 1 line when no module is given in a 'from' relative import, make ImportFrom.module NULL ........ r73432 | amaury.forgeotdarc | 2009-06-14 16:20:40 -0500 (Sun, 14 Jun 2009) | 3 lines #6227: Because of a wrong indentation, the test was not testing what it should. Ensure that the snippet in doctest_aliases actually contains aliases. ........ r73457 | benjamin.peterson | 2009-06-16 18:13:09 -0500 (Tue, 16 Jun 2009) | 1 line add underscores ........ r73460 | benjamin.peterson | 2009-06-16 22:23:04 -0500 (Tue, 16 Jun 2009) | 1 line remove unused 'encoding' member from the compiler struct ........ r73485 | benjamin.peterson | 2009-06-19 17:07:47 -0500 (Fri, 19 Jun 2009) | 1 line remove duplicate test ........ r73486 | benjamin.peterson | 2009-06-19 17:09:17 -0500 (Fri, 19 Jun 2009) | 1 line add missing assertion #6313 ........ r73488 | benjamin.peterson | 2009-06-19 17:16:28 -0500 (Fri, 19 Jun 2009) | 1 line show that this one isn't used ........ r73489 | benjamin.peterson | 2009-06-19 17:21:12 -0500 (Fri, 19 Jun 2009) | 1 line use closures ........ r73501 | benjamin.peterson | 2009-06-21 18:01:07 -0500 (Sun, 21 Jun 2009) | 1 line don't need to add the name 'lambda' as assigned ........ r73502 | benjamin.peterson | 2009-06-21 18:03:36 -0500 (Sun, 21 Jun 2009) | 1 line remove tmpname support since it's no longer used ........ r73513 | benjamin.peterson | 2009-06-22 20:18:57 -0500 (Mon, 22 Jun 2009) | 1 line fix grammar ........ r73514 | benjamin.peterson | 2009-06-22 22:01:56 -0500 (Mon, 22 Jun 2009) | 1 line remove some unused symtable constants ........ --- Python/Python-ast.c | 8 +----- Python/ast.c | 82 ++++++++++++++++++++++++++++++----------------------- Python/compile.c | 34 +++++++++++----------- Python/symtable.c | 10 +------ 4 files changed, 67 insertions(+), 67 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 1e85b2fac7..e9bd849495 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -1332,11 +1332,6 @@ 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) return NULL; @@ -4465,8 +4460,7 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) Py_XDECREF(tmp); tmp = NULL; } else { - PyErr_SetString(PyExc_TypeError, "required field \"module\" missing from ImportFrom"); - return 1; + module = NULL; } if (PyObject_HasAttrString(obj, "names")) { int res; diff --git a/Python/ast.c b/Python/ast.c index 83572ee882..d81f001646 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -362,12 +362,12 @@ static const char* FORBIDDEN[] = { }; static int -forbidden_name(expr_ty e, const node *n) +forbidden_name(identifier name, const node *n) { const char **p; - assert(PyUnicode_Check(e->v.Name.id)); + assert(PyUnicode_Check(name)); for (p = FORBIDDEN; *p; p++) { - if (PyUnicode_CompareWithASCIIString(e->v.Name.id, *p) == 0) { + if (PyUnicode_CompareWithASCIIString(name, *p) == 0) { ast_error(n, "assignment to keyword"); return 1; } @@ -414,7 +414,7 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n) break; case Name_kind: if (ctx == Store) { - if (forbidden_name(e, n)) + if (forbidden_name(e->v.Name.id, n)) return 0; /* forbidden_name() calls ast_error() */ } e->v.Name.ctx = ctx; @@ -424,10 +424,13 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n) 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; + if (asdl_seq_LEN(e->v.Tuple.elts)) { + e->v.Tuple.ctx = ctx; + s = e->v.Tuple.elts; + } + else { + expr_name = "()"; + } break; case Lambda_kind: expr_name = "lambda"; @@ -1378,7 +1381,7 @@ ast_for_atom(struct compiling *c, const node *n) /* testlist_comp: test ( comp_for | (',' test)* [','] ) */ if ((NCH(ch) > 1) && (TYPE(CHILD(ch, 1)) == comp_for)) return ast_for_genexp(c, ch); - + return ast_for_testlist(c, ch); case LSQB: /* list (or list comprehension) */ ch = CHILD(n, 1); @@ -1513,14 +1516,7 @@ ast_for_slice(struct compiling *c, const node *n) 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 { + if (NCH(ch) != 1) { ch = CHILD(ch, 1); if (TYPE(ch) == test) { step = ast_for_expr(c, ch); @@ -2014,7 +2010,7 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func) } else if (e->kind != Name_kind) { ast_error(CHILD(ch, 0), "keyword can't be an expression"); return NULL; - } else if (forbidden_name(e, ch)) { + } else if (forbidden_name(e->v.Name.id, ch)) { return NULL; } key = e->v.Name.id; @@ -2160,6 +2156,7 @@ ast_for_expr_stmt(struct compiling *c, const node *n) } } + static asdl_seq * ast_for_exprlist(struct compiling *c, const node *n, expr_context_ty context) { @@ -2260,49 +2257,64 @@ ast_for_flow_stmt(struct compiling *c, const node *n) } static alias_ty -alias_for_import_name(struct compiling *c, const node *n) +alias_for_import_name(struct compiling *c, const node *n, int store) { /* import_as_name: NAME ['as' NAME] dotted_as_name: dotted_name ['as' NAME] dotted_name: NAME ('.' NAME)* */ - PyObject *str, *name; + identifier str, name; loop: switch (TYPE(n)) { - case import_as_name: + case import_as_name: { + node *name_node = CHILD(n, 0); str = NULL; + name = NEW_IDENTIFIER(name_node); + if (!name) + return NULL; if (NCH(n) == 3) { - str = NEW_IDENTIFIER(CHILD(n, 2)); + node *str_node = CHILD(n, 2); + str = NEW_IDENTIFIER(str_node); if (!str) return NULL; + if (store && forbidden_name(str, str_node)) + return NULL; + } + else { + if (forbidden_name(name, name_node)) + return NULL; } - name = NEW_IDENTIFIER(CHILD(n, 0)); - if (!name) - return NULL; return alias(name, 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)); + node *asname_node = CHILD(n, 2); + alias_ty a = alias_for_import_name(c, CHILD(n, 0), 0); if (!a) return NULL; assert(!a->asname); - a->asname = NEW_IDENTIFIER(CHILD(n, 2)); + a->asname = NEW_IDENTIFIER(asname_node); if (!a->asname) return NULL; + if (forbidden_name(a->asname, asname_node)) + return NULL; return a; } break; case dotted_name: if (NCH(n) == 1) { - name = NEW_IDENTIFIER(CHILD(n, 0)); + node *name_node = CHILD(n, 0); + name = NEW_IDENTIFIER(name_node); if (!name) return NULL; + if (store && forbidden_name(name, name_node)) + return NULL; return alias(name, NULL, c->c_arena); } else { @@ -2382,7 +2394,7 @@ ast_for_import_stmt(struct compiling *c, const node *n) if (!aliases) return NULL; for (i = 0; i < NCH(n); i += 2) { - alias_ty import_alias = alias_for_import_name(c, CHILD(n, i)); + alias_ty import_alias = alias_for_import_name(c, CHILD(n, i), 1); if (!import_alias) return NULL; asdl_seq_SET(aliases, i / 2, import_alias); @@ -2393,13 +2405,15 @@ ast_for_import_stmt(struct compiling *c, const node *n) int n_children; int idx, ndots = 0; alias_ty mod = NULL; - identifier modname; + identifier modname = NULL; /* Count the number of dots (for relative imports) and check for the optional module name */ for (idx = 1; idx < NCH(n); idx++) { if (TYPE(CHILD(n, idx)) == dotted_name) { - mod = alias_for_import_name(c, CHILD(n, idx)); + mod = alias_for_import_name(c, CHILD(n, idx), 0); + if (!mod) + return NULL; idx++; break; } else if (TYPE(CHILD(n, idx)) == ELLIPSIS) { @@ -2444,14 +2458,14 @@ ast_for_import_stmt(struct compiling *c, const node *n) /* handle "from ... import *" special b/c there's no children */ if (TYPE(n) == STAR) { - alias_ty import_alias = alias_for_import_name(c, n); + alias_ty import_alias = alias_for_import_name(c, n, 1); 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)); + alias_ty import_alias = alias_for_import_name(c, CHILD(n, i), 1); if (!import_alias) return NULL; asdl_seq_SET(aliases, i / 2, import_alias); @@ -2459,8 +2473,6 @@ ast_for_import_stmt(struct compiling *c, const node *n) } if (mod != NULL) modname = mod->name; - else - modname = new_identifier("", c->c_arena); return ImportFrom(modname, aliases, ndots, lineno, col_offset, c->c_arena); } diff --git a/Python/compile.c b/Python/compile.c index f048743701..787dfe37d0 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -117,7 +117,6 @@ struct compiler_unit { 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]; @@ -146,7 +145,6 @@ struct compiler { 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 */ }; @@ -295,9 +293,6 @@ PyAST_Compile(mod_ty mod, const char *filename, PyCompilerFlags *flags, goto finally; } - /* XXX initialize to NULL for now, need to handle */ - c.c_encoding = NULL; - co = compiler_mod(&c, mod); finally: @@ -488,7 +483,6 @@ compiler_enter_scope(struct compiler *c, identifier name, void *key, } u->u_blocks = NULL; - u->u_tmpname = 0; u->u_nfblocks = 0; u->u_firstlineno = lineno; u->u_lineno = 0; @@ -2154,6 +2148,13 @@ compiler_from_import(struct compiler *c, stmt_ty s) PyObject *names = PyTuple_New(n); PyObject *level; + static PyObject *empty_string; + + if (!empty_string) { + empty_string = PyUnicode_FromString(""); + if (!empty_string) + return 0; + } if (!names) return 0; @@ -2171,23 +2172,24 @@ compiler_from_import(struct compiler *c, stmt_ty s) PyTuple_SET_ITEM(names, i, alias->name); } - if (s->lineno > c->c_future->ff_lineno) { - if (!PyUnicode_CompareWithASCIIString(s->v.ImportFrom.module, - "__future__")) { - Py_DECREF(level); - Py_DECREF(names); - return compiler_error(c, - "from __future__ imports must occur " + if (s->lineno > c->c_future->ff_lineno && s->v.ImportFrom.module && + !PyUnicode_CompareWithASCIIString(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); + if (s->v.ImportFrom.module) { + ADDOP_NAME(c, IMPORT_NAME, s->v.ImportFrom.module, names); + } + else { + ADDOP_NAME(c, IMPORT_NAME, empty_string, names); + } for (i = 0; i < n; i++) { alias_ty alias = (alias_ty)asdl_seq_GET(s->v.ImportFrom.names, i); identifier store_name; diff --git a/Python/symtable.c b/Python/symtable.c index f10e38211b..e0e63daa09 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -38,7 +38,6 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block, goto fail; ste->ste_table = st; ste->ste_id = k; - ste->ste_tmpname = 0; ste->ste_name = name; Py_INCREF(name); @@ -66,7 +65,6 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block, 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 && @@ -1099,7 +1097,6 @@ symtable_new_tmpname(struct symtable *st) } - static int symtable_visit_stmt(struct symtable *st, stmt_ty s) { @@ -1297,12 +1294,8 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) /* 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); @@ -1326,8 +1319,7 @@ symtable_visit_expr(struct symtable *st, expr_ty e) VISIT(st, expr, e->v.UnaryOp.operand); break; case Lambda_kind: { - if (!GET_IDENTIFIER(lambda) || - !symtable_add_def(st, lambda, DEF_LOCAL)) + if (!GET_IDENTIFIER(lambda)) return 0; if (e->v.Lambda.args->defaults) VISIT_SEQ(st, expr, e->v.Lambda.args->defaults); -- cgit v1.2.1 From 4982735db43513c8a18b7bfbbf936054ad32ccec Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 28 Jun 2009 23:32:44 +0000 Subject: In most cases, the parser will protect True, False, and None from being assign to. We must check for __debug__ in all cases. --- Python/ast.c | 51 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 13 deletions(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index d81f001646..8a1edd2f10 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -357,19 +357,24 @@ static const char* FORBIDDEN[] = { "None", "True", "False", - "__debug__", NULL, }; static int -forbidden_name(identifier name, const node *n) +forbidden_name(identifier name, const node *n, int full_checks) { - const char **p; assert(PyUnicode_Check(name)); - for (p = FORBIDDEN; *p; p++) { - if (PyUnicode_CompareWithASCIIString(name, *p) == 0) { - ast_error(n, "assignment to keyword"); - return 1; + if (PyUnicode_CompareWithASCIIString(name, "__debug__") == 0) { + ast_error(n, "assignment to keyword"); + return 1; + } + if (full_checks) { + const char **p; + for (p = FORBIDDEN; *p; p++) { + if (PyUnicode_CompareWithASCIIString(name, *p) == 0) { + ast_error(n, "assignment to keyword"); + return 1; + } } } return 0; @@ -403,6 +408,8 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n) switch (e->kind) { case Attribute_kind: e->v.Attribute.ctx = ctx; + if (ctx == Store && forbidden_name(e->v.Attribute.attr, n, 1)) + return 0; break; case Subscript_kind: e->v.Subscript.ctx = ctx; @@ -414,7 +421,7 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n) break; case Name_kind: if (ctx == Store) { - if (forbidden_name(e->v.Name.id, n)) + if (forbidden_name(e->v.Name.id, n, 1)) return 0; /* forbidden_name() calls ast_error() */ } e->v.Name.ctx = ctx; @@ -631,6 +638,8 @@ compiler_arg(struct compiling *c, const node *n) name = NEW_IDENTIFIER(ch); if (!name) return NULL; + if (forbidden_name(name, ch, 0)) + return NULL; if (NCH(n) == 3 && TYPE(CHILD(n, 1)) == COLON) { annotation = ast_for_expr(c, CHILD(n, 2)); @@ -697,6 +706,8 @@ handle_keywordonly_args(struct compiling *c, const node *n, int start, argname = NEW_IDENTIFIER(ch); if (!argname) goto error; + if (forbidden_name(argname, ch, 0)) + goto error; arg = arg(argname, annotation, c->c_arena); if (!arg) goto error; @@ -855,6 +866,8 @@ ast_for_arguments(struct compiling *c, const node *n) vararg = NEW_IDENTIFIER(CHILD(ch, 0)); if (!vararg) return NULL; + if (forbidden_name(vararg, CHILD(ch, 0), 0)) + return NULL; if (NCH(ch) > 1) { /* there is an annotation on the vararg */ varargannotation = ast_for_expr(c, CHILD(ch, 2)); @@ -880,6 +893,8 @@ ast_for_arguments(struct compiling *c, const node *n) } if (!kwarg) goto error; + if (forbidden_name(kwarg, CHILD(ch, 0), 0)) + goto error; i += 3; break; default: @@ -1001,6 +1016,8 @@ ast_for_funcdef(struct compiling *c, const node *n, asdl_seq *decorator_seq) name = NEW_IDENTIFIER(CHILD(n, name_i)); if (!name) return NULL; + if (forbidden_name(name, CHILD(n, name_i), 0)) + return NULL; args = ast_for_arguments(c, CHILD(n, name_i + 1)); if (!args) return NULL; @@ -2010,7 +2027,7 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func) } else if (e->kind != Name_kind) { ast_error(CHILD(ch, 0), "keyword can't be an expression"); return NULL; - } else if (forbidden_name(e->v.Name.id, ch)) { + } else if (forbidden_name(e->v.Name.id, ch, 1)) { return NULL; } key = e->v.Name.id; @@ -2279,11 +2296,11 @@ alias_for_import_name(struct compiling *c, const node *n, int store) str = NEW_IDENTIFIER(str_node); if (!str) return NULL; - if (store && forbidden_name(str, str_node)) + if (store && forbidden_name(str, str_node, 0)) return NULL; } else { - if (forbidden_name(name, name_node)) + if (forbidden_name(name, name_node, 0)) return NULL; } return alias(name, str, c->c_arena); @@ -2302,7 +2319,7 @@ alias_for_import_name(struct compiling *c, const node *n, int store) a->asname = NEW_IDENTIFIER(asname_node); if (!a->asname) return NULL; - if (forbidden_name(a->asname, asname_node)) + if (forbidden_name(a->asname, asname_node, 0)) return NULL; return a; } @@ -2313,7 +2330,7 @@ alias_for_import_name(struct compiling *c, const node *n, int store) name = NEW_IDENTIFIER(name_node); if (!name) return NULL; - if (store && forbidden_name(name, name_node)) + if (store && forbidden_name(name, name_node, 0)) return NULL; return alias(name, NULL, c->c_arena); } @@ -2853,6 +2870,8 @@ ast_for_except_clause(struct compiling *c, const node *exc, node *body) identifier e = NEW_IDENTIFIER(CHILD(exc, 3)); if (!e) return NULL; + if (forbidden_name(e, CHILD(exc, 3), 0)) + return NULL; expression = ast_for_expr(c, CHILD(exc, 1)); if (!expression) return NULL; @@ -3023,6 +3042,8 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq) classname = NEW_IDENTIFIER(CHILD(n, 1)); if (!classname) return NULL; + if (forbidden_name(classname, CHILD(n, 3), 0)) + return NULL; return ClassDef(classname, NULL, NULL, NULL, NULL, s, decorator_seq, LINENO(n), n->n_col_offset, c->c_arena); } @@ -3034,6 +3055,8 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq) classname = NEW_IDENTIFIER(CHILD(n, 1)); if (!classname) return NULL; + if (forbidden_name(classname, CHILD(n, 3), 0)) + return NULL; return ClassDef(classname, NULL, NULL, NULL, NULL, s, decorator_seq, LINENO(n), n->n_col_offset, c->c_arena); } @@ -3057,6 +3080,8 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq) classname = NEW_IDENTIFIER(CHILD(n, 1)); if (!classname) return NULL; + if (forbidden_name(classname, CHILD(n, 1), 0)) + return NULL; return ClassDef(classname, call->v.Call.args, call->v.Call.keywords, call->v.Call.starargs, call->v.Call.kwargs, s, -- cgit v1.2.1 From 97901d57c052fa9a74de911a7637f4da03e07f0e Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Thu, 2 Jul 2009 18:25:26 +0000 Subject: refactor logic a little when no sep or end is passed --- Python/bltinmodule.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index c33a37ea13..2224d3722f 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1459,13 +1459,19 @@ builtin_print(PyObject *self, PyObject *args, PyObject *kwds) Py_RETURN_NONE; } - if (sep && sep != Py_None && !PyUnicode_Check(sep)) { + if (sep == Py_None) { + sep = NULL; + } + else if (sep && !PyUnicode_Check(sep)) { PyErr_Format(PyExc_TypeError, "sep must be None or a string, not %.200s", sep->ob_type->tp_name); return NULL; } - if (end && end != Py_None && !PyUnicode_Check(end)) { + if (end == Py_None) { + end = NULL; + } + else if (end && !PyUnicode_Check(end)) { PyErr_Format(PyExc_TypeError, "end must be None or a string, not %.200s", end->ob_type->tp_name); @@ -1474,7 +1480,7 @@ builtin_print(PyObject *self, PyObject *args, PyObject *kwds) for (i = 0; i < PyTuple_Size(args); i++) { if (i > 0) { - if (sep == NULL || sep == Py_None) + if (sep == NULL) err = PyFile_WriteString(" ", file); else err = PyFile_WriteObject(sep, file, @@ -1488,7 +1494,7 @@ builtin_print(PyObject *self, PyObject *args, PyObject *kwds) return NULL; } - if (end == NULL || end == Py_None) + if (end == NULL) err = PyFile_WriteString("\n", file); else err = PyFile_WriteObject(end, file, Py_PRINT_RAW); -- cgit v1.2.1 From ed1bf688474c3d90ad665d30f677042a2feecb66 Mon Sep 17 00:00:00 2001 From: Hirokazu Yamamoto Date: Fri, 17 Jul 2009 06:55:42 +0000 Subject: Merged revisions 74040,74042 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r74040 | hirokazu.yamamoto | 2009-07-17 15:20:46 +0900 | 1 line Issue #6415: Fixed warnings.warn sagfault on bad formatted string. ........ r74042 | hirokazu.yamamoto | 2009-07-17 15:26:54 +0900 | 1 line NEWS about r74040. ........ --- Python/_warnings.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Python') diff --git a/Python/_warnings.c b/Python/_warnings.c index da52e357c3..ef7f373bdd 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -320,6 +320,8 @@ warn_explicit(PyObject *category, PyObject *message, } if (rc == 1) { text = PyObject_Str(message); + if (text == NULL) + goto cleanup; category = (PyObject*)message->ob_type; } else { -- cgit v1.2.1 From d47c8132c8b9a1284b890988608a4b3bd51c8ecc Mon Sep 17 00:00:00 2001 From: Alexandre Vassalotti Date: Fri, 17 Jul 2009 10:55:50 +0000 Subject: Merged revisions 73870,73879,73899-73900,73905-73906 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r73870 | r.david.murray | 2009-07-06 21:06:13 -0400 (Mon, 06 Jul 2009) | 5 lines Issue 6070: when creating a compiled file, after copying the mode bits, on posix zap the execute bit in case it was set on the .py file, since the compiled files are not directly executable on posix. Patch by Marco N. ........ r73879 | r.david.murray | 2009-07-07 05:54:16 -0400 (Tue, 07 Jul 2009) | 3 lines Update issue 6070 patch to match the patch that was actually tested on Windows. ........ r73899 | r.david.murray | 2009-07-08 21:43:41 -0400 (Wed, 08 Jul 2009) | 3 lines Conditionalize test cleanup code to eliminate traceback, which will hopefully reveal the real problem. ........ r73900 | r.david.murray | 2009-07-08 22:06:17 -0400 (Wed, 08 Jul 2009) | 2 lines Make test work with -O. ........ r73905 | r.david.murray | 2009-07-09 09:55:44 -0400 (Thu, 09 Jul 2009) | 3 lines Specify umask in execute bit test to get consistent results and make sure we test resetting all three execute bits. ........ r73906 | r.david.murray | 2009-07-09 11:35:33 -0400 (Thu, 09 Jul 2009) | 5 lines Curdir needs to be in the path for the test to work on all buildbots. (I copied this from another import test, but currently this will fail if TESTFN ends up in /tmp...see issue 2609). ........ --- Python/import.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 23dd7b4d08..0d50f5bddb 100644 --- a/Python/import.c +++ b/Python/import.c @@ -931,7 +931,11 @@ write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat) { FILE *fp; time_t mtime = srcstat->st_mtime; - mode_t mode = srcstat->st_mode; +#ifdef MS_WINDOWS /* since Windows uses different permissions */ + mode_t mode = srcstat->st_mode & ~S_IEXEC; +#else + mode_t mode = srcstat->st_mode & ~S_IXUSR & ~S_IXGRP & ~S_IXOTH; +#endif fp = open_exclusive(cpathname, mode); if (fp == NULL) { -- cgit v1.2.1 From c777324f993bdc6948434758ef64650d6b4fa8b8 Mon Sep 17 00:00:00 2001 From: Alexandre Vassalotti Date: Fri, 17 Jul 2009 11:43:26 +0000 Subject: Merged revisions 73665,73693,73704-73705,73707,73712-73713,73824 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r73665 | alexandre.vassalotti | 2009-06-28 21:01:51 -0400 (Sun, 28 Jun 2009) | 2 lines Update docstrings for sys.getdlopenflags() and sys.setdlopenflags(). ........ r73693 | jesse.noller | 2009-06-29 14:20:34 -0400 (Mon, 29 Jun 2009) | 1 line Bug 5906: add a documentation note for unix daemons vs. multiprocessing daemons ........ r73704 | georg.brandl | 2009-06-30 12:15:43 -0400 (Tue, 30 Jun 2009) | 1 line #6376: fix copy-n-paste oversight. ........ r73705 | georg.brandl | 2009-06-30 12:17:28 -0400 (Tue, 30 Jun 2009) | 1 line #6374: add a bit of explanation about shell=True on Windows. ........ r73707 | georg.brandl | 2009-06-30 12:35:11 -0400 (Tue, 30 Jun 2009) | 1 line #6371: fix link targets. ........ r73712 | ezio.melotti | 2009-06-30 18:51:06 -0400 (Tue, 30 Jun 2009) | 1 line Fixed defaultTestCase -> defaultTestResult ........ r73713 | ezio.melotti | 2009-06-30 18:56:16 -0400 (Tue, 30 Jun 2009) | 1 line Fixed a backslash that was not supposed to be there ........ r73824 | ezio.melotti | 2009-07-03 21:18:08 -0400 (Fri, 03 Jul 2009) | 1 line #6398 typo: versio. -> version. ........ --- Python/sysmodule.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 89613ecbc2..fa39480e8c 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -586,12 +586,14 @@ sys_setdlopenflags(PyObject *self, PyObject *args) 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)" -); +Set the flags used by the interpreter for dlopen calls, such as when the\n\ +interpreter loads extension modules. Among other things, this will enable\n\ +a lazy resolving of symbols when importing a module, if called as\n\ +sys.setdlopenflags(0). To share symbols across extension modules, call as\n\ +sys.setdlopenflags(ctypes.RTLD_GLOBAL). Symbolic names for the flag modules\n\ +can be either found in the ctypes module, or in the DLFCN module. If DLFCN\n\ +is not available, it can be generated from /usr/include/dlfcn.h using the\n\ +h2py script."); static PyObject * sys_getdlopenflags(PyObject *self, PyObject *args) @@ -605,10 +607,10 @@ sys_getdlopenflags(PyObject *self, PyObject *args) 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 +Return the current value of the flags that are used for dlopen calls.\n\ +The flag constants are defined in the ctypes and DLFCN modules."); + +#endif /* HAVE_DLOPEN */ #ifdef USE_MALLOPT /* Link with -lmalloc (or -lmpc) on an SGI */ -- cgit v1.2.1 From 1316f79d980701193356be7a5978f02c402b5b51 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 17 Jul 2009 19:11:02 +0000 Subject: update ast version --- Python/Python-ast.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index e9bd849495..e03dac0bb5 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -2,7 +2,7 @@ /* - __version__ 67616. + __version__ 73626. This module must be committed separately after each AST grammar change; The __version__ number is set to the revision number of the commit @@ -6411,7 +6411,7 @@ PyInit__ast(void) NULL; if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0) return NULL; - if (PyModule_AddStringConstant(m, "__version__", "67616") < 0) + if (PyModule_AddStringConstant(m, "__version__", "73626") < 0) return NULL; if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return NULL; -- cgit v1.2.1 From 4002bcf6d0a51bff1bd8ad8e252b17e4c4856019 Mon Sep 17 00:00:00 2001 From: Alexandre Vassalotti Date: Tue, 21 Jul 2009 02:51:58 +0000 Subject: Merged revisions 73683,73786 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r73683 | georg.brandl | 2009-06-29 10:44:49 -0400 (Mon, 29 Jun 2009) | 1 line Fix error handling in PyCode_Optimize, by Alexander Schremmer at EuroPython sprint. ........ r73786 | benjamin.peterson | 2009-07-02 18:56:16 -0400 (Thu, 02 Jul 2009) | 1 line condense with assertRaises ........ --- Python/peephole.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'Python') diff --git a/Python/peephole.c b/Python/peephole.c index 23735b0a31..9163091272 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -330,7 +330,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, /* Bail out if an exception is set */ if (PyErr_Occurred()) - goto exitUnchanged; + goto exitError; /* Bypass optimization when the lineno table is too complex */ assert(PyBytes_Check(lineno_obj)); @@ -348,7 +348,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, /* Make a modifiable copy of the code string */ codestr = (unsigned char *)PyMem_Malloc(codelen); if (codestr == NULL) - goto exitUnchanged; + goto exitError; codestr = (unsigned char *)memcpy(codestr, PyBytes_AS_STRING(code), codelen); @@ -363,11 +363,11 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, /* Mapping to new jump targets after NOPs are removed */ addrmap = (int *)PyMem_Malloc(codelen * sizeof(int)); if (addrmap == NULL) - goto exitUnchanged; + goto exitError; blocks = markblocks(codestr, codelen); if (blocks == NULL) - goto exitUnchanged; + goto exitError; assert(PyList_Check(consts)); for (i=0 ; i Date: Tue, 21 Jul 2009 04:30:03 +0000 Subject: Merged revisions 72487-72488,72879 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r72487 | jeffrey.yasskin | 2009-05-08 17:51:06 -0400 (Fri, 08 May 2009) | 7 lines PyCode_NewEmpty: Most uses of PyCode_New found by http://www.google.com/codesearch?q=PyCode_New are trying to build an empty code object, usually to put it in a dummy frame object. This patch adds a PyCode_NewEmpty wrapper which lets the user specify just the filename, function name, and first line number, instead of also requiring lots of code internals. ........ r72488 | jeffrey.yasskin | 2009-05-08 18:23:21 -0400 (Fri, 08 May 2009) | 13 lines Issue 5954, PyFrame_GetLineNumber: Most uses of PyCode_Addr2Line (http://www.google.com/codesearch?q=PyCode_Addr2Line) are just trying to get the line number of a specified frame, but there's no way to do that directly. Forcing people to go through the code object makes them know more about the guts of the interpreter than they should need. The remaining uses of PyCode_Addr2Line seem to be getting the line from a traceback (for example, http://www.google.com/codesearch/p?hl=en#u_9_nDrchrw/pygame-1.7.1release/src/base.c&q=PyCode_Addr2Line), which is replaced by the tb_lineno field. So we may be able to deprecate PyCode_Addr2Line entirely for external use. ........ r72879 | jeffrey.yasskin | 2009-05-23 19:23:01 -0400 (Sat, 23 May 2009) | 14 lines Issue #6042: lnotab-based tracing is very complicated and isn't documented very well. There were at least 3 comment blocks purporting to document co_lnotab, and none did a very good job. This patch unifies them into Objects/lnotab_notes.txt which tries to completely capture the current state of affairs. I also discovered that we've attached 2 layers of patches to the basic tracing scheme. The first layer avoids jumping to instructions that don't start a line, to avoid problems in if statements and while loops. The second layer discovered that jumps backward do need to trace at instructions that don't start a line, so it added extra lnotab entries for 'while' and 'for' loops, and added a special case for backward jumps within the same line. I replaced these patches by just treating forward and backward jumps differently. ........ --- Python/_warnings.c | 2 +- Python/ceval.c | 27 ++++++++++++--------------- Python/compile.c | 54 +++--------------------------------------------------- Python/traceback.c | 3 +-- 4 files changed, 17 insertions(+), 69 deletions(-) (limited to 'Python') diff --git a/Python/_warnings.c b/Python/_warnings.c index ef7f373bdd..35a840e3b4 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -462,7 +462,7 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, } else { globals = f->f_globals; - *lineno = PyCode_Addr2Line(f->f_code, f->f_lasti); + *lineno = PyFrame_GetLineNumber(f); } *module = NULL; diff --git a/Python/ceval.c b/Python/ceval.c index 6141c13d00..403acd2513 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2761,7 +2761,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) default: fprintf(stderr, "XXX lineno: %d, opcode: %d\n", - PyCode_Addr2Line(f->f_code, f->f_lasti), + PyFrame_GetLineNumber(f), opcode); PyErr_SetString(PyExc_SystemError, "unknown opcode"); why = WHY_EXCEPTION; @@ -3522,33 +3522,30 @@ _PyEval_CallTracing(PyObject *func, PyObject *args) return result; } +/* See Objects/lnotab_notes.txt for a description of how tracing works. */ 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; + int line = frame->f_lineno; /* 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. + instruction window, reset the window. */ - if ((frame->f_lasti < *instr_lb || frame->f_lasti >= *instr_ub)) { - int line; + if (frame->f_lasti < *instr_lb || frame->f_lasti >= *instr_ub) { 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); - } + line = _PyCode_CheckLineNumber(frame->f_code, frame->f_lasti, + &bounds); *instr_lb = bounds.ap_lower; *instr_ub = bounds.ap_upper; } - else if (frame->f_lasti <= *instr_prev) { + /* If the last instruction falls at the start of a line or if + it represents a jump backwards, update the frame's line + number and call the trace function. */ + if (frame->f_lasti == *instr_lb || frame->f_lasti < *instr_prev) { + frame->f_lineno = line; result = call_trace(func, obj, frame, PyTrace_LINE, Py_None); } *instr_prev = frame->f_lasti; diff --git a/Python/compile.c b/Python/compile.c index 787dfe37d0..24975b64a7 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1748,9 +1748,6 @@ compiler_for(struct compiler *c, stmt_ty s) VISIT(c, expr, s->v.For.iter); ADDOP(c, GET_ITER); compiler_use_next_block(c, start); - /* for expressions must be traced on each iteration, - so we need to set an extra line number. */ - c->u->u_lineno_set = 0; ADDOP_JREL(c, FOR_ITER, cleanup); VISIT(c, expr, s->v.For.target); VISIT_SEQ(c, stmt, s->v.For.body); @@ -1796,9 +1793,6 @@ compiler_while(struct compiler *c, stmt_ty s) if (!compiler_push_fblock(c, LOOP, loop)) return 0; if (constant == -1) { - /* while expressions must be traced on each iteration, - so we need to set an extra line number. */ - c->u->u_lineno_set = 0; VISIT(c, expr, s->v.While.test); ADDOP_JABS(c, POP_JUMP_IF_FALSE, anchor); } @@ -3654,51 +3648,9 @@ blocksize(basicblock *b) 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. -*/ +/* Appends a pair to the end of the line number table, a_lnotab, representing + the instruction's bytecode offset and line number. See + Objects/lnotab_notes.txt for the description of the line number table. */ static int assemble_lnotab(struct assembler *a, struct instr *i) diff --git a/Python/traceback.c b/Python/traceback.c index e77b1b282f..1de2df6f5d 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -114,8 +114,7 @@ newtracebackobject(PyTracebackObject *next, PyFrameObject *frame) Py_XINCREF(frame); tb->tb_frame = frame; tb->tb_lasti = frame->f_lasti; - tb->tb_lineno = PyCode_Addr2Line(frame->f_code, - frame->f_lasti); + tb->tb_lineno = PyFrame_GetLineNumber(frame); PyObject_GC_Track(tb); } return tb; -- cgit v1.2.1 From 0b284f70b647fab16ccb4cf7ae3ff88db3b6f99e Mon Sep 17 00:00:00 2001 From: Alexandre Vassalotti Date: Tue, 21 Jul 2009 05:23:51 +0000 Subject: Merged revisions 73750 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r73750 | benjamin.peterson | 2009-07-01 19:45:19 -0400 (Wed, 01 Jul 2009) | 1 line small optimization: avoid popping the current block until we have to ........ --- Python/ceval.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 403acd2513..003d4dfd17 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2839,19 +2839,18 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) fast_block_end: while (why != WHY_NOT && f->f_iblock > 0) { - PyTryBlock *b = PyFrame_BlockPop(f); + /* Peek at the current block. */ + PyTryBlock *b = &f->f_blockstack[f->f_iblock - 1]; 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(PyLong_AS_LONG(retval)); Py_DECREF(retval); break; } + /* Now we have to pop the block. */ + f->f_iblock--; if (b->b_type == EXCEPT_HANDLER) { UNWIND_EXCEPT_HANDLER(b); -- cgit v1.2.1 From 6a33815340f756838f181b8b8d0b33b0f3314037 Mon Sep 17 00:00:00 2001 From: Alexandre Vassalotti Date: Wed, 29 Jul 2009 20:12:15 +0000 Subject: Merged revisions 74075,74187,74197,74201,74216,74225 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r74075 | georg.brandl | 2009-07-18 05:06:31 -0400 (Sat, 18 Jul 2009) | 1 line #6505: fix typos. ........ r74187 | benjamin.peterson | 2009-07-23 10:19:08 -0400 (Thu, 23 Jul 2009) | 1 line use bools for autoraise ........ r74197 | benjamin.peterson | 2009-07-24 22:03:48 -0400 (Fri, 24 Jul 2009) | 1 line clarify ........ r74201 | amaury.forgeotdarc | 2009-07-25 12:22:06 -0400 (Sat, 25 Jul 2009) | 2 lines Better name a variable: 'buf' seems to imply a mutable buffer. ........ r74216 | michael.foord | 2009-07-26 17:12:14 -0400 (Sun, 26 Jul 2009) | 1 line Issue 6581. Michael Foord ........ r74225 | kurt.kaiser | 2009-07-27 12:09:28 -0400 (Mon, 27 Jul 2009) | 5 lines 1. Clean workspace more thoughly before build. 2. Add url of branch we are building to 'results' webpage. (url is now available in $repo_path, could be added to failure email.) 3. Adjust permissions to improve upload reliability. ........ --- Python/import.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 0d50f5bddb..2ae5fa7f6f 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1783,7 +1783,7 @@ static int init_builtin(char *); /* Forward */ its module object WITH INCREMENTED REFERENCE COUNT */ static PyObject * -load_module(char *name, FILE *fp, char *buf, int type, PyObject *loader) +load_module(char *name, FILE *fp, char *pathname, int type, PyObject *loader) { PyObject *modules; PyObject *m; @@ -1804,27 +1804,27 @@ load_module(char *name, FILE *fp, char *buf, int type, PyObject *loader) switch (type) { case PY_SOURCE: - m = load_source_module(name, buf, fp); + m = load_source_module(name, pathname, fp); break; case PY_COMPILED: - m = load_compiled_module(name, buf, fp); + m = load_compiled_module(name, pathname, fp); break; #ifdef HAVE_DYNAMIC_LOADING case C_EXTENSION: - m = _PyImport_LoadDynamicModule(name, buf, fp); + m = _PyImport_LoadDynamicModule(name, pathname, fp); break; #endif case PKG_DIRECTORY: - m = load_package(name, buf); + m = load_package(name, pathname); break; case C_BUILTIN: case PY_FROZEN: - if (buf != NULL && buf[0] != '\0') - name = buf; + if (pathname != NULL && pathname[0] != '\0') + name = pathname; if (type == C_BUILTIN) err = init_builtin(name); else -- cgit v1.2.1 From cd000f04a49d0b51d35ae97bc9c474c5b9d4b29b Mon Sep 17 00:00:00 2001 From: Sean Reifscheider Date: Sat, 1 Aug 2009 23:55:06 +0000 Subject: - Issue #6624: yArg_ParseTuple with "s" format when parsing argument with NUL: Bogus TypeError detail string. --- Python/getargs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index a5dc3602b2..486cf7d07d 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -387,7 +387,7 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) flags, levels, msgbuf, sizeof(msgbuf), &freelist); if (msg) { - seterror(i+1, msg, levels, fname, message); + seterror(i+1, msg, levels, fname, msg); return cleanreturn(0, freelist); } } -- cgit v1.2.1 From b8417dd9d75e53fd65dcd3b63e913ccfbee59516 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 11 Sep 2009 22:36:20 +0000 Subject: Merged revisions 74464 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r74464 | benjamin.peterson | 2009-08-15 17:59:21 -0500 (Sat, 15 Aug 2009) | 4 lines better col_offsets for "for" statements with tuple unpacking #6704 Patch from Frank Wierzbicki. ........ --- Python/ast.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index 8a1edd2f10..fb3894449a 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -1192,7 +1192,7 @@ ast_for_comprehension(struct compiling *c, const node *n) for (i = 0; i < n_fors; i++) { comprehension_ty comp; asdl_seq *t; - expr_ty expression; + expr_ty expression, first; node *for_ch; REQ(n, comp_for); @@ -1207,14 +1207,13 @@ ast_for_comprehension(struct compiling *c, const node *n) /* 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. */ + first = (expr_ty)asdl_seq_GET(t, 0); if (NCH(for_ch) == 1) - comp = comprehension((expr_ty)asdl_seq_GET(t, 0), expression, - NULL, c->c_arena); + comp = comprehension(first, expression, NULL, c->c_arena); else - comp = comprehension(Tuple(t, Store, LINENO(n), n->n_col_offset, - c->c_arena), - expression, NULL, c->c_arena); - + comp = comprehension(Tuple(t, Store, first->lineno, first->col_offset, + c->c_arena), + expression, NULL, c->c_arena); if (!comp) return NULL; @@ -1294,7 +1293,6 @@ ast_for_dictcomp(struct compiling *c, const node *n) key = ast_for_expr(c, CHILD(n, 0)); if (!key) return NULL; - value = ast_for_expr(c, CHILD(n, 2)); if (!value) return NULL; @@ -2802,7 +2800,7 @@ ast_for_for_stmt(struct compiling *c, const node *n) { asdl_seq *_target, *seq = NULL, *suite_seq; expr_ty expression; - expr_ty target; + expr_ty target, first; const node *node_target; /* for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] */ REQ(n, for_stmt); @@ -2819,10 +2817,11 @@ ast_for_for_stmt(struct compiling *c, const node *n) 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. */ + first = (expr_ty)asdl_seq_GET(_target, 0); if (NCH(node_target) == 1) - target = (expr_ty)asdl_seq_GET(_target, 0); + target = first; else - target = Tuple(_target, Store, LINENO(n), n->n_col_offset, c->c_arena); + target = Tuple(_target, Store, first->lineno, first->col_offset, c->c_arena); expression = ast_for_testlist(c, CHILD(n, 3)); if (!expression) -- cgit v1.2.1 From 8ccabc0faaf6b0af4ba2483c6212f324815fbef1 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 27 Sep 2009 02:43:28 +0000 Subject: fix an ambiguity in the grammar from the implementation of extended unpacking (one which was strangely "resolved" by pgen) This also kills the unused testlist1 rule and fixes parse tree validation of extended unpacking. --- Python/ast.c | 27 +- Python/graminit.c | 1668 +++++++++++++++++++++++++++-------------------------- 2 files changed, 853 insertions(+), 842 deletions(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index fb3894449a..97b57ec100 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -603,20 +603,23 @@ ast_for_comp_op(struct compiling *c, const node *n) static asdl_seq * seq_for_testlist(struct compiling *c, const node *n) { - /* testlist: test (',' test)* [','] */ + /* testlist: test (',' test)* [','] + testlist_star_expr: test|star_expr (',' test|star_expr)* [','] + */ asdl_seq *seq; expr_ty expression; int i; - assert(TYPE(n) == testlist || TYPE(n) == testlist_comp); + assert(TYPE(n) == testlist || TYPE(n) == testlist_star_expr || TYPE(n) == testlist_comp); 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)) == test_nocond); + const node *ch = CHILD(n, i); + assert(TYPE(ch) == test || TYPE(ch) == test_nocond || TYPE(ch) == star_expr); - expression = ast_for_expr(c, CHILD(n, i)); + expression = ast_for_expr(c, ch); if (!expression) return NULL; @@ -1886,10 +1889,9 @@ ast_for_expr(struct compiling *c, const node *n) break; case star_expr: - if (TYPE(CHILD(n, 0)) == STAR) { - return ast_for_starred(c, n); - } - /* Fallthrough */ + if (TYPE(CHILD(n, 0)) == STAR) + return ast_for_starred(c, n); + /* Fall through to generic case. */ /* 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. @@ -2067,7 +2069,6 @@ ast_for_testlist(struct compiling *c, const node* n) { /* testlist_comp: test (comp_for | (',' test)* [',']) */ /* testlist: test (',' test)* [','] */ - /* testlist1: test (',' test)* */ assert(NCH(n) > 0); if (TYPE(n) == testlist_comp) { if (NCH(n) > 1) @@ -2075,7 +2076,7 @@ ast_for_testlist(struct compiling *c, const node* n) } else { assert(TYPE(n) == testlist || - TYPE(n) == testlist1); + TYPE(n) == testlist_star_expr); } if (NCH(n) == 1) return ast_for_expr(c, CHILD(n, 0)); @@ -2091,9 +2092,9 @@ static stmt_ty ast_for_expr_stmt(struct compiling *c, const node *n) { REQ(n, expr_stmt); - /* expr_stmt: testlist (augassign (yield_expr|testlist) + /* expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) | ('=' (yield_expr|testlist))*) - testlist: test (',' test)* [','] + testlist_star_expr: (test|star_expr) (',' test|star_expr)* [','] augassign: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' | '//=' test: ... here starts the operator precendence dance @@ -2161,7 +2162,7 @@ ast_for_expr_stmt(struct compiling *c, const node *n) asdl_seq_SET(targets, i / 2, e); } value = CHILD(n, NCH(n) - 1); - if (TYPE(value) == testlist) + if (TYPE(value) == testlist_star_expr) expression = ast_for_testlist(c, value); else expression = ast_for_expr(c, value); diff --git a/Python/graminit.c b/Python/graminit.c index 1bea8a6b25..e3530857a5 100644 --- a/Python/graminit.c +++ b/Python/graminit.c @@ -364,20 +364,20 @@ static state states_14[2] = { {1, arcs_14_1}, }; static arc arcs_15_0[1] = { - {9, 1}, + {45, 1}, }; static arc arcs_15_1[3] = { - {45, 2}, + {46, 2}, {29, 3}, {0, 1}, }; static arc arcs_15_2[2] = { - {46, 4}, + {47, 4}, {9, 4}, }; static arc arcs_15_3[2] = { - {46, 5}, - {9, 5}, + {47, 5}, + {45, 5}, }; static arc arcs_15_4[1] = { {0, 4}, @@ -394,9 +394,25 @@ static state states_15[6] = { {1, arcs_15_4}, {2, arcs_15_5}, }; -static arc arcs_16_0[12] = { - {47, 1}, +static arc arcs_16_0[2] = { + {24, 1}, + {48, 1}, +}; +static arc arcs_16_1[2] = { + {30, 2}, + {0, 1}, +}; +static arc arcs_16_2[3] = { + {24, 1}, {48, 1}, + {0, 2}, +}; +static state states_16[3] = { + {2, arcs_16_0}, + {2, arcs_16_1}, + {3, arcs_16_2}, +}; +static arc arcs_17_0[12] = { {49, 1}, {50, 1}, {51, 1}, @@ -407,64 +423,56 @@ static arc arcs_16_0[12] = { {56, 1}, {57, 1}, {58, 1}, -}; -static arc arcs_16_1[1] = { - {0, 1}, -}; -static state states_16[2] = { - {12, arcs_16_0}, - {1, arcs_16_1}, -}; -static arc arcs_17_0[1] = { {59, 1}, + {60, 1}, }; static arc arcs_17_1[1] = { - {60, 2}, -}; -static arc arcs_17_2[1] = { - {0, 2}, + {0, 1}, }; -static state states_17[3] = { - {1, arcs_17_0}, +static state states_17[2] = { + {12, arcs_17_0}, {1, arcs_17_1}, - {1, arcs_17_2}, }; static arc arcs_18_0[1] = { {61, 1}, }; static arc arcs_18_1[1] = { - {0, 1}, + {62, 2}, }; -static state states_18[2] = { +static arc arcs_18_2[1] = { + {0, 2}, +}; +static state states_18[3] = { {1, arcs_18_0}, {1, arcs_18_1}, + {1, arcs_18_2}, }; -static arc arcs_19_0[5] = { - {62, 1}, +static arc arcs_19_0[1] = { {63, 1}, - {64, 1}, - {65, 1}, - {66, 1}, }; static arc arcs_19_1[1] = { {0, 1}, }; static state states_19[2] = { - {5, arcs_19_0}, + {1, arcs_19_0}, {1, arcs_19_1}, }; -static arc arcs_20_0[1] = { +static arc arcs_20_0[5] = { + {64, 1}, + {65, 1}, + {66, 1}, {67, 1}, + {68, 1}, }; static arc arcs_20_1[1] = { {0, 1}, }; static state states_20[2] = { - {1, arcs_20_0}, + {5, arcs_20_0}, {1, arcs_20_1}, }; static arc arcs_21_0[1] = { - {68, 1}, + {69, 1}, }; static arc arcs_21_1[1] = { {0, 1}, @@ -474,144 +482,135 @@ static state states_21[2] = { {1, arcs_21_1}, }; static arc arcs_22_0[1] = { - {69, 1}, + {70, 1}, }; -static arc arcs_22_1[2] = { - {9, 2}, +static arc arcs_22_1[1] = { {0, 1}, }; -static arc arcs_22_2[1] = { - {0, 2}, -}; -static state states_22[3] = { +static state states_22[2] = { {1, arcs_22_0}, - {2, arcs_22_1}, - {1, arcs_22_2}, + {1, arcs_22_1}, }; static arc arcs_23_0[1] = { - {46, 1}, + {71, 1}, }; -static arc arcs_23_1[1] = { +static arc arcs_23_1[2] = { + {9, 2}, {0, 1}, }; -static state states_23[2] = { +static arc arcs_23_2[1] = { + {0, 2}, +}; +static state states_23[3] = { {1, arcs_23_0}, - {1, arcs_23_1}, + {2, arcs_23_1}, + {1, arcs_23_2}, }; static arc arcs_24_0[1] = { - {70, 1}, + {47, 1}, +}; +static arc arcs_24_1[1] = { + {0, 1}, +}; +static state states_24[2] = { + {1, arcs_24_0}, + {1, arcs_24_1}, +}; +static arc arcs_25_0[1] = { + {72, 1}, }; -static arc arcs_24_1[2] = { +static arc arcs_25_1[2] = { {24, 2}, {0, 1}, }; -static arc arcs_24_2[2] = { - {71, 3}, +static arc arcs_25_2[2] = { + {73, 3}, {0, 2}, }; -static arc arcs_24_3[1] = { +static arc arcs_25_3[1] = { {24, 4}, }; -static arc arcs_24_4[1] = { +static arc arcs_25_4[1] = { {0, 4}, }; -static state states_24[5] = { - {1, arcs_24_0}, - {2, arcs_24_1}, - {2, arcs_24_2}, - {1, arcs_24_3}, - {1, arcs_24_4}, +static state states_25[5] = { + {1, arcs_25_0}, + {2, arcs_25_1}, + {2, arcs_25_2}, + {1, arcs_25_3}, + {1, arcs_25_4}, }; -static arc arcs_25_0[2] = { - {72, 1}, - {73, 1}, +static arc arcs_26_0[2] = { + {74, 1}, + {75, 1}, }; -static arc arcs_25_1[1] = { +static arc arcs_26_1[1] = { {0, 1}, }; -static state states_25[2] = { - {2, arcs_25_0}, - {1, arcs_25_1}, +static state states_26[2] = { + {2, arcs_26_0}, + {1, arcs_26_1}, }; -static arc arcs_26_0[1] = { - {74, 1}, +static arc arcs_27_0[1] = { + {76, 1}, }; -static arc arcs_26_1[1] = { - {75, 2}, +static arc arcs_27_1[1] = { + {77, 2}, }; -static arc arcs_26_2[1] = { +static arc arcs_27_2[1] = { {0, 2}, }; -static state states_26[3] = { - {1, arcs_26_0}, - {1, arcs_26_1}, - {1, arcs_26_2}, +static state states_27[3] = { + {1, arcs_27_0}, + {1, arcs_27_1}, + {1, arcs_27_2}, }; -static arc arcs_27_0[1] = { - {71, 1}, +static arc arcs_28_0[1] = { + {73, 1}, }; -static arc arcs_27_1[3] = { - {76, 2}, - {77, 2}, +static arc arcs_28_1[3] = { + {78, 2}, + {79, 2}, {12, 3}, }; -static arc arcs_27_2[4] = { - {76, 2}, - {77, 2}, +static arc arcs_28_2[4] = { + {78, 2}, + {79, 2}, {12, 3}, - {74, 4}, + {76, 4}, }; -static arc arcs_27_3[1] = { - {74, 4}, +static arc arcs_28_3[1] = { + {76, 4}, }; -static arc arcs_27_4[3] = { +static arc arcs_28_4[3] = { {31, 5}, {13, 6}, - {78, 5}, + {80, 5}, }; -static arc arcs_27_5[1] = { +static arc arcs_28_5[1] = { {0, 5}, }; -static arc arcs_27_6[1] = { - {78, 7}, +static arc arcs_28_6[1] = { + {80, 7}, }; -static arc arcs_27_7[1] = { +static arc arcs_28_7[1] = { {15, 5}, }; -static state states_27[8] = { - {1, arcs_27_0}, - {3, arcs_27_1}, - {4, arcs_27_2}, - {1, arcs_27_3}, - {3, arcs_27_4}, - {1, arcs_27_5}, - {1, arcs_27_6}, - {1, arcs_27_7}, -}; -static arc arcs_28_0[1] = { - {21, 1}, -}; -static arc arcs_28_1[2] = { - {80, 2}, - {0, 1}, -}; -static arc arcs_28_2[1] = { - {21, 3}, -}; -static arc arcs_28_3[1] = { - {0, 3}, -}; -static state states_28[4] = { +static state states_28[8] = { {1, arcs_28_0}, - {2, arcs_28_1}, - {1, arcs_28_2}, + {3, arcs_28_1}, + {4, arcs_28_2}, {1, arcs_28_3}, + {3, arcs_28_4}, + {1, arcs_28_5}, + {1, arcs_28_6}, + {1, arcs_28_7}, }; static arc arcs_29_0[1] = { - {12, 1}, + {21, 1}, }; static arc arcs_29_1[2] = { - {80, 2}, + {82, 2}, {0, 1}, }; static arc arcs_29_2[1] = { @@ -627,37 +626,45 @@ static state states_29[4] = { {1, arcs_29_3}, }; static arc arcs_30_0[1] = { - {79, 1}, + {12, 1}, }; static arc arcs_30_1[2] = { - {30, 2}, + {82, 2}, {0, 1}, }; -static arc arcs_30_2[2] = { - {79, 1}, - {0, 2}, +static arc arcs_30_2[1] = { + {21, 3}, +}; +static arc arcs_30_3[1] = { + {0, 3}, }; -static state states_30[3] = { +static state states_30[4] = { {1, arcs_30_0}, {2, arcs_30_1}, - {2, arcs_30_2}, + {1, arcs_30_2}, + {1, arcs_30_3}, }; static arc arcs_31_0[1] = { {81, 1}, }; static arc arcs_31_1[2] = { - {30, 0}, + {30, 2}, {0, 1}, }; -static state states_31[2] = { +static arc arcs_31_2[2] = { + {81, 1}, + {0, 2}, +}; +static state states_31[3] = { {1, arcs_31_0}, {2, arcs_31_1}, + {2, arcs_31_2}, }; static arc arcs_32_0[1] = { - {21, 1}, + {83, 1}, }; static arc arcs_32_1[2] = { - {76, 0}, + {30, 0}, {0, 1}, }; static state states_32[2] = { @@ -665,22 +672,18 @@ static state states_32[2] = { {2, arcs_32_1}, }; static arc arcs_33_0[1] = { - {82, 1}, -}; -static arc arcs_33_1[1] = { - {21, 2}, + {21, 1}, }; -static arc arcs_33_2[2] = { - {30, 1}, - {0, 2}, +static arc arcs_33_1[2] = { + {78, 0}, + {0, 1}, }; -static state states_33[3] = { +static state states_33[2] = { {1, arcs_33_0}, - {1, arcs_33_1}, - {2, arcs_33_2}, + {2, arcs_33_1}, }; static arc arcs_34_0[1] = { - {83, 1}, + {84, 1}, }; static arc arcs_34_1[1] = { {21, 2}, @@ -695,83 +698,62 @@ static state states_34[3] = { {2, arcs_34_2}, }; static arc arcs_35_0[1] = { - {84, 1}, + {85, 1}, }; static arc arcs_35_1[1] = { - {24, 2}, + {21, 2}, }; static arc arcs_35_2[2] = { - {30, 3}, + {30, 1}, {0, 2}, }; -static arc arcs_35_3[1] = { - {24, 4}, -}; -static arc arcs_35_4[1] = { - {0, 4}, -}; -static state states_35[5] = { +static state states_35[3] = { {1, arcs_35_0}, {1, arcs_35_1}, {2, arcs_35_2}, - {1, arcs_35_3}, - {1, arcs_35_4}, }; -static arc arcs_36_0[8] = { - {85, 1}, +static arc arcs_36_0[1] = { {86, 1}, - {87, 1}, - {88, 1}, - {89, 1}, - {19, 1}, - {18, 1}, - {17, 1}, }; static arc arcs_36_1[1] = { - {0, 1}, -}; -static state states_36[2] = { - {8, arcs_36_0}, - {1, arcs_36_1}, -}; -static arc arcs_37_0[1] = { - {90, 1}, -}; -static arc arcs_37_1[1] = { {24, 2}, }; -static arc arcs_37_2[1] = { - {25, 3}, +static arc arcs_36_2[2] = { + {30, 3}, + {0, 2}, }; -static arc arcs_37_3[1] = { - {26, 4}, +static arc arcs_36_3[1] = { + {24, 4}, }; -static arc arcs_37_4[3] = { - {91, 1}, - {92, 5}, +static arc arcs_36_4[1] = { {0, 4}, }; -static arc arcs_37_5[1] = { - {25, 6}, +static state states_36[5] = { + {1, arcs_36_0}, + {1, arcs_36_1}, + {2, arcs_36_2}, + {1, arcs_36_3}, + {1, arcs_36_4}, }; -static arc arcs_37_6[1] = { - {26, 7}, +static arc arcs_37_0[8] = { + {87, 1}, + {88, 1}, + {89, 1}, + {90, 1}, + {91, 1}, + {19, 1}, + {18, 1}, + {17, 1}, }; -static arc arcs_37_7[1] = { - {0, 7}, +static arc arcs_37_1[1] = { + {0, 1}, }; -static state states_37[8] = { - {1, arcs_37_0}, +static state states_37[2] = { + {8, arcs_37_0}, {1, arcs_37_1}, - {1, arcs_37_2}, - {1, arcs_37_3}, - {3, arcs_37_4}, - {1, arcs_37_5}, - {1, arcs_37_6}, - {1, arcs_37_7}, }; static arc arcs_38_0[1] = { - {93, 1}, + {92, 1}, }; static arc arcs_38_1[1] = { {24, 2}, @@ -782,8 +764,9 @@ static arc arcs_38_2[1] = { static arc arcs_38_3[1] = { {26, 4}, }; -static arc arcs_38_4[2] = { - {92, 5}, +static arc arcs_38_4[3] = { + {93, 1}, + {94, 5}, {0, 4}, }; static arc arcs_38_5[1] = { @@ -800,267 +783,279 @@ static state states_38[8] = { {1, arcs_38_1}, {1, arcs_38_2}, {1, arcs_38_3}, - {2, arcs_38_4}, + {3, arcs_38_4}, {1, arcs_38_5}, {1, arcs_38_6}, {1, arcs_38_7}, }; static arc arcs_39_0[1] = { - {94, 1}, + {95, 1}, }; static arc arcs_39_1[1] = { - {60, 2}, + {24, 2}, }; static arc arcs_39_2[1] = { - {95, 3}, + {25, 3}, }; static arc arcs_39_3[1] = { - {9, 4}, + {26, 4}, }; -static arc arcs_39_4[1] = { - {25, 5}, +static arc arcs_39_4[2] = { + {94, 5}, + {0, 4}, }; static arc arcs_39_5[1] = { - {26, 6}, + {25, 6}, }; -static arc arcs_39_6[2] = { - {92, 7}, - {0, 6}, +static arc arcs_39_6[1] = { + {26, 7}, }; static arc arcs_39_7[1] = { - {25, 8}, -}; -static arc arcs_39_8[1] = { - {26, 9}, -}; -static arc arcs_39_9[1] = { - {0, 9}, + {0, 7}, }; -static state states_39[10] = { +static state states_39[8] = { {1, arcs_39_0}, {1, arcs_39_1}, {1, arcs_39_2}, {1, arcs_39_3}, - {1, arcs_39_4}, + {2, arcs_39_4}, {1, arcs_39_5}, - {2, arcs_39_6}, + {1, arcs_39_6}, {1, arcs_39_7}, - {1, arcs_39_8}, - {1, arcs_39_9}, }; static arc arcs_40_0[1] = { {96, 1}, }; static arc arcs_40_1[1] = { - {25, 2}, + {62, 2}, }; static arc arcs_40_2[1] = { - {26, 3}, + {97, 3}, }; -static arc arcs_40_3[2] = { - {97, 4}, - {98, 5}, +static arc arcs_40_3[1] = { + {9, 4}, }; static arc arcs_40_4[1] = { - {25, 6}, + {25, 5}, }; static arc arcs_40_5[1] = { - {25, 7}, + {26, 6}, }; -static arc arcs_40_6[1] = { - {26, 8}, +static arc arcs_40_6[2] = { + {94, 7}, + {0, 6}, }; static arc arcs_40_7[1] = { - {26, 9}, + {25, 8}, }; -static arc arcs_40_8[4] = { - {97, 4}, - {92, 10}, - {98, 5}, - {0, 8}, +static arc arcs_40_8[1] = { + {26, 9}, }; static arc arcs_40_9[1] = { {0, 9}, }; -static arc arcs_40_10[1] = { - {25, 11}, -}; -static arc arcs_40_11[1] = { - {26, 12}, -}; -static arc arcs_40_12[2] = { - {98, 5}, - {0, 12}, -}; -static state states_40[13] = { +static state states_40[10] = { {1, arcs_40_0}, {1, arcs_40_1}, {1, arcs_40_2}, - {2, arcs_40_3}, + {1, arcs_40_3}, {1, arcs_40_4}, {1, arcs_40_5}, - {1, arcs_40_6}, + {2, arcs_40_6}, {1, arcs_40_7}, - {4, arcs_40_8}, + {1, arcs_40_8}, {1, arcs_40_9}, - {1, arcs_40_10}, - {1, arcs_40_11}, - {2, arcs_40_12}, }; static arc arcs_41_0[1] = { - {99, 1}, + {98, 1}, }; static arc arcs_41_1[1] = { - {100, 2}, + {25, 2}, }; -static arc arcs_41_2[2] = { - {30, 1}, - {25, 3}, +static arc arcs_41_2[1] = { + {26, 3}, }; -static arc arcs_41_3[1] = { - {26, 4}, +static arc arcs_41_3[2] = { + {99, 4}, + {100, 5}, }; static arc arcs_41_4[1] = { - {0, 4}, + {25, 6}, }; -static state states_41[5] = { +static arc arcs_41_5[1] = { + {25, 7}, +}; +static arc arcs_41_6[1] = { + {26, 8}, +}; +static arc arcs_41_7[1] = { + {26, 9}, +}; +static arc arcs_41_8[4] = { + {99, 4}, + {94, 10}, + {100, 5}, + {0, 8}, +}; +static arc arcs_41_9[1] = { + {0, 9}, +}; +static arc arcs_41_10[1] = { + {25, 11}, +}; +static arc arcs_41_11[1] = { + {26, 12}, +}; +static arc arcs_41_12[2] = { + {100, 5}, + {0, 12}, +}; +static state states_41[13] = { {1, arcs_41_0}, {1, arcs_41_1}, - {2, arcs_41_2}, - {1, arcs_41_3}, + {1, arcs_41_2}, + {2, arcs_41_3}, {1, arcs_41_4}, + {1, arcs_41_5}, + {1, arcs_41_6}, + {1, arcs_41_7}, + {4, arcs_41_8}, + {1, arcs_41_9}, + {1, arcs_41_10}, + {1, arcs_41_11}, + {2, arcs_41_12}, }; static arc arcs_42_0[1] = { - {24, 1}, + {101, 1}, }; -static arc arcs_42_1[2] = { - {80, 2}, - {0, 1}, +static arc arcs_42_1[1] = { + {102, 2}, }; -static arc arcs_42_2[1] = { - {101, 3}, +static arc arcs_42_2[2] = { + {30, 1}, + {25, 3}, }; static arc arcs_42_3[1] = { - {0, 3}, + {26, 4}, +}; +static arc arcs_42_4[1] = { + {0, 4}, }; -static state states_42[4] = { +static state states_42[5] = { {1, arcs_42_0}, - {2, arcs_42_1}, - {1, arcs_42_2}, + {1, arcs_42_1}, + {2, arcs_42_2}, {1, arcs_42_3}, + {1, arcs_42_4}, }; static arc arcs_43_0[1] = { - {102, 1}, + {24, 1}, }; static arc arcs_43_1[2] = { - {24, 2}, + {82, 2}, {0, 1}, }; -static arc arcs_43_2[2] = { - {80, 3}, - {0, 2}, +static arc arcs_43_2[1] = { + {103, 3}, }; static arc arcs_43_3[1] = { - {21, 4}, -}; -static arc arcs_43_4[1] = { - {0, 4}, + {0, 3}, }; -static state states_43[5] = { +static state states_43[4] = { {1, arcs_43_0}, {2, arcs_43_1}, - {2, arcs_43_2}, + {1, arcs_43_2}, {1, arcs_43_3}, - {1, arcs_43_4}, }; -static arc arcs_44_0[2] = { - {3, 1}, - {2, 2}, +static arc arcs_44_0[1] = { + {104, 1}, }; -static arc arcs_44_1[1] = { +static arc arcs_44_1[2] = { + {24, 2}, {0, 1}, }; -static arc arcs_44_2[1] = { - {103, 3}, +static arc arcs_44_2[2] = { + {82, 3}, + {0, 2}, }; static arc arcs_44_3[1] = { - {6, 4}, + {21, 4}, }; -static arc arcs_44_4[2] = { - {6, 4}, - {104, 1}, +static arc arcs_44_4[1] = { + {0, 4}, }; static state states_44[5] = { - {2, arcs_44_0}, - {1, arcs_44_1}, - {1, arcs_44_2}, + {1, arcs_44_0}, + {2, arcs_44_1}, + {2, arcs_44_2}, {1, arcs_44_3}, - {2, arcs_44_4}, + {1, arcs_44_4}, }; static arc arcs_45_0[2] = { - {105, 1}, - {106, 2}, + {3, 1}, + {2, 2}, }; -static arc arcs_45_1[2] = { - {90, 3}, +static arc arcs_45_1[1] = { {0, 1}, }; static arc arcs_45_2[1] = { - {0, 2}, + {105, 3}, }; static arc arcs_45_3[1] = { - {105, 4}, -}; -static arc arcs_45_4[1] = { - {92, 5}, + {6, 4}, }; -static arc arcs_45_5[1] = { - {24, 2}, +static arc arcs_45_4[2] = { + {6, 4}, + {106, 1}, }; -static state states_45[6] = { +static state states_45[5] = { {2, arcs_45_0}, - {2, arcs_45_1}, + {1, arcs_45_1}, {1, arcs_45_2}, {1, arcs_45_3}, - {1, arcs_45_4}, - {1, arcs_45_5}, + {2, arcs_45_4}, }; static arc arcs_46_0[2] = { - {105, 1}, - {108, 1}, + {107, 1}, + {108, 2}, }; -static arc arcs_46_1[1] = { +static arc arcs_46_1[2] = { + {92, 3}, {0, 1}, }; -static state states_46[2] = { - {2, arcs_46_0}, - {1, arcs_46_1}, +static arc arcs_46_2[1] = { + {0, 2}, }; -static arc arcs_47_0[1] = { - {109, 1}, +static arc arcs_46_3[1] = { + {107, 4}, }; -static arc arcs_47_1[2] = { - {33, 2}, - {25, 3}, +static arc arcs_46_4[1] = { + {94, 5}, }; -static arc arcs_47_2[1] = { - {25, 3}, +static arc arcs_46_5[1] = { + {24, 2}, }; -static arc arcs_47_3[1] = { - {24, 4}, +static state states_46[6] = { + {2, arcs_46_0}, + {2, arcs_46_1}, + {1, arcs_46_2}, + {1, arcs_46_3}, + {1, arcs_46_4}, + {1, arcs_46_5}, +}; +static arc arcs_47_0[2] = { + {107, 1}, + {110, 1}, }; -static arc arcs_47_4[1] = { - {0, 4}, +static arc arcs_47_1[1] = { + {0, 1}, }; -static state states_47[5] = { - {1, arcs_47_0}, - {2, arcs_47_1}, - {1, arcs_47_2}, - {1, arcs_47_3}, - {1, arcs_47_4}, +static state states_47[2] = { + {2, arcs_47_0}, + {1, arcs_47_1}, }; static arc arcs_48_0[1] = { - {109, 1}, + {111, 1}, }; static arc arcs_48_1[2] = { {33, 2}, @@ -1070,7 +1065,7 @@ static arc arcs_48_2[1] = { {25, 3}, }; static arc arcs_48_3[1] = { - {107, 4}, + {24, 4}, }; static arc arcs_48_4[1] = { {0, 4}, @@ -1083,15 +1078,27 @@ static state states_48[5] = { {1, arcs_48_4}, }; static arc arcs_49_0[1] = { - {110, 1}, + {111, 1}, }; static arc arcs_49_1[2] = { - {111, 0}, - {0, 1}, + {33, 2}, + {25, 3}, +}; +static arc arcs_49_2[1] = { + {25, 3}, +}; +static arc arcs_49_3[1] = { + {109, 4}, }; -static state states_49[2] = { +static arc arcs_49_4[1] = { + {0, 4}, +}; +static state states_49[5] = { {1, arcs_49_0}, {2, arcs_49_1}, + {1, arcs_49_2}, + {1, arcs_49_3}, + {1, arcs_49_4}, }; static arc arcs_50_0[1] = { {112, 1}, @@ -1104,91 +1111,90 @@ static state states_50[2] = { {1, arcs_50_0}, {2, arcs_50_1}, }; -static arc arcs_51_0[2] = { +static arc arcs_51_0[1] = { {114, 1}, - {115, 2}, }; -static arc arcs_51_1[1] = { - {112, 2}, +static arc arcs_51_1[2] = { + {115, 0}, + {0, 1}, +}; +static state states_51[2] = { + {1, arcs_51_0}, + {2, arcs_51_1}, +}; +static arc arcs_52_0[2] = { + {116, 1}, + {117, 2}, +}; +static arc arcs_52_1[1] = { + {114, 2}, }; -static arc arcs_51_2[1] = { +static arc arcs_52_2[1] = { {0, 2}, }; -static state states_51[3] = { - {2, arcs_51_0}, - {1, arcs_51_1}, - {1, arcs_51_2}, +static state states_52[3] = { + {2, arcs_52_0}, + {1, arcs_52_1}, + {1, arcs_52_2}, }; -static arc arcs_52_0[1] = { - {116, 1}, +static arc arcs_53_0[1] = { + {103, 1}, }; -static arc arcs_52_1[2] = { - {117, 0}, +static arc arcs_53_1[2] = { + {118, 0}, {0, 1}, }; -static state states_52[2] = { - {1, arcs_52_0}, - {2, arcs_52_1}, +static state states_53[2] = { + {1, arcs_53_0}, + {2, arcs_53_1}, }; -static arc arcs_53_0[10] = { - {118, 1}, +static arc arcs_54_0[10] = { {119, 1}, {120, 1}, {121, 1}, {122, 1}, {123, 1}, {124, 1}, - {95, 1}, - {114, 2}, - {125, 3}, + {125, 1}, + {97, 1}, + {116, 2}, + {126, 3}, }; -static arc arcs_53_1[1] = { +static arc arcs_54_1[1] = { {0, 1}, }; -static arc arcs_53_2[1] = { - {95, 1}, +static arc arcs_54_2[1] = { + {97, 1}, }; -static arc arcs_53_3[2] = { - {114, 1}, +static arc arcs_54_3[2] = { + {116, 1}, {0, 3}, }; -static state states_53[4] = { - {10, arcs_53_0}, - {1, arcs_53_1}, - {1, arcs_53_2}, - {2, arcs_53_3}, -}; -static arc arcs_54_0[2] = { - {31, 1}, - {101, 2}, -}; -static arc arcs_54_1[1] = { - {101, 2}, -}; -static arc arcs_54_2[1] = { - {0, 2}, -}; -static state states_54[3] = { - {2, arcs_54_0}, +static state states_54[4] = { + {10, arcs_54_0}, {1, arcs_54_1}, {1, arcs_54_2}, + {2, arcs_54_3}, }; static arc arcs_55_0[1] = { - {126, 1}, + {31, 1}, }; -static arc arcs_55_1[2] = { - {127, 0}, - {0, 1}, +static arc arcs_55_1[1] = { + {103, 2}, +}; +static arc arcs_55_2[1] = { + {0, 2}, }; -static state states_55[2] = { +static state states_55[3] = { {1, arcs_55_0}, - {2, arcs_55_1}, + {1, arcs_55_1}, + {1, arcs_55_2}, }; static arc arcs_56_0[1] = { - {128, 1}, + {127, 1}, }; static arc arcs_56_1[2] = { - {129, 0}, + {128, 0}, {0, 1}, }; static state states_56[2] = { @@ -1196,10 +1202,10 @@ static state states_56[2] = { {2, arcs_56_1}, }; static arc arcs_57_0[1] = { - {130, 1}, + {129, 1}, }; static arc arcs_57_1[2] = { - {131, 0}, + {130, 0}, {0, 1}, }; static state states_57[2] = { @@ -1207,23 +1213,22 @@ static state states_57[2] = { {2, arcs_57_1}, }; static arc arcs_58_0[1] = { - {132, 1}, + {131, 1}, }; -static arc arcs_58_1[3] = { - {133, 0}, - {134, 0}, +static arc arcs_58_1[2] = { + {132, 0}, {0, 1}, }; static state states_58[2] = { {1, arcs_58_0}, - {3, arcs_58_1}, + {2, arcs_58_1}, }; static arc arcs_59_0[1] = { - {135, 1}, + {133, 1}, }; static arc arcs_59_1[3] = { - {136, 0}, - {137, 0}, + {134, 0}, + {135, 0}, {0, 1}, }; static state states_59[2] = { @@ -1231,477 +1236,482 @@ static state states_59[2] = { {3, arcs_59_1}, }; static arc arcs_60_0[1] = { - {138, 1}, + {136, 1}, +}; +static arc arcs_60_1[3] = { + {137, 0}, + {138, 0}, + {0, 1}, +}; +static state states_60[2] = { + {1, arcs_60_0}, + {3, arcs_60_1}, +}; +static arc arcs_61_0[1] = { + {139, 1}, }; -static arc arcs_60_1[5] = { +static arc arcs_61_1[5] = { {31, 0}, - {139, 0}, {140, 0}, {141, 0}, + {142, 0}, {0, 1}, }; -static state states_60[2] = { - {1, arcs_60_0}, - {5, arcs_60_1}, +static state states_61[2] = { + {1, arcs_61_0}, + {5, arcs_61_1}, }; -static arc arcs_61_0[4] = { - {136, 1}, +static arc arcs_62_0[4] = { {137, 1}, - {142, 1}, - {143, 2}, + {138, 1}, + {143, 1}, + {144, 2}, }; -static arc arcs_61_1[1] = { - {138, 2}, +static arc arcs_62_1[1] = { + {139, 2}, }; -static arc arcs_61_2[1] = { +static arc arcs_62_2[1] = { {0, 2}, }; -static state states_61[3] = { - {4, arcs_61_0}, - {1, arcs_61_1}, - {1, arcs_61_2}, -}; -static arc arcs_62_0[1] = { - {144, 1}, +static state states_62[3] = { + {4, arcs_62_0}, + {1, arcs_62_1}, + {1, arcs_62_2}, }; -static arc arcs_62_1[3] = { +static arc arcs_63_0[1] = { {145, 1}, +}; +static arc arcs_63_1[3] = { + {146, 1}, {32, 2}, {0, 1}, }; -static arc arcs_62_2[1] = { - {138, 3}, +static arc arcs_63_2[1] = { + {139, 3}, }; -static arc arcs_62_3[1] = { +static arc arcs_63_3[1] = { {0, 3}, }; -static state states_62[4] = { - {1, arcs_62_0}, - {3, arcs_62_1}, - {1, arcs_62_2}, - {1, arcs_62_3}, +static state states_63[4] = { + {1, arcs_63_0}, + {3, arcs_63_1}, + {1, arcs_63_2}, + {1, arcs_63_3}, }; -static arc arcs_63_0[10] = { +static arc arcs_64_0[10] = { {13, 1}, - {147, 2}, - {149, 3}, + {148, 2}, + {150, 3}, {21, 4}, - {152, 4}, - {153, 5}, - {77, 4}, - {154, 4}, + {153, 4}, + {154, 5}, + {79, 4}, {155, 4}, {156, 4}, + {157, 4}, }; -static arc arcs_63_1[3] = { - {46, 6}, - {146, 6}, +static arc arcs_64_1[3] = { + {47, 6}, + {147, 6}, {15, 4}, }; -static arc arcs_63_2[2] = { - {146, 7}, - {148, 4}, +static arc arcs_64_2[2] = { + {147, 7}, + {149, 4}, }; -static arc arcs_63_3[2] = { - {150, 8}, - {151, 4}, +static arc arcs_64_3[2] = { + {151, 8}, + {152, 4}, }; -static arc arcs_63_4[1] = { +static arc arcs_64_4[1] = { {0, 4}, }; -static arc arcs_63_5[2] = { - {153, 5}, +static arc arcs_64_5[2] = { + {154, 5}, {0, 5}, }; -static arc arcs_63_6[1] = { +static arc arcs_64_6[1] = { {15, 4}, }; -static arc arcs_63_7[1] = { - {148, 4}, +static arc arcs_64_7[1] = { + {149, 4}, }; -static arc arcs_63_8[1] = { - {151, 4}, +static arc arcs_64_8[1] = { + {152, 4}, }; -static state states_63[9] = { - {10, arcs_63_0}, - {3, arcs_63_1}, - {2, arcs_63_2}, - {2, arcs_63_3}, - {1, arcs_63_4}, - {2, arcs_63_5}, - {1, arcs_63_6}, - {1, arcs_63_7}, - {1, arcs_63_8}, -}; -static arc arcs_64_0[1] = { +static state states_64[9] = { + {10, arcs_64_0}, + {3, arcs_64_1}, + {2, arcs_64_2}, + {2, arcs_64_3}, + {1, arcs_64_4}, + {2, arcs_64_5}, + {1, arcs_64_6}, + {1, arcs_64_7}, + {1, arcs_64_8}, +}; +static arc arcs_65_0[2] = { {24, 1}, + {48, 1}, }; -static arc arcs_64_1[3] = { - {157, 2}, +static arc arcs_65_1[3] = { + {158, 2}, {30, 3}, {0, 1}, }; -static arc arcs_64_2[1] = { +static arc arcs_65_2[1] = { {0, 2}, }; -static arc arcs_64_3[2] = { +static arc arcs_65_3[3] = { {24, 4}, + {48, 4}, {0, 3}, }; -static arc arcs_64_4[2] = { +static arc arcs_65_4[2] = { {30, 3}, {0, 4}, }; -static state states_64[5] = { - {1, arcs_64_0}, - {3, arcs_64_1}, - {1, arcs_64_2}, - {2, arcs_64_3}, - {2, arcs_64_4}, +static state states_65[5] = { + {2, arcs_65_0}, + {3, arcs_65_1}, + {1, arcs_65_2}, + {3, arcs_65_3}, + {2, arcs_65_4}, }; -static arc arcs_65_0[3] = { +static arc arcs_66_0[3] = { {13, 1}, - {147, 2}, - {76, 3}, + {148, 2}, + {78, 3}, }; -static arc arcs_65_1[2] = { +static arc arcs_66_1[2] = { {14, 4}, {15, 5}, }; -static arc arcs_65_2[1] = { - {158, 6}, +static arc arcs_66_2[1] = { + {159, 6}, }; -static arc arcs_65_3[1] = { +static arc arcs_66_3[1] = { {21, 5}, }; -static arc arcs_65_4[1] = { +static arc arcs_66_4[1] = { {15, 5}, }; -static arc arcs_65_5[1] = { +static arc arcs_66_5[1] = { {0, 5}, }; -static arc arcs_65_6[1] = { - {148, 5}, +static arc arcs_66_6[1] = { + {149, 5}, }; -static state states_65[7] = { - {3, arcs_65_0}, - {2, arcs_65_1}, - {1, arcs_65_2}, - {1, arcs_65_3}, - {1, arcs_65_4}, - {1, arcs_65_5}, - {1, arcs_65_6}, +static state states_66[7] = { + {3, arcs_66_0}, + {2, arcs_66_1}, + {1, arcs_66_2}, + {1, arcs_66_3}, + {1, arcs_66_4}, + {1, arcs_66_5}, + {1, arcs_66_6}, }; -static arc arcs_66_0[1] = { - {159, 1}, +static arc arcs_67_0[1] = { + {160, 1}, }; -static arc arcs_66_1[2] = { +static arc arcs_67_1[2] = { {30, 2}, {0, 1}, }; -static arc arcs_66_2[2] = { - {159, 1}, +static arc arcs_67_2[2] = { + {160, 1}, {0, 2}, }; -static state states_66[3] = { - {1, arcs_66_0}, - {2, arcs_66_1}, - {2, arcs_66_2}, +static state states_67[3] = { + {1, arcs_67_0}, + {2, arcs_67_1}, + {2, arcs_67_2}, }; -static arc arcs_67_0[2] = { +static arc arcs_68_0[2] = { {24, 1}, {25, 2}, }; -static arc arcs_67_1[2] = { +static arc arcs_68_1[2] = { {25, 2}, {0, 1}, }; -static arc arcs_67_2[3] = { +static arc arcs_68_2[3] = { {24, 3}, - {160, 4}, + {161, 4}, {0, 2}, }; -static arc arcs_67_3[2] = { - {160, 4}, +static arc arcs_68_3[2] = { + {161, 4}, {0, 3}, }; -static arc arcs_67_4[1] = { +static arc arcs_68_4[1] = { {0, 4}, }; -static state states_67[5] = { - {2, arcs_67_0}, - {2, arcs_67_1}, - {3, arcs_67_2}, - {2, arcs_67_3}, - {1, arcs_67_4}, +static state states_68[5] = { + {2, arcs_68_0}, + {2, arcs_68_1}, + {3, arcs_68_2}, + {2, arcs_68_3}, + {1, arcs_68_4}, }; -static arc arcs_68_0[1] = { +static arc arcs_69_0[1] = { {25, 1}, }; -static arc arcs_68_1[2] = { +static arc arcs_69_1[2] = { {24, 2}, {0, 1}, }; -static arc arcs_68_2[1] = { +static arc arcs_69_2[1] = { {0, 2}, }; -static state states_68[3] = { - {1, arcs_68_0}, - {2, arcs_68_1}, - {1, arcs_68_2}, +static state states_69[3] = { + {1, arcs_69_0}, + {2, arcs_69_1}, + {1, arcs_69_2}, }; -static arc arcs_69_0[1] = { - {116, 1}, +static arc arcs_70_0[2] = { + {103, 1}, + {48, 1}, }; -static arc arcs_69_1[2] = { +static arc arcs_70_1[2] = { {30, 2}, {0, 1}, }; -static arc arcs_69_2[2] = { - {116, 1}, +static arc arcs_70_2[3] = { + {103, 1}, + {48, 1}, {0, 2}, }; -static state states_69[3] = { - {1, arcs_69_0}, - {2, arcs_69_1}, - {2, arcs_69_2}, +static state states_70[3] = { + {2, arcs_70_0}, + {2, arcs_70_1}, + {3, arcs_70_2}, }; -static arc arcs_70_0[1] = { +static arc arcs_71_0[1] = { {24, 1}, }; -static arc arcs_70_1[2] = { +static arc arcs_71_1[2] = { {30, 2}, {0, 1}, }; -static arc arcs_70_2[2] = { +static arc arcs_71_2[2] = { {24, 1}, {0, 2}, }; -static state states_70[3] = { - {1, arcs_70_0}, - {2, arcs_70_1}, - {2, arcs_70_2}, +static state states_71[3] = { + {1, arcs_71_0}, + {2, arcs_71_1}, + {2, arcs_71_2}, }; -static arc arcs_71_0[1] = { +static arc arcs_72_0[1] = { {24, 1}, }; -static arc arcs_71_1[4] = { +static arc arcs_72_1[4] = { {25, 2}, - {157, 3}, + {158, 3}, {30, 4}, {0, 1}, }; -static arc arcs_71_2[1] = { +static arc arcs_72_2[1] = { {24, 5}, }; -static arc arcs_71_3[1] = { +static arc arcs_72_3[1] = { {0, 3}, }; -static arc arcs_71_4[2] = { +static arc arcs_72_4[2] = { {24, 6}, {0, 4}, }; -static arc arcs_71_5[3] = { - {157, 3}, +static arc arcs_72_5[3] = { + {158, 3}, {30, 7}, {0, 5}, }; -static arc arcs_71_6[2] = { +static arc arcs_72_6[2] = { {30, 4}, {0, 6}, }; -static arc arcs_71_7[2] = { +static arc arcs_72_7[2] = { {24, 8}, {0, 7}, }; -static arc arcs_71_8[1] = { +static arc arcs_72_8[1] = { {25, 9}, }; -static arc arcs_71_9[1] = { +static arc arcs_72_9[1] = { {24, 10}, }; -static arc arcs_71_10[2] = { +static arc arcs_72_10[2] = { {30, 7}, {0, 10}, }; -static state states_71[11] = { - {1, arcs_71_0}, - {4, arcs_71_1}, - {1, arcs_71_2}, - {1, arcs_71_3}, - {2, arcs_71_4}, - {3, arcs_71_5}, - {2, arcs_71_6}, - {2, arcs_71_7}, - {1, arcs_71_8}, - {1, arcs_71_9}, - {2, arcs_71_10}, -}; -static arc arcs_72_0[1] = { - {161, 1}, +static state states_72[11] = { + {1, arcs_72_0}, + {4, arcs_72_1}, + {1, arcs_72_2}, + {1, arcs_72_3}, + {2, arcs_72_4}, + {3, arcs_72_5}, + {2, arcs_72_6}, + {2, arcs_72_7}, + {1, arcs_72_8}, + {1, arcs_72_9}, + {2, arcs_72_10}, +}; +static arc arcs_73_0[1] = { + {162, 1}, }; -static arc arcs_72_1[1] = { +static arc arcs_73_1[1] = { {21, 2}, }; -static arc arcs_72_2[2] = { +static arc arcs_73_2[2] = { {13, 3}, {25, 4}, }; -static arc arcs_72_3[2] = { +static arc arcs_73_3[2] = { {14, 5}, {15, 6}, }; -static arc arcs_72_4[1] = { +static arc arcs_73_4[1] = { {26, 7}, }; -static arc arcs_72_5[1] = { +static arc arcs_73_5[1] = { {15, 6}, }; -static arc arcs_72_6[1] = { +static arc arcs_73_6[1] = { {25, 4}, }; -static arc arcs_72_7[1] = { +static arc arcs_73_7[1] = { {0, 7}, }; -static state states_72[8] = { - {1, arcs_72_0}, - {1, arcs_72_1}, - {2, arcs_72_2}, - {2, arcs_72_3}, - {1, arcs_72_4}, - {1, arcs_72_5}, - {1, arcs_72_6}, - {1, arcs_72_7}, -}; -static arc arcs_73_0[3] = { - {162, 1}, +static state states_73[8] = { + {1, arcs_73_0}, + {1, arcs_73_1}, + {2, arcs_73_2}, + {2, arcs_73_3}, + {1, arcs_73_4}, + {1, arcs_73_5}, + {1, arcs_73_6}, + {1, arcs_73_7}, +}; +static arc arcs_74_0[3] = { + {163, 1}, {31, 2}, {32, 3}, }; -static arc arcs_73_1[2] = { +static arc arcs_74_1[2] = { {30, 4}, {0, 1}, }; -static arc arcs_73_2[1] = { +static arc arcs_74_2[1] = { {24, 5}, }; -static arc arcs_73_3[1] = { +static arc arcs_74_3[1] = { {24, 6}, }; -static arc arcs_73_4[4] = { - {162, 1}, +static arc arcs_74_4[4] = { + {163, 1}, {31, 2}, {32, 3}, {0, 4}, }; -static arc arcs_73_5[2] = { +static arc arcs_74_5[2] = { {30, 7}, {0, 5}, }; -static arc arcs_73_6[1] = { +static arc arcs_74_6[1] = { {0, 6}, }; -static arc arcs_73_7[2] = { - {162, 5}, +static arc arcs_74_7[2] = { + {163, 5}, {32, 3}, }; -static state states_73[8] = { - {3, arcs_73_0}, - {2, arcs_73_1}, - {1, arcs_73_2}, - {1, arcs_73_3}, - {4, arcs_73_4}, - {2, arcs_73_5}, - {1, arcs_73_6}, - {2, arcs_73_7}, +static state states_74[8] = { + {3, arcs_74_0}, + {2, arcs_74_1}, + {1, arcs_74_2}, + {1, arcs_74_3}, + {4, arcs_74_4}, + {2, arcs_74_5}, + {1, arcs_74_6}, + {2, arcs_74_7}, }; -static arc arcs_74_0[1] = { +static arc arcs_75_0[1] = { {24, 1}, }; -static arc arcs_74_1[3] = { - {157, 2}, +static arc arcs_75_1[3] = { + {158, 2}, {29, 3}, {0, 1}, }; -static arc arcs_74_2[1] = { +static arc arcs_75_2[1] = { {0, 2}, }; -static arc arcs_74_3[1] = { +static arc arcs_75_3[1] = { {24, 2}, }; -static state states_74[4] = { - {1, arcs_74_0}, - {3, arcs_74_1}, - {1, arcs_74_2}, - {1, arcs_74_3}, -}; -static arc arcs_75_0[2] = { - {157, 1}, - {164, 1}, -}; -static arc arcs_75_1[1] = { - {0, 1}, -}; -static state states_75[2] = { - {2, arcs_75_0}, - {1, arcs_75_1}, +static state states_75[4] = { + {1, arcs_75_0}, + {3, arcs_75_1}, + {1, arcs_75_2}, + {1, arcs_75_3}, }; -static arc arcs_76_0[1] = { - {94, 1}, +static arc arcs_76_0[2] = { + {158, 1}, + {165, 1}, }; static arc arcs_76_1[1] = { - {60, 2}, -}; -static arc arcs_76_2[1] = { - {95, 3}, -}; -static arc arcs_76_3[1] = { - {105, 4}, -}; -static arc arcs_76_4[2] = { - {163, 5}, - {0, 4}, -}; -static arc arcs_76_5[1] = { - {0, 5}, + {0, 1}, }; -static state states_76[6] = { - {1, arcs_76_0}, +static state states_76[2] = { + {2, arcs_76_0}, {1, arcs_76_1}, - {1, arcs_76_2}, - {1, arcs_76_3}, - {2, arcs_76_4}, - {1, arcs_76_5}, }; static arc arcs_77_0[1] = { - {90, 1}, + {96, 1}, }; static arc arcs_77_1[1] = { - {107, 2}, + {62, 2}, }; -static arc arcs_77_2[2] = { - {163, 3}, - {0, 2}, +static arc arcs_77_2[1] = { + {97, 3}, }; static arc arcs_77_3[1] = { - {0, 3}, + {107, 4}, +}; +static arc arcs_77_4[2] = { + {164, 5}, + {0, 4}, +}; +static arc arcs_77_5[1] = { + {0, 5}, }; -static state states_77[4] = { +static state states_77[6] = { {1, arcs_77_0}, {1, arcs_77_1}, - {2, arcs_77_2}, + {1, arcs_77_2}, {1, arcs_77_3}, + {2, arcs_77_4}, + {1, arcs_77_5}, }; static arc arcs_78_0[1] = { - {24, 1}, + {92, 1}, }; -static arc arcs_78_1[2] = { - {30, 0}, - {0, 1}, +static arc arcs_78_1[1] = { + {109, 2}, +}; +static arc arcs_78_2[2] = { + {164, 3}, + {0, 2}, +}; +static arc arcs_78_3[1] = { + {0, 3}, }; -static state states_78[2] = { +static state states_78[4] = { {1, arcs_78_0}, - {2, arcs_78_1}, + {1, arcs_78_1}, + {2, arcs_78_2}, + {1, arcs_78_3}, }; static arc arcs_79_0[1] = { {21, 1}, @@ -1730,11 +1740,11 @@ static state states_80[3] = { }; static dfa dfas[81] = { {256, "single_input", 0, 3, states_0, - "\004\050\060\200\000\000\000\050\370\044\034\144\011\040\004\000\000\103\050\037\202"}, + "\004\050\060\200\000\000\000\240\340\223\160\220\045\200\020\000\000\206\120\076\204"}, {257, "file_input", 0, 2, states_1, - "\204\050\060\200\000\000\000\050\370\044\034\144\011\040\004\000\000\103\050\037\202"}, + "\204\050\060\200\000\000\000\240\340\223\160\220\045\200\020\000\000\206\120\076\204"}, {258, "eval_input", 0, 3, states_2, - "\000\040\040\200\000\000\000\000\000\040\000\000\000\040\004\000\000\103\050\037\000"}, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, {259, "decorator", 0, 7, states_3, "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {260, "decorators", 0, 2, states_4, @@ -1754,139 +1764,139 @@ static dfa dfas[81] = { {267, "vfpdef", 0, 2, states_11, "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {268, "stmt", 0, 2, states_12, - "\000\050\060\200\000\000\000\050\370\044\034\144\011\040\004\000\000\103\050\037\202"}, + "\000\050\060\200\000\000\000\240\340\223\160\220\045\200\020\000\000\206\120\076\204"}, {269, "simple_stmt", 0, 4, states_13, - "\000\040\040\200\000\000\000\050\370\044\034\000\000\040\004\000\000\103\050\037\200"}, + "\000\040\040\200\000\000\000\240\340\223\160\000\000\200\020\000\000\206\120\076\200"}, {270, "small_stmt", 0, 2, states_14, - "\000\040\040\200\000\000\000\050\370\044\034\000\000\040\004\000\000\103\050\037\200"}, + "\000\040\040\200\000\000\000\240\340\223\160\000\000\200\020\000\000\206\120\076\200"}, {271, "expr_stmt", 0, 6, states_15, - "\000\040\040\200\000\000\000\000\000\040\000\000\000\040\004\000\000\103\050\037\000"}, - {272, "augassign", 0, 2, states_16, - "\000\000\000\000\000\200\377\007\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {273, "del_stmt", 0, 3, states_17, - "\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {274, "pass_stmt", 0, 2, states_18, + "\000\040\040\200\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {272, "testlist_star_expr", 0, 3, states_16, + "\000\040\040\200\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {273, "augassign", 0, 2, states_17, + "\000\000\000\000\000\000\376\037\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {274, "del_stmt", 0, 3, states_18, "\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {275, "flow_stmt", 0, 2, states_19, - "\000\000\000\000\000\000\000\000\170\000\000\000\000\000\000\000\000\000\000\000\200"}, - {276, "break_stmt", 0, 2, states_20, - "\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000"}, - {277, "continue_stmt", 0, 2, states_21, - "\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000"}, - {278, "return_stmt", 0, 3, states_22, + {275, "pass_stmt", 0, 2, states_19, + "\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {276, "flow_stmt", 0, 2, states_20, + "\000\000\000\000\000\000\000\000\340\001\000\000\000\000\000\000\000\000\000\000\200"}, + {277, "break_stmt", 0, 2, states_21, "\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000"}, - {279, "yield_stmt", 0, 2, states_23, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200"}, - {280, "raise_stmt", 0, 5, states_24, + {278, "continue_stmt", 0, 2, states_22, "\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000\000\000\000"}, - {281, "import_stmt", 0, 2, states_25, - "\000\000\000\000\000\000\000\000\200\004\000\000\000\000\000\000\000\000\000\000\000"}, - {282, "import_name", 0, 3, states_26, - "\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000"}, - {283, "import_from", 0, 8, states_27, + {279, "return_stmt", 0, 3, states_23, "\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000"}, - {284, "import_as_name", 0, 4, states_28, + {280, "yield_stmt", 0, 2, states_24, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200"}, + {281, "raise_stmt", 0, 5, states_25, + "\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000"}, + {282, "import_stmt", 0, 2, states_26, + "\000\000\000\000\000\000\000\000\000\022\000\000\000\000\000\000\000\000\000\000\000"}, + {283, "import_name", 0, 3, states_27, + "\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000"}, + {284, "import_from", 0, 8, states_28, + "\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000"}, + {285, "import_as_name", 0, 4, states_29, "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {285, "dotted_as_name", 0, 4, states_29, + {286, "dotted_as_name", 0, 4, states_30, "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {286, "import_as_names", 0, 3, states_30, + {287, "import_as_names", 0, 3, states_31, "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {287, "dotted_as_names", 0, 2, states_31, + {288, "dotted_as_names", 0, 2, states_32, "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {288, "dotted_name", 0, 2, states_32, + {289, "dotted_name", 0, 2, states_33, "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {289, "global_stmt", 0, 3, states_33, - "\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000"}, - {290, "nonlocal_stmt", 0, 3, states_34, - "\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000\000"}, - {291, "assert_stmt", 0, 5, states_35, + {290, "global_stmt", 0, 3, states_34, "\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000"}, - {292, "compound_stmt", 0, 2, states_36, - "\000\010\020\000\000\000\000\000\000\000\000\144\011\000\000\000\000\000\000\000\002"}, - {293, "if_stmt", 0, 8, states_37, - "\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000"}, - {294, "while_stmt", 0, 8, states_38, - "\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000"}, - {295, "for_stmt", 0, 10, states_39, - "\000\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000"}, - {296, "try_stmt", 0, 13, states_40, + {291, "nonlocal_stmt", 0, 3, states_35, + "\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000"}, + {292, "assert_stmt", 0, 5, states_36, + "\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000\000"}, + {293, "compound_stmt", 0, 2, states_37, + "\000\010\020\000\000\000\000\000\000\000\000\220\045\000\000\000\000\000\000\000\004"}, + {294, "if_stmt", 0, 8, states_38, + "\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000"}, + {295, "while_stmt", 0, 8, states_39, + "\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000"}, + {296, "for_stmt", 0, 10, states_40, "\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000"}, - {297, "with_stmt", 0, 5, states_41, - "\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000"}, - {298, "with_item", 0, 4, states_42, - "\000\040\040\200\000\000\000\000\000\040\000\000\000\040\004\000\000\103\050\037\000"}, - {299, "except_clause", 0, 5, states_43, - "\000\000\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000"}, - {300, "suite", 0, 5, states_44, - "\004\040\040\200\000\000\000\050\370\044\034\000\000\040\004\000\000\103\050\037\200"}, - {301, "test", 0, 6, states_45, - "\000\040\040\200\000\000\000\000\000\040\000\000\000\040\004\000\000\103\050\037\000"}, - {302, "test_nocond", 0, 2, states_46, - "\000\040\040\200\000\000\000\000\000\040\000\000\000\040\004\000\000\103\050\037\000"}, - {303, "lambdef", 0, 5, states_47, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000"}, - {304, "lambdef_nocond", 0, 5, states_48, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000"}, - {305, "or_test", 0, 2, states_49, - "\000\040\040\200\000\000\000\000\000\040\000\000\000\000\004\000\000\103\050\037\000"}, - {306, "and_test", 0, 2, states_50, - "\000\040\040\200\000\000\000\000\000\040\000\000\000\000\004\000\000\103\050\037\000"}, - {307, "not_test", 0, 3, states_51, - "\000\040\040\200\000\000\000\000\000\040\000\000\000\000\004\000\000\103\050\037\000"}, - {308, "comparison", 0, 2, states_52, - "\000\040\040\200\000\000\000\000\000\040\000\000\000\000\000\000\000\103\050\037\000"}, - {309, "comp_op", 0, 4, states_53, - "\000\000\000\000\000\000\000\000\000\000\000\200\000\000\304\077\000\000\000\000\000"}, - {310, "star_expr", 0, 3, states_54, - "\000\040\040\200\000\000\000\000\000\040\000\000\000\000\000\000\000\103\050\037\000"}, - {311, "expr", 0, 2, states_55, - "\000\040\040\000\000\000\000\000\000\040\000\000\000\000\000\000\000\103\050\037\000"}, - {312, "xor_expr", 0, 2, states_56, - "\000\040\040\000\000\000\000\000\000\040\000\000\000\000\000\000\000\103\050\037\000"}, - {313, "and_expr", 0, 2, states_57, - "\000\040\040\000\000\000\000\000\000\040\000\000\000\000\000\000\000\103\050\037\000"}, - {314, "shift_expr", 0, 2, states_58, - "\000\040\040\000\000\000\000\000\000\040\000\000\000\000\000\000\000\103\050\037\000"}, - {315, "arith_expr", 0, 2, states_59, - "\000\040\040\000\000\000\000\000\000\040\000\000\000\000\000\000\000\103\050\037\000"}, - {316, "term", 0, 2, states_60, - "\000\040\040\000\000\000\000\000\000\040\000\000\000\000\000\000\000\103\050\037\000"}, - {317, "factor", 0, 3, states_61, - "\000\040\040\000\000\000\000\000\000\040\000\000\000\000\000\000\000\103\050\037\000"}, - {318, "power", 0, 4, states_62, - "\000\040\040\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\050\037\000"}, - {319, "atom", 0, 9, states_63, - "\000\040\040\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\050\037\000"}, - {320, "testlist_comp", 0, 5, states_64, - "\000\040\040\200\000\000\000\000\000\040\000\000\000\040\004\000\000\103\050\037\000"}, - {321, "trailer", 0, 7, states_65, - "\000\040\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\010\000\000"}, - {322, "subscriptlist", 0, 3, states_66, - "\000\040\040\202\000\000\000\000\000\040\000\000\000\040\004\000\000\103\050\037\000"}, - {323, "subscript", 0, 5, states_67, - "\000\040\040\202\000\000\000\000\000\040\000\000\000\040\004\000\000\103\050\037\000"}, - {324, "sliceop", 0, 3, states_68, + {297, "try_stmt", 0, 13, states_41, + "\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000"}, + {298, "with_stmt", 0, 5, states_42, + "\000\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000"}, + {299, "with_item", 0, 4, states_43, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {300, "except_clause", 0, 5, states_44, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000"}, + {301, "suite", 0, 5, states_45, + "\004\040\040\200\000\000\000\240\340\223\160\000\000\200\020\000\000\206\120\076\200"}, + {302, "test", 0, 6, states_46, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {303, "test_nocond", 0, 2, states_47, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {304, "lambdef", 0, 5, states_48, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000"}, + {305, "lambdef_nocond", 0, 5, states_49, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000"}, + {306, "or_test", 0, 2, states_50, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\020\000\000\206\120\076\000"}, + {307, "and_test", 0, 2, states_51, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\020\000\000\206\120\076\000"}, + {308, "not_test", 0, 3, states_52, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\020\000\000\206\120\076\000"}, + {309, "comparison", 0, 2, states_53, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + {310, "comp_op", 0, 4, states_54, + "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\220\177\000\000\000\000\000"}, + {311, "star_expr", 0, 3, states_55, + "\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {312, "expr", 0, 2, states_56, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + {313, "xor_expr", 0, 2, states_57, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + {314, "and_expr", 0, 2, states_58, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + {315, "shift_expr", 0, 2, states_59, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + {316, "arith_expr", 0, 2, states_60, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + {317, "term", 0, 2, states_61, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + {318, "factor", 0, 3, states_62, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + {319, "power", 0, 4, states_63, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\120\076\000"}, + {320, "atom", 0, 9, states_64, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\120\076\000"}, + {321, "testlist_comp", 0, 5, states_65, + "\000\040\040\200\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {322, "trailer", 0, 7, states_66, + "\000\040\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\020\000\000"}, + {323, "subscriptlist", 0, 3, states_67, + "\000\040\040\002\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {324, "subscript", 0, 5, states_68, + "\000\040\040\002\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {325, "sliceop", 0, 3, states_69, "\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {325, "exprlist", 0, 3, states_69, - "\000\040\040\200\000\000\000\000\000\040\000\000\000\000\000\000\000\103\050\037\000"}, - {326, "testlist", 0, 3, states_70, - "\000\040\040\200\000\000\000\000\000\040\000\000\000\040\004\000\000\103\050\037\000"}, - {327, "dictorsetmaker", 0, 11, states_71, - "\000\040\040\200\000\000\000\000\000\040\000\000\000\040\004\000\000\103\050\037\000"}, - {328, "classdef", 0, 8, states_72, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002"}, - {329, "arglist", 0, 8, states_73, - "\000\040\040\200\001\000\000\000\000\040\000\000\000\040\004\000\000\103\050\037\000"}, - {330, "argument", 0, 4, states_74, - "\000\040\040\200\000\000\000\000\000\040\000\000\000\040\004\000\000\103\050\037\000"}, - {331, "comp_iter", 0, 2, states_75, - "\000\000\000\000\000\000\000\000\000\000\000\104\000\000\000\000\000\000\000\000\000"}, - {332, "comp_for", 0, 6, states_76, - "\000\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000"}, - {333, "comp_if", 0, 4, states_77, - "\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000"}, - {334, "testlist1", 0, 2, states_78, - "\000\040\040\200\000\000\000\000\000\040\000\000\000\040\004\000\000\103\050\037\000"}, + {326, "exprlist", 0, 3, states_70, + "\000\040\040\200\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + {327, "testlist", 0, 3, states_71, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {328, "dictorsetmaker", 0, 11, states_72, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {329, "classdef", 0, 8, states_73, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004"}, + {330, "arglist", 0, 8, states_74, + "\000\040\040\200\001\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {331, "argument", 0, 4, states_75, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {332, "comp_iter", 0, 2, states_76, + "\000\000\000\000\000\000\000\000\000\000\000\020\001\000\000\000\000\000\000\000\000"}, + {333, "comp_for", 0, 6, states_77, + "\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000"}, + {334, "comp_if", 0, 4, states_78, + "\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000"}, {335, "encoding_decl", 0, 2, states_79, "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {336, "yield_expr", 0, 3, states_80, @@ -1897,29 +1907,29 @@ static label labels[168] = { {256, 0}, {4, 0}, {269, 0}, - {292, 0}, + {293, 0}, {257, 0}, {268, 0}, {0, 0}, {258, 0}, - {326, 0}, + {327, 0}, {259, 0}, {50, 0}, - {288, 0}, + {289, 0}, {7, 0}, - {329, 0}, + {330, 0}, {8, 0}, {260, 0}, {261, 0}, - {328, 0}, + {329, 0}, {262, 0}, {1, "def"}, {1, 0}, {263, 0}, {51, 0}, - {301, 0}, + {302, 0}, {11, 0}, - {300, 0}, + {301, 0}, {264, 0}, {265, 0}, {22, 0}, @@ -1931,15 +1941,17 @@ static label labels[168] = { {270, 0}, {13, 0}, {271, 0}, - {273, 0}, {274, 0}, {275, 0}, - {281, 0}, - {289, 0}, + {276, 0}, + {282, 0}, {290, 0}, {291, 0}, + {292, 0}, {272, 0}, + {273, 0}, {336, 0}, + {311, 0}, {37, 0}, {38, 0}, {39, 0}, @@ -1953,36 +1965,36 @@ static label labels[168] = { {47, 0}, {49, 0}, {1, "del"}, - {325, 0}, + {326, 0}, {1, "pass"}, - {276, 0}, {277, 0}, {278, 0}, - {280, 0}, {279, 0}, + {281, 0}, + {280, 0}, {1, "break"}, {1, "continue"}, {1, "return"}, {1, "raise"}, {1, "from"}, - {282, 0}, {283, 0}, + {284, 0}, {1, "import"}, - {287, 0}, + {288, 0}, {23, 0}, {52, 0}, - {286, 0}, - {284, 0}, - {1, "as"}, + {287, 0}, {285, 0}, + {1, "as"}, + {286, 0}, {1, "global"}, {1, "nonlocal"}, {1, "assert"}, - {293, 0}, {294, 0}, {295, 0}, {296, 0}, {297, 0}, + {298, 0}, {1, "if"}, {1, "elif"}, {1, "else"}, @@ -1990,27 +2002,26 @@ static label labels[168] = { {1, "for"}, {1, "in"}, {1, "try"}, - {299, 0}, + {300, 0}, {1, "finally"}, {1, "with"}, - {298, 0}, - {311, 0}, + {299, 0}, + {312, 0}, {1, "except"}, {5, 0}, {6, 0}, - {305, 0}, - {303, 0}, - {302, 0}, + {306, 0}, {304, 0}, + {303, 0}, + {305, 0}, {1, "lambda"}, - {306, 0}, - {1, "or"}, {307, 0}, + {1, "or"}, + {308, 0}, {1, "and"}, {1, "not"}, - {308, 0}, - {310, 0}, {309, 0}, + {310, 0}, {20, 0}, {21, 0}, {28, 0}, @@ -2019,45 +2030,44 @@ static label labels[168] = { {29, 0}, {29, 0}, {1, "is"}, - {312, 0}, - {18, 0}, {313, 0}, - {33, 0}, + {18, 0}, {314, 0}, - {19, 0}, + {33, 0}, {315, 0}, + {19, 0}, + {316, 0}, {34, 0}, {35, 0}, - {316, 0}, + {317, 0}, {14, 0}, {15, 0}, - {317, 0}, + {318, 0}, {17, 0}, {24, 0}, {48, 0}, {32, 0}, - {318, 0}, {319, 0}, - {321, 0}, {320, 0}, + {322, 0}, + {321, 0}, {9, 0}, {10, 0}, {26, 0}, - {327, 0}, + {328, 0}, {27, 0}, {2, 0}, {3, 0}, {1, "None"}, {1, "True"}, {1, "False"}, - {332, 0}, - {322, 0}, + {333, 0}, {323, 0}, {324, 0}, + {325, 0}, {1, "class"}, - {330, 0}, {331, 0}, - {333, 0}, + {332, 0}, {334, 0}, {335, 0}, {1, "yield"}, -- cgit v1.2.1 From 07194b1ca66cd745689e24253b5f2a9288807e6e Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 27 Sep 2009 14:08:59 +0000 Subject: star_expr now always has two nodes --- Python/ast.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index 97b57ec100..dfcc8e32e1 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -1889,9 +1889,7 @@ ast_for_expr(struct compiling *c, const node *n) break; case star_expr: - if (TYPE(CHILD(n, 0)) == STAR) - return ast_for_starred(c, n); - /* Fall through to generic case. */ + return ast_for_starred(c, n); /* The next five cases all handle BinOps. The main body of code is the same in each case, but the switch turned inside out to reuse the code for each type of operator. -- cgit v1.2.1 From a3bf94243351f14c50e2df4cd059aa4385c864da Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Tue, 29 Sep 2009 19:21:35 +0000 Subject: Merged revisions 75141 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r75141 | mark.dickinson | 2009-09-29 20:01:06 +0100 (Tue, 29 Sep 2009) | 3 lines Issue #7019: Unmarshalling of bad long data could produce unnormalized PyLongs. Raise ValueError instead. ........ --- Python/marshal.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/marshal.c b/Python/marshal.c index 54d19d5de3..256285b426 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -553,7 +553,7 @@ static PyObject * r_PyLong(RFILE *p) { PyLongObject *ob; - int size, i, j, md; + int size, i, j, md, shorts_in_top_digit; long n; digit d; @@ -566,7 +566,8 @@ r_PyLong(RFILE *p) return NULL; } - size = 1 + (ABS(n)-1) / PyLong_MARSHAL_RATIO; + size = 1 + (ABS(n) - 1) / PyLong_MARSHAL_RATIO; + shorts_in_top_digit = 1 + (ABS(n) - 1) % PyLong_MARSHAL_RATIO; ob = _PyLong_New(size); if (ob == NULL) return NULL; @@ -583,12 +584,21 @@ r_PyLong(RFILE *p) ob->ob_digit[i] = d; } d = 0; - for (j=0; j < (ABS(n)-1)%PyLong_MARSHAL_RATIO + 1; j++) { + for (j=0; j < shorts_in_top_digit; j++) { md = r_short(p); if (md < 0 || md > PyLong_MARSHAL_BASE) goto bad_digit; + /* topmost marshal digit should be nonzero */ + if (md == 0 && j == shorts_in_top_digit - 1) { + Py_DECREF(ob); + PyErr_SetString(PyExc_ValueError, + "bad marshal data (unnormalized long data)"); + return NULL; + } d += (digit)md << j*PyLong_MARSHAL_SHIFT; } + /* top digit should be nonzero, else the resulting PyLong won't be + normalized */ ob->ob_digit[size-1] = d; return (PyObject *)ob; bad_digit: -- cgit v1.2.1 From 8ebdcc791be8e8b529665fc9b923d031629c408b Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Sat, 3 Oct 2009 16:14:07 +0000 Subject: silence with (void) two warnings about computed and unused value of POP() --- Python/ceval.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 003d4dfd17..dd378d6cc4 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2509,13 +2509,13 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) PyObject *exit_func; u = TOP(); if (u == Py_None) { - POP(); + (void)POP(); exit_func = TOP(); SET_TOP(u); v = w = Py_None; } else if (PyLong_Check(u)) { - POP(); + (void)POP(); switch(PyLong_AsLong(u)) { case WHY_RETURN: case WHY_CONTINUE: -- cgit v1.2.1 From c7963af8d161e72e93509de6445d06bad6967ecf Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 3 Oct 2009 20:27:13 +0000 Subject: Merged revisions 75223 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r75223 | benjamin.peterson | 2009-10-03 15:23:24 -0500 (Sat, 03 Oct 2009) | 1 line #7050 fix a SystemError when using tuple unpacking and augmented assignment ........ --- Python/ast.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index dfcc8e32e1..8a35a1206f 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -2115,6 +2115,19 @@ ast_for_expr_stmt(struct compiling *c, const node *n) return NULL; if(!set_context(c, expr1, Store, ch)) return NULL; + /* set_context checks that most expressions are not the left side. + Augmented assignments can only have a name, a subscript, or an + attribute on the left, though, so we have to explicitly check for + those. */ + switch (expr1->kind) { + case Name_kind: + case Attribute_kind: + case Subscript_kind: + break; + default: + ast_error(ch, "illegal expression for augmented assignment"); + return NULL; + } ch = CHILD(n, 2); if (TYPE(ch) == testlist) -- cgit v1.2.1 From c7dcd39e217f6889a925cc9cd80c2f29594bbefb Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 4 Oct 2009 20:32:25 +0000 Subject: Merged revisions 74841 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r74841 | thomas.wouters | 2009-09-16 14:55:54 -0500 (Wed, 16 Sep 2009) | 23 lines Fix issue #1590864, multiple threads and fork() can cause deadlocks, by acquiring the import lock around fork() calls. This prevents other threads from having that lock while the fork happens, and is the recommended way of dealing with such issues. There are two other locks we care about, the GIL and the Thread Local Storage lock. The GIL is obviously held when calling Python functions like os.fork(), and the TLS lock is explicitly reallocated instead, while also deleting now-orphaned TLS data. This only fixes calls to os.fork(), not extension modules or embedding programs calling C's fork() directly. Solving that requires a new set of API functions, and possibly a rewrite of the Python/thread_*.c mess. Add a warning explaining the problem to the documentation in the mean time. This also changes behaviour a little on AIX. Before, AIX (but only AIX) was getting the import lock reallocated, seemingly to avoid this very same problem. This is not the right approach, because the import lock is a re-entrant one, and reallocating would do the wrong thing when forking while holding the import lock. Will backport to 2.6, minus the tiny AIX behaviour change. ........ --- Python/import.c | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 2ae5fa7f6f..62142aea26 100644 --- a/Python/import.c +++ b/Python/import.c @@ -262,8 +262,8 @@ static PyThread_type_lock import_lock = 0; static long import_lock_thread = -1; static int import_lock_level = 0; -static void -lock_import(void) +void +_PyImport_AcquireLock(void) { long me = PyThread_get_thread_ident(); if (me == -1) @@ -287,8 +287,8 @@ lock_import(void) import_lock_level = 1; } -static int -unlock_import(void) +int +_PyImport_ReleaseLock(void) { long me = PyThread_get_thread_ident(); if (me == -1 || import_lock == NULL) @@ -303,23 +303,16 @@ unlock_import(void) return 1; } -/* This function is called from PyOS_AfterFork to ensure that newly - created child processes do not share locks with the parent. */ +/* This function used to be called from PyOS_AfterFork to ensure that newly + created child processes do not share locks with the parent, but for some + reason only on AIX systems. Instead of re-initializing the lock, we now + acquire the import lock around fork() calls. */ 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 * @@ -336,7 +329,7 @@ static PyObject * imp_acquire_lock(PyObject *self, PyObject *noargs) { #ifdef WITH_THREAD - lock_import(); + _PyImport_AcquireLock(); #endif Py_INCREF(Py_None); return Py_None; @@ -346,7 +339,7 @@ static PyObject * imp_release_lock(PyObject *self, PyObject *noargs) { #ifdef WITH_THREAD - if (unlock_import() < 0) { + if (_PyImport_ReleaseLock() < 0) { PyErr_SetString(PyExc_RuntimeError, "not holding the import lock"); return NULL; @@ -2201,9 +2194,9 @@ PyImport_ImportModuleLevel(char *name, PyObject *globals, PyObject *locals, PyObject *fromlist, int level) { PyObject *result; - lock_import(); + _PyImport_AcquireLock(); result = import_module_level(name, globals, locals, fromlist, level); - if (unlock_import() < 0) { + if (_PyImport_ReleaseLock() < 0) { Py_XDECREF(result); PyErr_SetString(PyExc_RuntimeError, "not holding the import lock"); -- cgit v1.2.1 From f960e3d89e9df749e709998d6d0d12d962224132 Mon Sep 17 00:00:00 2001 From: Neil Schemenauer Date: Wed, 14 Oct 2009 19:14:38 +0000 Subject: Issue #1754094: Improve the stack depth calculation in the compiler. There should be no other effect than a small decrease in memory use. --- Python/compile.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/compile.c b/Python/compile.c index 24975b64a7..d06a03b907 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -772,7 +772,7 @@ opcode_stack_effect(int opcode, int oparg) case UNPACK_EX: return (oparg&0xFF) + (oparg>>8); case FOR_ITER: - return 1; + return 1; /* or -1, at end of iterator */ case STORE_ATTR: return -2; @@ -799,7 +799,7 @@ opcode_stack_effect(int opcode, int oparg) case COMPARE_OP: return -1; case IMPORT_NAME: - return 0; + return -1; case IMPORT_FROM: return 1; @@ -3546,7 +3546,7 @@ dfs(struct compiler *c, basicblock *b, struct assembler *a) static int stackdepth_walk(struct compiler *c, basicblock *b, int depth, int maxdepth) { - int i; + int i, target_depth; struct instr *instr; if (b->b_seen || b->b_startdepth >= depth) return maxdepth; @@ -3559,8 +3559,17 @@ stackdepth_walk(struct compiler *c, basicblock *b, int depth, int maxdepth) maxdepth = depth; assert(depth >= 0); /* invalid code or bug in stackdepth() */ if (instr->i_jrel || instr->i_jabs) { + target_depth = depth; + if (instr->i_opcode == FOR_ITER) { + target_depth = depth-2; + } else if (instr->i_opcode == SETUP_FINALLY || + instr->i_opcode == SETUP_EXCEPT) { + target_depth = depth+3; + if (target_depth > maxdepth) + maxdepth = target_depth; + } maxdepth = stackdepth_walk(c, instr->i_target, - depth, maxdepth); + target_depth, maxdepth); if (instr->i_opcode == JUMP_ABSOLUTE || instr->i_opcode == JUMP_FORWARD) { goto out; /* remaining code is dead */ -- cgit v1.2.1 From 26d8fbd945451134d1527e2367c436e01395e0c6 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Thu, 15 Oct 2009 19:55:18 +0000 Subject: Merged revisions 75440 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r75440 | mark.dickinson | 2009-10-15 18:45:39 +0100 (Thu, 15 Oct 2009) | 1 line Allow core Python build to succeed under WITHOUT_COMPLEX. The module build stage still fails. ........ --- Python/compile.c | 9 ++++++--- Python/formatter_unicode.c | 2 ++ 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/compile.c b/Python/compile.c index d06a03b907..081268bcac 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -895,10 +895,8 @@ compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o) { PyObject *t, *v; Py_ssize_t arg; - unsigned char *p, *q; - Py_complex z; + unsigned char *p; double d; - int real_part_zero, imag_part_zero; /* necessary to make sure types aren't coerced (e.g., int and long) */ /* _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms */ @@ -913,7 +911,11 @@ compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o) else t = PyTuple_Pack(2, o, o->ob_type); } +#ifndef WITHOUT_COMPLEX else if (PyComplex_Check(o)) { + Py_complex z; + int real_part_zero, imag_part_zero; + unsigned char *q; /* complex case is even messier: we need to make complex(x, 0.) different from complex(x, -0.) and complex(0., y) different from complex(-0., y), for any x and y. In @@ -943,6 +945,7 @@ compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o) t = PyTuple_Pack(2, o, o->ob_type); } } +#endif /* WITHOUT_COMPLEX */ else { t = PyTuple_Pack(2, o, o->ob_type); } diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index c350907da1..79cb5f9192 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -9,6 +9,8 @@ #define FORMAT_STRING _PyUnicode_FormatAdvanced #define FORMAT_LONG _PyLong_FormatAdvanced #define FORMAT_FLOAT _PyFloat_FormatAdvanced +#ifndef WITHOUT_COMPLEX #define FORMAT_COMPLEX _PyComplex_FormatAdvanced +#endif #include "../Objects/stringlib/formatter.h" -- cgit v1.2.1 From 94be56fe981742b8657e2f07ecb86b5aca70711c Mon Sep 17 00:00:00 2001 From: Skip Montanaro Date: Sun, 18 Oct 2009 14:25:35 +0000 Subject: Issue 7147 - remove ability to attempt to build Python without complex number support (was broken anyway) --- Python/ast.c | 6 ------ Python/bltinmodule.c | 2 -- Python/getargs.c | 4 ---- Python/marshal.c | 4 ---- Python/modsupport.c | 2 -- 5 files changed, 18 deletions(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index 8a35a1206f..c3edea3534 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -3177,17 +3177,13 @@ parsenumber(struct compiling *c, const char *s) const char *end; long x; double dx; -#ifndef WITHOUT_COMPLEX Py_complex compl; int imflag; -#endif assert(s != NULL); errno = 0; end = s + strlen(s) - 1; -#ifndef WITHOUT_COMPLEX imflag = *end == 'j' || *end == 'J'; -#endif if (s[0] == '0') { x = (long) PyOS_strtoul((char *)s, (char **)&end, 0); if (x < 0 && errno == 0) { @@ -3204,7 +3200,6 @@ parsenumber(struct compiling *c, const char *s) return PyLong_FromLong(x); } /* XXX Huge floats may silently fail */ -#ifndef WITHOUT_COMPLEX if (imflag) { compl.real = 0.; compl.imag = PyOS_string_to_double(s, (char **)&end, NULL); @@ -3213,7 +3208,6 @@ parsenumber(struct compiling *c, const char *s) return PyComplex_FromCComplex(compl); } else -#endif { dx = PyOS_string_to_double(s, NULL, NULL); if (dx == -1.0 && PyErr_Occurred()) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 2224d3722f..ab6049cabf 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -2302,9 +2302,7 @@ _PyBuiltin_Init(void) SETBUILTIN("bytearray", &PyByteArray_Type); SETBUILTIN("bytes", &PyBytes_Type); SETBUILTIN("classmethod", &PyClassMethod_Type); -#ifndef WITHOUT_COMPLEX SETBUILTIN("complex", &PyComplex_Type); -#endif SETBUILTIN("dict", &PyDict_Type); SETBUILTIN("enumerate", &PyEnum_Type); SETBUILTIN("filter", &PyFilter_Type); diff --git a/Python/getargs.c b/Python/getargs.c index 486cf7d07d..f41cd05eaf 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -818,7 +818,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, break; } -#ifndef WITHOUT_COMPLEX case 'D': {/* complex double */ Py_complex *p = va_arg(*p_va, Py_complex *); Py_complex cval; @@ -829,7 +828,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, *p = cval; break; } -#endif /* WITHOUT_COMPLEX */ case 'c': {/* char */ char *p = va_arg(*p_va, char *); @@ -1772,9 +1770,7 @@ skipitem(const char **p_format, va_list *p_va, int flags) #endif case 'f': /* float */ case 'd': /* double */ -#ifndef WITHOUT_COMPLEX case 'D': /* complex double */ -#endif case 'c': /* char */ { (void) va_arg(*p_va, void *); diff --git a/Python/marshal.c b/Python/marshal.c index 256285b426..3391085ccb 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -254,7 +254,6 @@ w_object(PyObject *v, WFILE *p) PyMem_Free(buf); } } -#ifndef WITHOUT_COMPLEX else if (PyComplex_CheckExact(v)) { if (p->version > 1) { unsigned char buf[8]; @@ -297,7 +296,6 @@ w_object(PyObject *v, WFILE *p) PyMem_Free(buf); } } -#endif else if (PyBytes_CheckExact(v)) { w_byte(TYPE_STRING, p); n = PyBytes_GET_SIZE(v); @@ -714,7 +712,6 @@ r_object(RFILE *p) break; } -#ifndef WITHOUT_COMPLEX case TYPE_COMPLEX: { char buf[256]; @@ -773,7 +770,6 @@ r_object(RFILE *p) retval = PyComplex_FromCComplex(c); break; } -#endif case TYPE_STRING: n = r_long(p); diff --git a/Python/modsupport.c b/Python/modsupport.c index 0cbc6f7cfb..0f31634a78 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -279,11 +279,9 @@ do_mkvalue(const char **p_format, va_list *p_va, int flags) 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': { -- cgit v1.2.1 From e4216a84485c97ae3ff3c9fcd27feba89513fc27 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sun, 18 Oct 2009 16:41:32 +0000 Subject: Remove the uses of WITHOUT_COMPLEX introduced in r75471 --- Python/compile.c | 2 -- Python/formatter_unicode.c | 2 -- 2 files changed, 4 deletions(-) (limited to 'Python') diff --git a/Python/compile.c b/Python/compile.c index 081268bcac..2bb9beb3d8 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -911,7 +911,6 @@ compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o) else t = PyTuple_Pack(2, o, o->ob_type); } -#ifndef WITHOUT_COMPLEX else if (PyComplex_Check(o)) { Py_complex z; int real_part_zero, imag_part_zero; @@ -945,7 +944,6 @@ compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o) t = PyTuple_Pack(2, o, o->ob_type); } } -#endif /* WITHOUT_COMPLEX */ else { t = PyTuple_Pack(2, o, o->ob_type); } diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index 79cb5f9192..c350907da1 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -9,8 +9,6 @@ #define FORMAT_STRING _PyUnicode_FormatAdvanced #define FORMAT_LONG _PyLong_FormatAdvanced #define FORMAT_FLOAT _PyFloat_FormatAdvanced -#ifndef WITHOUT_COMPLEX #define FORMAT_COMPLEX _PyComplex_FormatAdvanced -#endif #include "../Objects/stringlib/formatter.h" -- cgit v1.2.1 From f10b60500f32a7f9b014d5aa0df36edea83c210c Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Tue, 20 Oct 2009 21:52:47 +0000 Subject: Merged revisions 75570 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r75570 | antoine.pitrou | 2009-10-20 23:29:37 +0200 (mar., 20 oct. 2009) | 6 lines Issue #1722344: threading._shutdown() is now called in Py_Finalize(), which fixes the problem of some exceptions being thrown at shutdown when the interpreter is killed. Patch by Adam Olsen. ........ --- Python/pythonrun.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index e7a051288d..875e44e99b 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -18,6 +18,7 @@ #include "eval.h" #include "marshal.h" #include "osdefs.h" +#include "abstract.h" #ifdef HAVE_SIGNAL_H #include @@ -66,6 +67,7 @@ static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *, static void err_input(perrdetail *); static void initsigs(void); static void call_py_exitfuncs(void); +static void wait_for_thread_shutdown(void); static void call_ll_exitfuncs(void); extern void _PyUnicode_Init(void); extern void _PyUnicode_Fini(void); @@ -363,6 +365,8 @@ Py_Finalize(void) if (!initialized) return; + wait_for_thread_shutdown(); + /* 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 @@ -2059,6 +2063,34 @@ call_py_exitfuncs(void) PyErr_Clear(); } +/* Wait until threading._shutdown completes, provided + the threading module was imported in the first place. + The shutdown routine will wait until all non-daemon + "threading" threads have completed. */ +static void +wait_for_thread_shutdown(void) +{ +#ifdef WITH_THREAD + PyObject *result; + PyThreadState *tstate = PyThreadState_GET(); + PyObject *threading = PyMapping_GetItemString(tstate->interp->modules, + "threading"); + if (threading == NULL) { + /* threading not imported */ + PyErr_Clear(); + return; + } + result = PyObject_CallMethod(threading, "_shutdown", ""); + if (result == NULL) { + PyErr_WriteUnraisable(threading); + } + else { + Py_DECREF(result); + } + Py_DECREF(threading); +#endif +} + #define NEXITFUNCS 32 static void (*exitfuncs[NEXITFUNCS])(void); static int nexitfuncs = 0; -- cgit v1.2.1 From 2af1d72a116233f3774a629f4fb822a79a40db84 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Thu, 22 Oct 2009 11:22:50 +0000 Subject: Peephole constant folding had missed UNARY_POSITIVE. --- Python/peephole.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Python') diff --git a/Python/peephole.c b/Python/peephole.c index 9163091272..104db8cb97 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -197,6 +197,9 @@ fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts) case UNARY_INVERT: newconst = PyNumber_Invert(v); break; + case UNARY_POSITIVE: + newconst = PyNumber_Positive(v); + break; default: /* Called with an unknown opcode */ PyErr_Format(PyExc_SystemError, @@ -500,6 +503,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */ case UNARY_NEGATIVE: case UNARY_INVERT: + case UNARY_POSITIVE: if (lastlc >= 1 && ISBASICBLOCK(blocks, i-3, 4) && fold_unaryops_on_constants(&codestr[i-3], consts)) { -- cgit v1.2.1 From 75346d5209e0c3e982fb175e08ecb6da54c044a8 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sat, 24 Oct 2009 20:11:21 +0000 Subject: Remove AtheOS support, as per PEP 11 (which claims that all code was removed in Python 3.0). --- Python/dynload_atheos.c | 47 -------- Python/thread.c | 4 - Python/thread_atheos.h | 300 ------------------------------------------------ 3 files changed, 351 deletions(-) delete mode 100644 Python/dynload_atheos.c delete mode 100644 Python/thread_atheos.h (limited to 'Python') diff --git a/Python/dynload_atheos.c b/Python/dynload_atheos.c deleted file mode 100644 index b01fdfa004..0000000000 --- a/Python/dynload_atheos.c +++ /dev/null @@ -1,47 +0,0 @@ - -/* Support for dynamic loading of extension modules */ - -#include -#include - -#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), "PyInit_%.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/Python/thread.c b/Python/thread.c index 1d7bed972f..c440d43ee5 100644 --- a/Python/thread.c +++ b/Python/thread.c @@ -137,10 +137,6 @@ static size_t _pythread_stacksize = 0; #include "thread_plan9.h" #endif -#ifdef ATHEOS_THREADS -#include "thread_atheos.h" -#endif - /* #ifdef FOOBAR_THREADS #include "thread_foobar.h" diff --git a/Python/thread_atheos.h b/Python/thread_atheos.h deleted file mode 100644 index c9f5e23189..0000000000 --- a/Python/thread_atheos.h +++ /dev/null @@ -1,300 +0,0 @@ -/* Threading for AtheOS. - Based on thread_beos.h. */ - -#include -#include -#include -#include -#include - -/* 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 -} -- cgit v1.2.1 From a074dd040afda08292d427b60d6835e477662231 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sat, 24 Oct 2009 20:24:16 +0000 Subject: Disable support for Mach C Threads. --- Python/thread.c | 1 + 1 file changed, 1 insertion(+) (limited to 'Python') diff --git a/Python/thread.c b/Python/thread.c index c440d43ee5..5b8ec10b5c 100644 --- a/Python/thread.c +++ b/Python/thread.c @@ -122,6 +122,7 @@ static size_t _pythread_stacksize = 0; #endif #ifdef C_THREADS +#error Mach C Threads are now unsupported, and code will be removed in 3.3. #include "thread_cthread.h" #endif -- cgit v1.2.1 From 6f7971351b0484fca0ae17f74dd3eac6994902cd Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sat, 24 Oct 2009 20:30:34 +0000 Subject: Disable support for SunOS LWP --- Python/thread.c | 1 + 1 file changed, 1 insertion(+) (limited to 'Python') diff --git a/Python/thread.c b/Python/thread.c index 5b8ec10b5c..acb2103884 100644 --- a/Python/thread.c +++ b/Python/thread.c @@ -109,6 +109,7 @@ static size_t _pythread_stacksize = 0; #endif #ifdef SUN_LWP +#error SunOS lightweight processes are now unsupported, and code will be removed in 3.3. #include "thread_lwp.h" #endif -- cgit v1.2.1 From df312333c2011f462ad06f998263706e46995dc7 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sat, 24 Oct 2009 20:35:52 +0000 Subject: Disable GNU pth support --- Python/thread.c | 1 + 1 file changed, 1 insertion(+) (limited to 'Python') diff --git a/Python/thread.c b/Python/thread.c index acb2103884..f5722a7f13 100644 --- a/Python/thread.c +++ b/Python/thread.c @@ -114,6 +114,7 @@ static size_t _pythread_stacksize = 0; #endif #ifdef HAVE_PTH +#error GNU pth threads are now unsupported, and code will be removed in 3.3. #include "thread_pth.h" #undef _POSIX_THREADS #endif -- cgit v1.2.1 From 2489e2c722274e0424466615053d0da998766ac4 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sat, 24 Oct 2009 20:43:49 +0000 Subject: Disable support for Irix threads --- Python/thread.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'Python') diff --git a/Python/thread.c b/Python/thread.c index f5722a7f13..a839481b4f 100644 --- a/Python/thread.c +++ b/Python/thread.c @@ -23,12 +23,6 @@ #include -#ifdef __sgi -#ifndef HAVE_PTHREAD_H /* XXX Need to check in configure.in */ -#undef _POSIX_THREADS -#endif -#endif - #include "pythread.h" #ifndef _POSIX_THREADS @@ -101,6 +95,7 @@ PyThread_init_thread(void) static size_t _pythread_stacksize = 0; #ifdef SGI_THREADS +#error SGI Irix threads are now unsupported, and code will be removed in 3.3. #include "thread_sgi.h" #endif -- cgit v1.2.1 From c1167993c92727782dc01ad95bed37dbaf015640 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Mon, 26 Oct 2009 14:19:42 +0000 Subject: Merged revisions 75714 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r75714 | mark.dickinson | 2009-10-26 14:18:44 +0000 (Mon, 26 Oct 2009) | 1 line Warn against replacing PyNumber_Add with PyNumber_InPlaceAdd in sum ........ --- Python/bltinmodule.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index ab6049cabf..297c795ca3 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1958,6 +1958,15 @@ builtin_sum(PyObject *self, PyObject *args) } break; } + /* It's tempting to use PyNumber_InPlaceAdd instead of + PyNumber_Add here, to avoid quadratic running time + when doing 'sum(list_of_lists, [])'. However, this + would produce a change in behaviour: a snippet like + + empty = [] + sum([[x] for x in range(10)], empty) + + would change the value of empty. */ temp = PyNumber_Add(result, item); Py_DECREF(result); Py_DECREF(item); -- cgit v1.2.1 From 95c5a78877168ea54ff75b0a10cdc301c02a05d9 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Mon, 26 Oct 2009 14:36:29 +0000 Subject: Move some comments to more appropriate places --- Python/pystrtod.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'Python') diff --git a/Python/pystrtod.c b/Python/pystrtod.c index 95c0ff6376..d1eb71d7b8 100644 --- a/Python/pystrtod.c +++ b/Python/pystrtod.c @@ -3,11 +3,8 @@ #include #include -/* _Py_parse_inf_or_nan: Attempt to parse a string of the form "nan", "inf" or - "infinity", with an optional leading sign of "+" or "-". On success, - return the NaN or Infinity as a double and set *endptr to point just beyond - the successfully parsed portion of the string. On failure, return -1.0 and - set *endptr to point to the start of the string. */ +/* Case-insensitive string match used for nan and inf detection; t should be + lower-case. Returns 1 for a successful match, 0 otherwise. */ static int case_insensitive_match(const char *s, const char *t) @@ -19,6 +16,12 @@ case_insensitive_match(const char *s, const char *t) return *t ? 0 : 1; } +/* _Py_parse_inf_or_nan: Attempt to parse a string of the form "nan", "inf" or + "infinity", with an optional leading sign of "+" or "-". On success, + return the NaN or Infinity as a double and set *endptr to point just beyond + the successfully parsed portion of the string. On failure, return -1.0 and + set *endptr to point to the start of the string. */ + double _Py_parse_inf_or_nan(const char *p, char **endptr) { -- cgit v1.2.1 From 40811947740e2d3c4cde019e304f5cf85c940f8a Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Tue, 27 Oct 2009 15:28:25 +0000 Subject: Merged revisions 75365,75394,75402-75403,75418,75459,75484,75592-75596,75600,75602-75607,75610-75613,75616-75617,75623,75627,75640,75647,75696,75795 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r75365 | georg.brandl | 2009-10-11 22:16:16 +0200 (So, 11 Okt 2009) | 1 line Fix broken links found by "make linkcheck". scipy.org seems to be done right now, so I could not verify links going there. ........ r75394 | georg.brandl | 2009-10-13 20:10:59 +0200 (Di, 13 Okt 2009) | 1 line Fix markup. ........ r75402 | georg.brandl | 2009-10-14 17:51:48 +0200 (Mi, 14 Okt 2009) | 1 line #7125: fix typo. ........ r75403 | georg.brandl | 2009-10-14 17:57:46 +0200 (Mi, 14 Okt 2009) | 1 line #7126: os.environ changes *do* take effect in subprocesses started with os.system(). ........ r75418 | georg.brandl | 2009-10-14 20:48:32 +0200 (Mi, 14 Okt 2009) | 1 line #7116: str.join() takes an iterable. ........ r75459 | georg.brandl | 2009-10-17 10:57:43 +0200 (Sa, 17 Okt 2009) | 1 line Fix refleaks in _ctypes PyCSimpleType_New, which fixes the refleak seen in test___all__. ........ r75484 | georg.brandl | 2009-10-18 09:58:12 +0200 (So, 18 Okt 2009) | 1 line Fix missing word. ........ r75592 | georg.brandl | 2009-10-22 09:05:48 +0200 (Do, 22 Okt 2009) | 1 line Fix punctuation. ........ r75593 | georg.brandl | 2009-10-22 09:06:49 +0200 (Do, 22 Okt 2009) | 1 line Revert unintended change. ........ r75594 | georg.brandl | 2009-10-22 09:56:02 +0200 (Do, 22 Okt 2009) | 1 line Fix markup. ........ r75595 | georg.brandl | 2009-10-22 09:56:56 +0200 (Do, 22 Okt 2009) | 1 line Fix duplicate target. ........ r75596 | georg.brandl | 2009-10-22 10:05:04 +0200 (Do, 22 Okt 2009) | 1 line Add a new directive marking up implementation details and start using it. ........ r75600 | georg.brandl | 2009-10-22 13:01:46 +0200 (Do, 22 Okt 2009) | 1 line Make it more robust. ........ r75602 | georg.brandl | 2009-10-22 13:28:06 +0200 (Do, 22 Okt 2009) | 1 line Document new directive. ........ r75603 | georg.brandl | 2009-10-22 13:28:23 +0200 (Do, 22 Okt 2009) | 1 line Allow short form with text as argument. ........ r75604 | georg.brandl | 2009-10-22 13:36:50 +0200 (Do, 22 Okt 2009) | 1 line Fix stylesheet for multi-paragraph impl-details. ........ r75605 | georg.brandl | 2009-10-22 13:48:10 +0200 (Do, 22 Okt 2009) | 1 line Use "impl-detail" directive where applicable. ........ r75606 | georg.brandl | 2009-10-22 17:00:06 +0200 (Do, 22 Okt 2009) | 1 line #6324: membership test tries iteration via __iter__. ........ r75607 | georg.brandl | 2009-10-22 17:04:09 +0200 (Do, 22 Okt 2009) | 1 line #7088: document new functions in signal as Unix-only. ........ r75610 | georg.brandl | 2009-10-22 17:27:24 +0200 (Do, 22 Okt 2009) | 1 line Reorder __slots__ fine print and add a clarification. ........ r75611 | georg.brandl | 2009-10-22 17:42:32 +0200 (Do, 22 Okt 2009) | 1 line #7035: improve docs of the various _errors() functions, and give them docstrings. ........ r75612 | georg.brandl | 2009-10-22 17:52:15 +0200 (Do, 22 Okt 2009) | 1 line #7156: document curses as Unix-only. ........ r75613 | georg.brandl | 2009-10-22 17:54:35 +0200 (Do, 22 Okt 2009) | 1 line #6977: getopt does not support optional option arguments. ........ r75616 | georg.brandl | 2009-10-22 18:17:05 +0200 (Do, 22 Okt 2009) | 1 line Add proper references. ........ r75617 | georg.brandl | 2009-10-22 18:20:55 +0200 (Do, 22 Okt 2009) | 1 line Make printout margin important. ........ r75623 | georg.brandl | 2009-10-23 10:14:44 +0200 (Fr, 23 Okt 2009) | 1 line #7188: fix optionxform() docs. ........ r75627 | fred.drake | 2009-10-23 15:04:51 +0200 (Fr, 23 Okt 2009) | 2 lines add further note about what's passed to optionxform ........ r75640 | neil.schemenauer | 2009-10-23 21:58:17 +0200 (Fr, 23 Okt 2009) | 2 lines Improve some docstrings in the 'warnings' module. ........ r75647 | georg.brandl | 2009-10-24 12:04:19 +0200 (Sa, 24 Okt 2009) | 1 line Fix markup. ........ r75696 | georg.brandl | 2009-10-25 21:25:43 +0100 (So, 25 Okt 2009) | 1 line Fix a demo. ........ r75795 | georg.brandl | 2009-10-27 16:10:22 +0100 (Di, 27 Okt 2009) | 1 line Fix a strange mis-edit. ........ --- Python/codecs.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'Python') diff --git a/Python/codecs.c b/Python/codecs.c index d1915f181d..e6ffa0d3f9 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -957,7 +957,9 @@ static int _PyCodecRegistry_Init(void) { "strict_errors", strict_errors, - METH_O + METH_O, + PyDoc_STR("Implements the 'strict' error handling, which " + "raises a UnicodeError on coding errors.") } }, { @@ -965,7 +967,9 @@ static int _PyCodecRegistry_Init(void) { "ignore_errors", ignore_errors, - METH_O + METH_O, + PyDoc_STR("Implements the 'ignore' error handling, which " + "ignores malformed data and continues.") } }, { @@ -973,7 +977,9 @@ static int _PyCodecRegistry_Init(void) { "replace_errors", replace_errors, - METH_O + METH_O, + PyDoc_STR("Implements the 'replace' error handling, which " + "replaces malformed data with a replacement marker.") } }, { @@ -981,7 +987,10 @@ static int _PyCodecRegistry_Init(void) { "xmlcharrefreplace_errors", xmlcharrefreplace_errors, - METH_O + METH_O, + PyDoc_STR("Implements the 'xmlcharrefreplace' error handling, " + "which replaces an unencodable character with the " + "appropriate XML character reference.") } }, { @@ -989,7 +998,10 @@ static int _PyCodecRegistry_Init(void) { "backslashreplace_errors", backslashreplace_errors, - METH_O + METH_O, + PyDoc_STR("Implements the 'backslashreplace' error handling, " + "which replaces an unencodable character with a " + "backslashed escape sequence.") } }, { -- cgit v1.2.1 From 26ad1df9768ed894740d1f88993e146ecd627ea6 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 28 Oct 2009 21:59:39 +0000 Subject: in wide builds, avoid storing high unicode characters from source code with surrogates This is accomplished by decoding with utf-32 instead of utf-16 on all builds. The patch is by Adam Olsen. --- Python/ast.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index c3edea3534..c6a6417efe 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -3246,10 +3246,11 @@ decode_unicode(struct compiling *c, const char *s, size_t len, int rawmode, cons u = NULL; } else { /* check for integer overflow */ - if (len > PY_SIZE_MAX / 4) + if (len > PY_SIZE_MAX / 6) return NULL; - /* "\XX" may become "\u005c\uHHLL" (12 bytes) */ - u = PyBytes_FromStringAndSize((char *)NULL, len * 4); + /* "ä" (2 bytes) may become "\U000000E4" (10 bytes), or 1:5 + "\ä" (3 bytes) may become "\u005c\U000000E4" (16 bytes), or ~1:6 */ + u = PyBytes_FromStringAndSize((char *)NULL, len * 6); if (u == NULL) return NULL; p = buf = PyBytes_AsString(u); @@ -3266,20 +3267,24 @@ decode_unicode(struct compiling *c, const char *s, size_t len, int rawmode, cons PyObject *w; char *r; Py_ssize_t rn, i; - w = decode_utf8(c, &s, end, "utf-16-be"); + w = decode_utf8(c, &s, end, "utf-32-be"); if (w == NULL) { Py_DECREF(u); return NULL; } r = PyBytes_AS_STRING(w); rn = Py_SIZE(w); - assert(rn % 2 == 0); - for (i = 0; i < rn; i += 2) { - sprintf(p, "\\u%02x%02x", + assert(rn % 4 == 0); + for (i = 0; i < rn; i += 4) { + sprintf(p, "\\U%02x%02x%02x%02x", r[i + 0] & 0xFF, - r[i + 1] & 0xFF); - p += 6; + r[i + 1] & 0xFF, + r[i + 2] & 0xFF, + r[i + 3] & 0xFF); + p += 10; } + /* Should be impossible to overflow */ + assert(p - buf <= Py_SIZE(u)); Py_DECREF(w); } else { *p++ = *s++; -- cgit v1.2.1 From ffdc4d981eb178f99c1d3b8567bbd74207a5e02a Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sat, 31 Oct 2009 10:18:44 +0000 Subject: Merged revisions 75982 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r75982 | mark.dickinson | 2009-10-31 10:11:28 +0000 (Sat, 31 Oct 2009) | 5 lines Issue #6603: Fix --with-tsc build failures on x86-64 that resulted from a gcc inline assembler peculiarity. (gcc's "A" constraint apparently means 'rax or rdx' in 64-bit mode, not edx:eax or rdx:rax as one might expect.) ........ --- Python/ceval.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index dd378d6cc4..bf37845865 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -51,11 +51,29 @@ ppc_getcounter(uint64 *v) ((long*)(v))[1] = tb; } -#else /* this is for linux/x86 (and probably any other GCC/x86 combo) */ +#elif defined(__i386__) + +/* this is for linux/x86 (and probably any other GCC/x86 combo) */ #define READ_TIMESTAMP(val) \ __asm__ __volatile__("rdtsc" : "=A" (val)) +#elif defined(__x86_64__) + +/* for gcc/x86_64, the "A" constraint in DI mode means *either* rax *or* rdx; + not edx:eax as it does for i386. Since rdtsc puts its result in edx:eax + even in 64-bit mode, we need to use "a" and "d" for the lower and upper + 32-bit pieces of the result. */ + +#define READ_TIMESTAMP(val) \ + __asm__ __volatile__("rdtsc" : \ + "=a" (((int*)&(val))[0]), "=d" (((int*)&(val))[1])); + + +#else + +#error "Don't know how to implement timestamp counter for this architecture" + #endif void dump_tsc(int opcode, int ticked, uint64 inst0, uint64 inst1, -- cgit v1.2.1 From 26a4de345259275b630e67d752142a36fe834406 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Tue, 10 Nov 2009 19:50:40 +0000 Subject: Merge in the new GIL. --- Python/ceval.c | 162 ++++++++++++++++---------- Python/ceval_gil.h | 335 +++++++++++++++++++++++++++++++++++++++++++++++++++++ Python/pystate.c | 1 + Python/sysmodule.c | 64 +++++++++- 4 files changed, 499 insertions(+), 63 deletions(-) create mode 100644 Python/ceval_gil.h (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index bf37845865..321ab54d31 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -216,6 +216,28 @@ PyEval_GetCallStats(PyObject *self) #endif +#define COMPUTE_EVAL_BREAKER() \ + (eval_breaker = gil_drop_request | pendingcalls_to_do | pending_async_exc) + +#define SET_GIL_DROP_REQUEST() \ + do { gil_drop_request = 1; eval_breaker = 1; } while (0) + +#define RESET_GIL_DROP_REQUEST() \ + do { gil_drop_request = 0; COMPUTE_EVAL_BREAKER(); } while (0) + +#define SIGNAL_PENDING_CALLS() \ + do { pendingcalls_to_do = 1; eval_breaker = 1; } while (0) + +#define UNSIGNAL_PENDING_CALLS() \ + do { pendingcalls_to_do = 0; COMPUTE_EVAL_BREAKER(); } while (0) + +#define SIGNAL_ASYNC_EXC() \ + do { pending_async_exc = 1; eval_breaker = 1; } while (0) + +#define UNSIGNAL_ASYNC_EXC() \ + do { pending_async_exc = 0; COMPUTE_EVAL_BREAKER(); } while (0) + + #ifdef WITH_THREAD #ifdef HAVE_ERRNO_H @@ -223,36 +245,55 @@ PyEval_GetCallStats(PyObject *self) #endif #include "pythread.h" -static PyThread_type_lock interpreter_lock = 0; /* This is the GIL */ static PyThread_type_lock pending_lock = 0; /* for pending calls */ static long main_thread = 0; +/* This single variable consolidates all requests to break out of the fast path + in the eval loop. */ +static volatile int eval_breaker = 0; +/* Request for droppping the GIL */ +static volatile int gil_drop_request = 0; +/* Request for running pending calls */ +static volatile int pendingcalls_to_do = 0; +/* Request for looking at the `async_exc` field of the current thread state */ +static volatile int pending_async_exc = 0; + +#include "ceval_gil.h" int PyEval_ThreadsInitialized(void) { - return interpreter_lock != 0; + return gil_created(); } void PyEval_InitThreads(void) { - if (interpreter_lock) + if (gil_created()) return; - interpreter_lock = PyThread_allocate_lock(); - PyThread_acquire_lock(interpreter_lock, 1); + create_gil(); + take_gil(PyThreadState_GET()); main_thread = PyThread_get_thread_ident(); + if (!pending_lock) + pending_lock = PyThread_allocate_lock(); } void PyEval_AcquireLock(void) { - PyThread_acquire_lock(interpreter_lock, 1); + PyThreadState *tstate = PyThreadState_GET(); + if (tstate == NULL) + Py_FatalError("PyEval_AcquireLock: current thread state is NULL"); + take_gil(tstate); } void PyEval_ReleaseLock(void) { - PyThread_release_lock(interpreter_lock); + /* This function must succeed when the current thread state is NULL. + We therefore avoid PyThreadState_GET() which dumps a fatal error + in debug mode. + */ + drop_gil(_PyThreadState_Current); } void @@ -261,8 +302,8 @@ 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); + assert(gil_created()); + take_gil(tstate); if (PyThreadState_Swap(tstate) != NULL) Py_FatalError( "PyEval_AcquireThread: non-NULL old thread state"); @@ -275,7 +316,7 @@ PyEval_ReleaseThread(PyThreadState *tstate) Py_FatalError("PyEval_ReleaseThread: NULL thread state"); if (PyThreadState_Swap(NULL) != tstate) Py_FatalError("PyEval_ReleaseThread: wrong thread state"); - PyThread_release_lock(interpreter_lock); + drop_gil(tstate); } /* This function is called from PyOS_AfterFork to ensure that newly @@ -287,17 +328,17 @@ void PyEval_ReInitThreads(void) { PyObject *threading, *result; - PyThreadState *tstate; + PyThreadState *tstate = PyThreadState_GET(); - if (!interpreter_lock) + if (!gil_created()) 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(); + recreate_gil(); pending_lock = PyThread_allocate_lock(); - PyThread_acquire_lock(interpreter_lock, 1); + take_gil(tstate); main_thread = PyThread_get_thread_ident(); /* Update the threading module with the new state. @@ -317,7 +358,21 @@ PyEval_ReInitThreads(void) Py_DECREF(result); Py_DECREF(threading); } -#endif + +#else +static int eval_breaker = 0; +static int gil_drop_request = 0; +static int pending_async_exc = 0; +#endif /* WITH_THREAD */ + +/* This function is used to signal that async exceptions are waiting to be + raised, therefore it is also useful in non-threaded builds. */ + +void +_PyEval_SignalAsyncExc(void) +{ + SIGNAL_ASYNC_EXC(); +} /* Functions save_thread and restore_thread are always defined so dynamically loaded modules needn't be compiled separately for use @@ -330,8 +385,8 @@ PyEval_SaveThread(void) if (tstate == NULL) Py_FatalError("PyEval_SaveThread: NULL tstate"); #ifdef WITH_THREAD - if (interpreter_lock) - PyThread_release_lock(interpreter_lock); + if (gil_created()) + drop_gil(tstate); #endif return tstate; } @@ -342,9 +397,9 @@ PyEval_RestoreThread(PyThreadState *tstate) if (tstate == NULL) Py_FatalError("PyEval_RestoreThread: NULL tstate"); #ifdef WITH_THREAD - if (interpreter_lock) { + if (gil_created()) { int err = errno; - PyThread_acquire_lock(interpreter_lock, 1); + take_gil(tstate); errno = err; } #endif @@ -390,7 +445,6 @@ static struct { } pendingcalls[NPENDINGCALLS]; static int pendingfirst = 0; static int pendinglast = 0; -static volatile int pendingcalls_to_do = 1; /* trigger initialization of lock */ static char pendingbusy = 0; int @@ -429,8 +483,7 @@ Py_AddPendingCall(int (*func)(void *), void *arg) pendinglast = j; } /* signal main loop */ - _Py_Ticker = 0; - pendingcalls_to_do = 1; + SIGNAL_PENDING_CALLS(); if (lock != NULL) PyThread_release_lock(lock); return result; @@ -472,7 +525,10 @@ Py_MakePendingCalls(void) arg = pendingcalls[j].arg; pendingfirst = (j + 1) % NPENDINGCALLS; } - pendingcalls_to_do = pendingfirst != pendinglast; + if (pendingfirst != pendinglast) + SIGNAL_PENDING_CALLS(); + else + UNSIGNAL_PENDING_CALLS(); PyThread_release_lock(pending_lock); /* having released the lock, perform the callback */ if (func == NULL) @@ -538,8 +594,7 @@ Py_AddPendingCall(int (*func)(void *), void *arg) pendingcalls[i].arg = arg; pendinglast = j; - _Py_Ticker = 0; - pendingcalls_to_do = 1; /* Signal main loop */ + SIGNAL_PENDING_CALLS(); busy = 0; /* XXX End critical section */ return 0; @@ -552,7 +607,7 @@ Py_MakePendingCalls(void) if (busy) return 0; busy = 1; - pendingcalls_to_do = 0; + UNSIGNAL_PENDING_CALLS(); for (;;) { int i; int (*func)(void *); @@ -565,7 +620,7 @@ Py_MakePendingCalls(void) pendingfirst = (i + 1) % NPENDINGCALLS; if (func(arg) < 0) { busy = 0; - pendingcalls_to_do = 1; /* We're not done yet */ + SIGNAL_PENDING_CALLS(); /* We're not done yet */ return -1; } } @@ -658,10 +713,7 @@ static int unpack_iterable(PyObject *, int, int, PyObject **); fast_next_opcode*/ static int _Py_TracingPossible = 0; -/* 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 = 0; /* so that we hit a "tick" first thing */ + PyObject * PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals) @@ -791,10 +843,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) #define DISPATCH() \ { \ - /* Avoid multiple loads from _Py_Ticker despite `volatile` */ \ - int _tick = _Py_Ticker - 1; \ - _Py_Ticker = _tick; \ - if (_tick >= 0) { \ + if (!eval_breaker) { \ FAST_DISPATCH(); \ } \ continue; \ @@ -1168,13 +1217,12 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) async I/O handler); see Py_AddPendingCall() and Py_MakePendingCalls() above. */ - if (--_Py_Ticker < 0) { + if (eval_breaker) { 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; @@ -1184,39 +1232,31 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) why = WHY_EXCEPTION; goto on_error; } - if (pendingcalls_to_do) - /* MakePendingCalls() didn't succeed. - Force early re-execution of this - "periodic" code, possibly after - a thread switch */ - _Py_Ticker = 0; } + if (gil_drop_request) { #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); - + drop_gil(tstate); + /* Other threads may run now */ - - PyThread_acquire_lock(interpreter_lock, 1); + + take_gil(tstate); 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 + } + /* Check for asynchronous exceptions. */ + if (tstate->async_exc != NULL) { + x = tstate->async_exc; + tstate->async_exc = NULL; + UNSIGNAL_ASYNC_EXC(); + PyErr_SetNone(x); + Py_DECREF(x); + why = WHY_EXCEPTION; + goto on_error; + } } fast_next_opcode: diff --git a/Python/ceval_gil.h b/Python/ceval_gil.h new file mode 100644 index 0000000000..2687f9524d --- /dev/null +++ b/Python/ceval_gil.h @@ -0,0 +1,335 @@ +/* + * Implementation of the Global Interpreter Lock (GIL). + */ + +#include +#include + + +/* First some general settings */ + +/* microseconds (the Python API uses seconds, though) */ +#define DEFAULT_INTERVAL 5000 +static unsigned long gil_interval = DEFAULT_INTERVAL; +#define INTERVAL (gil_interval >= 1 ? gil_interval : 1) + +/* Enable if you want to force the switching of threads at least every `gil_interval` */ +#undef FORCE_SWITCHING +#define FORCE_SWITCHING + + +/* + Notes about the implementation: + + - The GIL is just a boolean variable (gil_locked) whose access is protected + by a mutex (gil_mutex), and whose changes are signalled by a condition + variable (gil_cond). gil_mutex is taken for short periods of time, + and therefore mostly uncontended. + + - In the GIL-holding thread, the main loop (PyEval_EvalFrameEx) must be + able to release the GIL on demand by another thread. A volatile boolean + variable (gil_drop_request) is used for that purpose, which is checked + at every turn of the eval loop. That variable is set after a wait of + `interval` microseconds on `gil_cond` has timed out. + + [Actually, another volatile boolean variable (eval_breaker) is used + which ORs several conditions into one. Volatile booleans are + sufficient as inter-thread signalling means since Python is run + on cache-coherent architectures only.] + + - A thread wanting to take the GIL will first let pass a given amount of + time (`interval` microseconds) before setting gil_drop_request. This + encourages a defined switching period, but doesn't enforce it since + opcodes can take an arbitrary time to execute. + + The `interval` value is available for the user to read and modify + using the Python API `sys.{get,set}switchinterval()`. + + - When a thread releases the GIL and gil_drop_request is set, that thread + ensures that another GIL-awaiting thread gets scheduled. + It does so by waiting on a condition variable (switch_cond) until + the value of gil_last_holder is changed to something else than its + own thread state pointer, indicating that another thread was able to + take the GIL. + + This is meant to prohibit the latency-adverse behaviour on multi-core + machines where one thread would speculatively release the GIL, but still + run and end up being the first to re-acquire it, making the "timeslices" + much longer than expected. + (Note: this mechanism is enabled with FORCE_SWITCHING above) +*/ + +#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 /* _POSIX_THREADS */ +# endif +#endif + + +#ifdef _POSIX_THREADS + +/* + * POSIX support + */ + +#include + +#define ADD_MICROSECONDS(tv, interval) \ +do { \ + tv.tv_usec += (long) interval; \ + tv.tv_sec += tv.tv_usec / 1000000; \ + tv.tv_usec %= 1000000; \ +} while (0) + +/* We assume all modern POSIX systems have gettimeofday() */ +#ifdef GETTIMEOFDAY_NO_TZ +#define GETTIMEOFDAY(ptv) gettimeofday(ptv) +#else +#define GETTIMEOFDAY(ptv) gettimeofday(ptv, (struct timezone *)NULL) +#endif + +#define MUTEX_T pthread_mutex_t +#define MUTEX_INIT(mut) \ + if (pthread_mutex_init(&mut, NULL)) { \ + Py_FatalError("pthread_mutex_init(" #mut ") failed"); }; +#define MUTEX_LOCK(mut) \ + if (pthread_mutex_lock(&mut)) { \ + Py_FatalError("pthread_mutex_lock(" #mut ") failed"); }; +#define MUTEX_UNLOCK(mut) \ + if (pthread_mutex_unlock(&mut)) { \ + Py_FatalError("pthread_mutex_unlock(" #mut ") failed"); }; + +#define COND_T pthread_cond_t +#define COND_INIT(cond) \ + if (pthread_cond_init(&cond, NULL)) { \ + Py_FatalError("pthread_cond_init(" #cond ") failed"); }; +#define COND_PREPARE(cond) +#define COND_SIGNAL(cond) \ + if (pthread_cond_signal(&cond)) { \ + Py_FatalError("pthread_cond_signal(" #cond ") failed"); }; +#define COND_WAIT(cond, mut) \ + if (pthread_cond_wait(&cond, &mut)) { \ + Py_FatalError("pthread_cond_wait(" #cond ") failed"); }; +#define COND_TIMED_WAIT(cond, mut, microseconds, timeout_result) \ + { \ + int r; \ + struct timespec ts; \ + struct timeval deadline; \ + \ + GETTIMEOFDAY(&deadline); \ + ADD_MICROSECONDS(deadline, microseconds); \ + ts.tv_sec = deadline.tv_sec; \ + ts.tv_nsec = deadline.tv_usec * 1000; \ + \ + r = pthread_cond_timedwait(&cond, &mut, &ts); \ + if (r == ETIMEDOUT) \ + timeout_result = 1; \ + else if (r) \ + Py_FatalError("pthread_cond_timedwait(" #cond ") failed"); \ + else \ + timeout_result = 0; \ + } \ + +#elif defined(NT_THREADS) + +/* + * Windows (2000 and later, as well as (hopefully) CE) support + */ + +#include + +#define MUTEX_T HANDLE +#define MUTEX_INIT(mut) \ + if (!(mut = CreateMutex(NULL, FALSE, NULL))) { \ + Py_FatalError("CreateMutex(" #mut ") failed"); }; +#define MUTEX_LOCK(mut) \ + if (WaitForSingleObject(mut, INFINITE) != WAIT_OBJECT_0) { \ + Py_FatalError("WaitForSingleObject(" #mut ") failed"); }; +#define MUTEX_UNLOCK(mut) \ + if (!ReleaseMutex(mut)) { \ + Py_FatalError("ReleaseMutex(" #mut ") failed"); }; + +/* We emulate condition variables with events. It is sufficient here. + (WaitForMultipleObjects() allows the event to be caught and the mutex + to be taken atomically) */ +#define COND_T HANDLE +#define COND_INIT(cond) \ + /* auto-reset, non-signalled */ \ + if (!(cond = CreateEvent(NULL, FALSE, FALSE, NULL))) { \ + Py_FatalError("CreateMutex(" #cond ") failed"); }; +#define COND_PREPARE(cond) \ + if (!ResetEvent(cond)) { \ + Py_FatalError("ResetEvent(" #cond ") failed"); }; +#define COND_SIGNAL(cond) \ + if (!SetEvent(cond)) { \ + Py_FatalError("SetEvent(" #cond ") failed"); }; +#define COND_WAIT(cond, mut) \ + { \ + DWORD r; \ + HANDLE objects[2] = { cond, mut }; \ + MUTEX_UNLOCK(mut); \ + r = WaitForMultipleObjects(2, objects, TRUE, INFINITE); \ + if (r != WAIT_OBJECT_0) \ + Py_FatalError("WaitForSingleObject(" #cond ") failed"); \ + } +#define COND_TIMED_WAIT(cond, mut, microseconds, timeout_result) \ + { \ + DWORD r; \ + HANDLE objects[2] = { cond, mut }; \ + MUTEX_UNLOCK(mut); \ + r = WaitForMultipleObjects(2, objects, TRUE, microseconds / 1000); \ + if (r == WAIT_TIMEOUT) { \ + MUTEX_LOCK(mut); \ + timeout_result = 1; \ + } \ + else if (r != WAIT_OBJECT_0) \ + Py_FatalError("WaitForSingleObject(" #cond ") failed"); \ + else \ + timeout_result = 0; \ + } + +#else + +#error You need either a POSIX-compatible or a Windows system! + +#endif /* _POSIX_THREADS, NT_THREADS */ + + +/* Whether the GIL is already taken (-1 if uninitialized). This is volatile + because it can be read without any lock taken in ceval.c. */ +static volatile int gil_locked = -1; +/* Number of GIL switches since the beginning. */ +static unsigned long gil_switch_number = 0; +/* Last thread holding / having held the GIL. This helps us know whether + anyone else was scheduled after we dropped the GIL. */ +static PyThreadState *gil_last_holder = NULL; + +/* This condition variable allows one or several threads to wait until + the GIL is released. In addition, the mutex also protects the above + variables. */ +static COND_T gil_cond; +static MUTEX_T gil_mutex; + +#ifdef FORCE_SWITCHING +/* This condition variable helps the GIL-releasing thread wait for + a GIL-awaiting thread to be scheduled and take the GIL. */ +static COND_T switch_cond; +static MUTEX_T switch_mutex; +#endif + + +static int gil_created(void) +{ + return gil_locked >= 0; +} + +static void create_gil(void) +{ + MUTEX_INIT(gil_mutex); +#ifdef FORCE_SWITCHING + MUTEX_INIT(switch_mutex); +#endif + COND_INIT(gil_cond); +#ifdef FORCE_SWITCHING + COND_INIT(switch_cond); +#endif + gil_locked = 0; + gil_last_holder = NULL; +} + +static void recreate_gil(void) +{ + create_gil(); +} + +static void drop_gil(PyThreadState *tstate) +{ + /* NOTE: tstate is allowed to be NULL. */ + if (!gil_locked) + Py_FatalError("drop_gil: GIL is not locked"); + if (tstate != NULL && tstate != gil_last_holder) + Py_FatalError("drop_gil: wrong thread state"); + + MUTEX_LOCK(gil_mutex); + gil_locked = 0; + COND_SIGNAL(gil_cond); +#ifdef FORCE_SWITCHING + COND_PREPARE(switch_cond); +#endif + MUTEX_UNLOCK(gil_mutex); + +#ifdef FORCE_SWITCHING + if (gil_drop_request) { + MUTEX_LOCK(switch_mutex); + /* Not switched yet => wait */ + if (gil_last_holder == tstate) + COND_WAIT(switch_cond, switch_mutex); + MUTEX_UNLOCK(switch_mutex); + } +#endif +} + +static void take_gil(PyThreadState *tstate) +{ + int err; + if (tstate == NULL) + Py_FatalError("take_gil: NULL tstate"); + + err = errno; + MUTEX_LOCK(gil_mutex); + + if (!gil_locked) + goto _ready; + + COND_PREPARE(gil_cond); + while (gil_locked) { + int timed_out = 0; + unsigned long saved_switchnum; + + saved_switchnum = gil_switch_number; + COND_TIMED_WAIT(gil_cond, gil_mutex, INTERVAL, timed_out); + /* If we timed out and no switch occurred in the meantime, it is time + to ask the GIL-holding thread to drop it. */ + if (timed_out && gil_locked && gil_switch_number == saved_switchnum) { + SET_GIL_DROP_REQUEST(); + } + } +_ready: +#ifdef FORCE_SWITCHING + /* This mutex must be taken before modifying gil_last_holder (see drop_gil()). */ + MUTEX_LOCK(switch_mutex); +#endif + /* We now hold the GIL */ + gil_locked = 1; + + if (tstate != gil_last_holder) { + gil_last_holder = tstate; + ++gil_switch_number; + } +#ifdef FORCE_SWITCHING + COND_SIGNAL(switch_cond); + MUTEX_UNLOCK(switch_mutex); +#endif + if (gil_drop_request) { + RESET_GIL_DROP_REQUEST(); + } + if (tstate->async_exc != NULL) { + _PyEval_SignalAsyncExc(); + } + + MUTEX_UNLOCK(gil_mutex); + errno = err; +} + +void _PyEval_SetSwitchInterval(unsigned long microseconds) +{ + gil_interval = microseconds; +} + +unsigned long _PyEval_GetSwitchInterval() +{ + return gil_interval; +} diff --git a/Python/pystate.c b/Python/pystate.c index fe5de5f4d2..78c501e4c5 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -434,6 +434,7 @@ PyThreadState_SetAsyncExc(long id, PyObject *exc) { p->async_exc = exc; HEAD_UNLOCK(); Py_XDECREF(old_exc); + _PyEval_SignalAsyncExc(); return 1; } } diff --git a/Python/sysmodule.c b/Python/sysmodule.c index fa39480e8c..51bd85bd3f 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -448,10 +448,18 @@ Return the profiling function set with sys.setprofile.\n\ See the profiler chapter in the library manual." ); +/* TODO: deprecate */ +static int _check_interval = 100; + static PyObject * sys_setcheckinterval(PyObject *self, PyObject *args) { - if (!PyArg_ParseTuple(args, "i:setcheckinterval", &_Py_CheckInterval)) + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "sys.getcheckinterval() and sys.setcheckinterval() " + "are deprecated. Use sys.setswitchinterval() " + "instead.", 1) < 0) + return NULL; + if (!PyArg_ParseTuple(args, "i:setcheckinterval", &_check_interval)) return NULL; Py_INCREF(Py_None); return Py_None; @@ -467,13 +475,59 @@ n instructions. This also affects how often thread switches occur." static PyObject * sys_getcheckinterval(PyObject *self, PyObject *args) { - return PyLong_FromLong(_Py_CheckInterval); + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "sys.getcheckinterval() and sys.setcheckinterval() " + "are deprecated. Use sys.getswitchinterval() " + "instead.", 1) < 0) + return NULL; + return PyLong_FromLong(_check_interval); } PyDoc_STRVAR(getcheckinterval_doc, "getcheckinterval() -> current check interval; see setcheckinterval()." ); +#ifdef WITH_THREAD +static PyObject * +sys_setswitchinterval(PyObject *self, PyObject *args) +{ + double d; + if (!PyArg_ParseTuple(args, "d:setswitchinterval", &d)) + return NULL; + if (d <= 0.0) { + PyErr_SetString(PyExc_ValueError, + "switch interval must be strictly positive"); + return NULL; + } + _PyEval_SetSwitchInterval((unsigned long) (1e6 * d)); + Py_INCREF(Py_None); + return Py_None; +} + +PyDoc_STRVAR(setswitchinterval_doc, +"setswitchinterval(n)\n\ +\n\ +Set the ideal thread switching delay inside the Python interpreter\n\ +The actual frequency of switching threads can be lower if the\n\ +interpreter executes long sequences of uninterruptible code\n\ +(this is implementation-specific and workload-dependent).\n\ +\n\ +The parameter must represent the desired switching delay in seconds\n\ +A typical value is 0.005 (5 milliseconds)." +); + +static PyObject * +sys_getswitchinterval(PyObject *self, PyObject *args) +{ + return PyFloat_FromDouble(1e-6 * _PyEval_GetSwitchInterval()); +} + +PyDoc_STRVAR(getswitchinterval_doc, +"getswitchinterval() -> current thread switch interval; see setswitchinterval()." +); + +#endif /* WITH_THREAD */ + #ifdef WITH_TSC static PyObject * sys_settscdump(PyObject *self, PyObject *args) @@ -895,6 +949,12 @@ static PyMethodDef sys_methods[] = { setcheckinterval_doc}, {"getcheckinterval", sys_getcheckinterval, METH_NOARGS, getcheckinterval_doc}, +#ifdef WITH_THREAD + {"setswitchinterval", sys_setswitchinterval, METH_VARARGS, + setswitchinterval_doc}, + {"getswitchinterval", sys_getswitchinterval, METH_NOARGS, + getswitchinterval_doc}, +#endif #ifdef HAVE_DLOPEN {"setdlopenflags", sys_setdlopenflags, METH_VARARGS, setdlopenflags_doc}, -- cgit v1.2.1 From d6518315e45d04e0b1b3c5ed211424c56811f33a Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Tue, 10 Nov 2009 22:38:52 +0000 Subject: Remove obsolete comment. --- Python/sysmodule.c | 1 - 1 file changed, 1 deletion(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 51bd85bd3f..84813baee5 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -448,7 +448,6 @@ Return the profiling function set with sys.setprofile.\n\ See the profiler chapter in the library manual." ); -/* TODO: deprecate */ static int _check_interval = 100; static PyObject * -- cgit v1.2.1 From 5d3b1ce99bb91fced4ea5c1681cff9fb48459791 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Wed, 11 Nov 2009 18:11:36 +0000 Subject: Our condition variable emulation under Windows is imperfect, which seems to be the cause of the buildbot hangs. Try to fix it, and add some comments. --- Python/ceval_gil.h | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) (limited to 'Python') diff --git a/Python/ceval_gil.h b/Python/ceval_gil.h index 2687f9524d..bcc4fb9f6c 100644 --- a/Python/ceval_gil.h +++ b/Python/ceval_gil.h @@ -153,8 +153,20 @@ do { \ Py_FatalError("ReleaseMutex(" #mut ") failed"); }; /* We emulate condition variables with events. It is sufficient here. - (WaitForMultipleObjects() allows the event to be caught and the mutex - to be taken atomically) */ + WaitForMultipleObjects() allows the event to be caught and the mutex + to be taken atomically. + As for SignalObjectAndWait(), its semantics are unfortunately a bit + more foggy. Many sources on the Web define it as atomically releasing + the first object while starting to wait on the second, but MSDN states + it is *not* atomic... + + In any case, the emulation here is tailored for our particular use case. + For example, we don't care how many threads are woken up when a condition + gets signalled. Generic emulations of the pthread_cond_* API using + Win32 functions can be found on the Web. + The following read can be edificating (or not): + http://www.cse.wustl.edu/~schmidt/win32-cv-1.html +*/ #define COND_T HANDLE #define COND_INIT(cond) \ /* auto-reset, non-signalled */ \ @@ -168,12 +180,9 @@ do { \ Py_FatalError("SetEvent(" #cond ") failed"); }; #define COND_WAIT(cond, mut) \ { \ - DWORD r; \ - HANDLE objects[2] = { cond, mut }; \ - MUTEX_UNLOCK(mut); \ - r = WaitForMultipleObjects(2, objects, TRUE, INFINITE); \ - if (r != WAIT_OBJECT_0) \ - Py_FatalError("WaitForSingleObject(" #cond ") failed"); \ + if (SignalObjectAndWait(mut, cond, INFINITE, FALSE) != WAIT_OBJECT_0) \ + Py_FatalError("SignalObjectAndWait(" #mut ", " #cond") failed"); \ + MUTEX_LOCK(mut); \ } #define COND_TIMED_WAIT(cond, mut, microseconds, timeout_result) \ { \ @@ -257,7 +266,8 @@ static void drop_gil(PyThreadState *tstate) gil_locked = 0; COND_SIGNAL(gil_cond); #ifdef FORCE_SWITCHING - COND_PREPARE(switch_cond); + if (gil_drop_request) + COND_PREPARE(switch_cond); #endif MUTEX_UNLOCK(gil_mutex); @@ -266,6 +276,11 @@ static void drop_gil(PyThreadState *tstate) MUTEX_LOCK(switch_mutex); /* Not switched yet => wait */ if (gil_last_holder == tstate) + /* NOTE: if COND_WAIT does not atomically start waiting when + releasing the mutex, another thread can run through, take + the GIL and drop it again, and reset the condition + (COND_PREPARE above) before we even had a chance to wait + for it. */ COND_WAIT(switch_cond, switch_mutex); MUTEX_UNLOCK(switch_mutex); } -- cgit v1.2.1 From 7f3c8d86f7999f49856de91843d6c87de6a67d9e Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Thu, 12 Nov 2009 22:56:02 +0000 Subject: Try to strengthen condition-waiting under Windows. If it doesn't work (doesn't solve erratic freezes) we'll have to resort to tougher (Windows-only) measures. --- Python/ceval_gil.h | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'Python') diff --git a/Python/ceval_gil.h b/Python/ceval_gil.h index bcc4fb9f6c..d4d6fdde6e 100644 --- a/Python/ceval_gil.h +++ b/Python/ceval_gil.h @@ -106,7 +106,7 @@ do { \ #define COND_INIT(cond) \ if (pthread_cond_init(&cond, NULL)) { \ Py_FatalError("pthread_cond_init(" #cond ") failed"); }; -#define COND_PREPARE(cond) +#define COND_RESET(cond) #define COND_SIGNAL(cond) \ if (pthread_cond_signal(&cond)) { \ Py_FatalError("pthread_cond_signal(" #cond ") failed"); }; @@ -172,7 +172,7 @@ do { \ /* auto-reset, non-signalled */ \ if (!(cond = CreateEvent(NULL, FALSE, FALSE, NULL))) { \ Py_FatalError("CreateMutex(" #cond ") failed"); }; -#define COND_PREPARE(cond) \ +#define COND_RESET(cond) \ if (!ResetEvent(cond)) { \ Py_FatalError("ResetEvent(" #cond ") failed"); }; #define COND_SIGNAL(cond) \ @@ -265,23 +265,21 @@ static void drop_gil(PyThreadState *tstate) MUTEX_LOCK(gil_mutex); gil_locked = 0; COND_SIGNAL(gil_cond); -#ifdef FORCE_SWITCHING - if (gil_drop_request) - COND_PREPARE(switch_cond); -#endif MUTEX_UNLOCK(gil_mutex); #ifdef FORCE_SWITCHING - if (gil_drop_request) { + if (gil_drop_request && tstate != NULL) { MUTEX_LOCK(switch_mutex); /* Not switched yet => wait */ - if (gil_last_holder == tstate) + if (gil_last_holder == tstate) { + RESET_GIL_DROP_REQUEST(); /* NOTE: if COND_WAIT does not atomically start waiting when releasing the mutex, another thread can run through, take the GIL and drop it again, and reset the condition - (COND_PREPARE above) before we even had a chance to wait - for it. */ + before we even had a chance to wait for it. */ COND_WAIT(switch_cond, switch_mutex); + COND_RESET(switch_cond); + } MUTEX_UNLOCK(switch_mutex); } #endif @@ -299,7 +297,7 @@ static void take_gil(PyThreadState *tstate) if (!gil_locked) goto _ready; - COND_PREPARE(gil_cond); + COND_RESET(gil_cond); while (gil_locked) { int timed_out = 0; unsigned long saved_switchnum; -- cgit v1.2.1 From d7ad3ea3c73f164bd7895035ffc8c25a96d251bb Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 20 Nov 2009 01:19:41 +0000 Subject: Merged revisions 76423-76424 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r76423 | benjamin.peterson | 2009-11-19 19:15:53 -0600 (Thu, 19 Nov 2009) | 1 line provide line number for lambdas ........ r76424 | benjamin.peterson | 2009-11-19 19:16:58 -0600 (Thu, 19 Nov 2009) | 1 line genexps have linenos ........ --- Python/symtable.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/symtable.c b/Python/symtable.c index e0e63daa09..7fa01b899e 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1323,9 +1323,8 @@ symtable_visit_expr(struct symtable *st, expr_ty e) 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, lambda, - FunctionBlock, (void *)e, 0)) + FunctionBlock, (void *)e, e->lineno)) return 0; VISIT_IN_BLOCK(st, arguments, e->v.Lambda.args, (void*)e); VISIT_IN_BLOCK(st, expr, e->v.Lambda.body, (void*)e); @@ -1623,7 +1622,7 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e, VISIT(st, expr, outermost->iter); /* Create comprehension scope for the rest */ if (!scope_name || - !symtable_enter_block(st, scope_name, FunctionBlock, (void *)e, 0)) { + !symtable_enter_block(st, scope_name, FunctionBlock, (void *)e, e->lineno)) { return 0; } st->st_cur->ste_generator = is_generator; -- cgit v1.2.1 From 7e20442f707b90d4d2eb0b47eabe9b29b923103e Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 25 Nov 2009 17:46:26 +0000 Subject: Merged revisions 75264,75268,75293,75318,75391-75392,75436,75478,75971,76003,76058,76140-76141,76231,76380,76428-76429 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r75264 | andrew.kuchling | 2009-10-05 17:30:22 -0500 (Mon, 05 Oct 2009) | 1 line Add various items ........ r75268 | andrew.kuchling | 2009-10-05 17:45:39 -0500 (Mon, 05 Oct 2009) | 1 line Remove two notes ........ r75293 | kristjan.jonsson | 2009-10-09 09:32:19 -0500 (Fri, 09 Oct 2009) | 2 lines http://bugs.python.org/issue7029 a non-default timer wasn't actually used by the individual Tests. ........ r75318 | benjamin.peterson | 2009-10-10 16:15:58 -0500 (Sat, 10 Oct 2009) | 1 line remove script which uses long gone module ........ r75391 | andrew.kuchling | 2009-10-13 10:49:33 -0500 (Tue, 13 Oct 2009) | 1 line Link to PEP ........ r75392 | andrew.kuchling | 2009-10-13 11:11:49 -0500 (Tue, 13 Oct 2009) | 1 line Various link, textual, and markup fixes ........ r75436 | benjamin.peterson | 2009-10-15 10:39:15 -0500 (Thu, 15 Oct 2009) | 1 line don't need to mess up sys.path ........ r75478 | senthil.kumaran | 2009-10-17 20:58:45 -0500 (Sat, 17 Oct 2009) | 3 lines Fix a typo. ........ r75971 | benjamin.peterson | 2009-10-30 22:56:15 -0500 (Fri, 30 Oct 2009) | 1 line add some checks for evaluation order with parenthesis #7210 ........ r76003 | antoine.pitrou | 2009-10-31 19:30:13 -0500 (Sat, 31 Oct 2009) | 6 lines Hopefully fix the buildbot problems on test_mailbox, by computing the maildir toc cache refresh date before actually refreshing the cache. (see #6896) ........ r76058 | benjamin.peterson | 2009-11-02 10:14:19 -0600 (Mon, 02 Nov 2009) | 1 line grant list.index() a more informative error message #7252 ........ r76140 | nick.coghlan | 2009-11-07 02:13:55 -0600 (Sat, 07 Nov 2009) | 1 line Add test for runpy.run_module package execution and use something other than logging as the example of a non-executable package ........ r76141 | nick.coghlan | 2009-11-07 02:15:01 -0600 (Sat, 07 Nov 2009) | 1 line Some minor cleanups to private runpy code and docstrings ........ r76231 | benjamin.peterson | 2009-11-12 17:42:23 -0600 (Thu, 12 Nov 2009) | 1 line this main is much more useful ........ r76380 | antoine.pitrou | 2009-11-18 14:20:46 -0600 (Wed, 18 Nov 2009) | 3 lines Mention Giampolo R's new FTP TLS support in the what's new file ........ r76428 | benjamin.peterson | 2009-11-19 20:15:50 -0600 (Thu, 19 Nov 2009) | 1 line turn goto into do while loop ........ r76429 | benjamin.peterson | 2009-11-19 20:56:43 -0600 (Thu, 19 Nov 2009) | 2 lines avoid doing an uneeded import in a function ........ --- Python/compile.c | 67 ++++++++++++++++++++++++++------------------------------ 1 file changed, 31 insertions(+), 36 deletions(-) (limited to 'Python') diff --git a/Python/compile.c b/Python/compile.c index 2bb9beb3d8..d8fb47b16e 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3802,49 +3802,47 @@ 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 bsize, totsize, extended_arg_count = 0, last_extended_arg_count; 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; + do { + 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; + } + last_extended_arg_count = extended_arg_count; + 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++; } - 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 @@ -3855,10 +3853,7 @@ start: 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; - } + } while (last_extended_arg_count != extended_arg_count); } static PyObject * -- cgit v1.2.1 From a412ebff3dce42d46a21c7dded2e29c4243f4a8d Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sat, 28 Nov 2009 16:12:28 +0000 Subject: Issue #4486: When an exception has an explicit cause, do not print its implicit context too. --- Python/pythonrun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 875e44e99b..3764740e81 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1576,7 +1576,7 @@ print_exception_recursive(PyObject *f, PyObject *value, PyObject *seen) cause_message, f); } } - if (context) { + else if (context) { res = PySet_Contains(seen, context); if (res == -1) PyErr_Clear(); -- cgit v1.2.1 From a83432f18258ffa6e3431fba960353cbe4a1b5b7 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sat, 28 Nov 2009 16:38:16 +0000 Subject: Merged revisions 76575 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r76575 | mark.dickinson | 2009-11-28 16:32:27 +0000 (Sat, 28 Nov 2009) | 5 lines Issue #1678380: When distinguishing between -0.0 and 0.0 in compiler_add_o, use copysign instead of examining the first and last bytes of the double. The latter method fails for little-endian ARM, OABI, where doubles are little-endian but with the words swapped. ........ --- Python/compile.c | 45 +++++++++++++++++---------------------------- 1 file changed, 17 insertions(+), 28 deletions(-) (limited to 'Python') diff --git a/Python/compile.c b/Python/compile.c index d8fb47b16e..2c58d449b5 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -895,50 +895,39 @@ compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o) { PyObject *t, *v; Py_ssize_t arg; - unsigned char *p; double d; /* necessary to make sure types aren't coerced (e.g., int and long) */ /* _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms */ if (PyFloat_Check(o)) { d = PyFloat_AS_DOUBLE(o); - p = (unsigned char*) &d; /* all we need is to make the tuple different in either the 0.0 * or -0.0 case from all others, just to avoid the "coercion". */ - if (*p==0 && p[sizeof(double)-1]==0) + if (d == 0.0 && copysign(1.0, d) < 0.0) t = PyTuple_Pack(3, o, o->ob_type, Py_None); else t = PyTuple_Pack(2, o, o->ob_type); } else if (PyComplex_Check(o)) { Py_complex z; - int real_part_zero, imag_part_zero; - unsigned char *q; - /* complex case is even messier: we need to make complex(x, - 0.) different from complex(x, -0.) and complex(0., y) - different from complex(-0., y), for any x and y. In - particular, all four complex zeros should be - distinguished.*/ + int real_negzero, imag_negzero; + /* For the complex case we must make complex(x, 0.) + different from complex(x, -0.) and complex(0., y) + different from complex(-0., y), for any x and y. + All four complex zeros must be distinguished.*/ z = PyComplex_AsCComplex(o); - p = (unsigned char*) &(z.real); - q = (unsigned char*) &(z.imag); - /* all that matters here is that on IEEE platforms - real_part_zero will be true if z.real == 0., and false if - z.real == -0. In fact, real_part_zero will also be true - for some other rarely occurring nonzero floats, but this - doesn't matter. Similar comments apply to - imag_part_zero. */ - real_part_zero = *p==0 && p[sizeof(double)-1]==0; - imag_part_zero = *q==0 && q[sizeof(double)-1]==0; - if (real_part_zero && imag_part_zero) { - t = PyTuple_Pack(4, o, o->ob_type, Py_True, Py_True); - } - else if (real_part_zero && !imag_part_zero) { - t = PyTuple_Pack(4, o, o->ob_type, Py_True, Py_False); - } - else if (!real_part_zero && imag_part_zero) { - t = PyTuple_Pack(4, o, o->ob_type, Py_False, Py_True); + real_negzero = z.real == 0.0 && copysign(1.0, z.real) < 0.0; + imag_negzero = z.imag == 0.0 && copysign(1.0, z.imag) < 0.0; + if (real_negzero && imag_negzero) { + t = PyTuple_Pack(5, o, o->ob_type, + Py_None, Py_None, Py_None); + } + else if (imag_negzero) { + t = PyTuple_Pack(4, o, o->ob_type, Py_None, Py_None); + } + else if (real_negzero) { + t = PyTuple_Pack(3, o, o->ob_type, Py_None); } else { t = PyTuple_Pack(2, o, o->ob_type); -- cgit v1.2.1 From 75ca61558705a01811796175088fbf326416257b Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Thu, 3 Dec 2009 10:59:46 +0000 Subject: Issue #7414: Add missing 'case 'C'' to skipitem() in getargs.c. This was causing PyArg_ParseTupleAndKeywords(args, kwargs, "|CC", ...) to fail with a RuntimeError. Thanks Case Van Horsen for tracking down the source of this error. --- Python/getargs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index f41cd05eaf..b69aaed56c 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1772,6 +1772,7 @@ skipitem(const char **p_format, va_list *p_va, int flags) case 'd': /* double */ case 'D': /* complex double */ case 'c': /* char */ + case 'C': /* unicode char */ { (void) va_arg(*p_va, void *); break; -- cgit v1.2.1 From 3109ebd6a19ed38b1b76978c7c8b07b58570ba88 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Thu, 10 Dec 2009 02:09:08 +0000 Subject: remove magic number bumping from the 2.x -U option #7459 --- Python/import.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 62142aea26..8321b14929 100644 --- a/Python/import.c +++ b/Python/import.c @@ -78,24 +78,23 @@ typedef unsigned short mode_t; 3040 (added signature annotations) 3050 (print becomes a function) 3060 (PEP 3115 metaclass syntax) - 3070 (PEP 3109 raise changes) - 3080 (PEP 3137 make __file__ and __name__ unicode) - 3090 (kill str8 interning) - 3100 (merge from 2.6a0, see 62151) - 3102 (__file__ points to source file) - Python 3.0a4: 3110 (WITH_CLEANUP optimization). - Python 3.0a5: 3130 (lexical exception stacking, including POP_EXCEPT) - Python 3.1a0: 3140 (optimize list, set and dict comprehensions: + 3061 (string literals become unicode) + 3071 (PEP 3109 raise changes) + 3081 (PEP 3137 make __file__ and __name__ unicode) + 3091 (kill str8 interning) + 3101 (merge from 2.6a0, see 62151) + 3103 (__file__ points to source file) + Python 3.0a4: 3111 (WITH_CLEANUP optimization). + Python 3.0a5: 3131 (lexical exception stacking, including POP_EXCEPT) + Python 3.1a0: 3141 (optimize list, set and dict comprehensions: change LIST_APPEND and SET_ADD, add MAP_ADD) - Python 3.1a0: 3150 (optimize conditional branches: + Python 3.1a0: 3151 (optimize conditional branches: introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE) Python 3.2a0: 3160 (add SETUP_WITH) */ #define MAGIC (3160 | ((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. */ +/* Magic word as global */ static long pyc_magic = MAGIC; /* See _PyImport_FixupExtension() below */ @@ -161,13 +160,6 @@ _PyImport_Init(void) filetab->suffix = ".pyo"; } } - - { - /* 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 -- cgit v1.2.1 From 21a3d41d9f19d28acc07ab7d4e6ee152be902ac6 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 13 Dec 2009 01:23:39 +0000 Subject: Merged revisions 76534,76538,76628,76701,76774 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r76534 | martin.v.loewis | 2009-11-26 02:42:05 -0600 (Thu, 26 Nov 2009) | 2 lines Fix typo. ........ r76538 | georg.brandl | 2009-11-26 14:48:25 -0600 (Thu, 26 Nov 2009) | 1 line #7400: typo. ........ r76628 | andrew.kuchling | 2009-12-02 08:27:11 -0600 (Wed, 02 Dec 2009) | 1 line Markup fixes ........ r76701 | andrew.kuchling | 2009-12-07 20:37:05 -0600 (Mon, 07 Dec 2009) | 1 line Typo fix; grammar fix ........ r76774 | benjamin.peterson | 2009-12-12 18:54:15 -0600 (Sat, 12 Dec 2009) | 1 line account for PyObject_IsInstance's new ability to fail ........ --- Python/bltinmodule.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 297c795ca3..5710c0724c 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -529,6 +529,7 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds) int mode = -1; int dont_inherit = 0; int supplied_flags = 0; + int is_ast; PyCompilerFlags cf; PyObject *cmd; static char *kwlist[] = {"source", "filename", "mode", "flags", @@ -567,7 +568,10 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds) return NULL; } - if (PyAST_Check(cmd)) { + is_ast = PyAST_Check(cmd); + if (is_ast == -1) + return NULL; + if (is_ast) { PyObject *result; if (supplied_flags & PyCF_ONLY_AST) { Py_INCREF(cmd); -- cgit v1.2.1 From b9035d45226b0afebfeb658d3dd9cdf5871e586b Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 13 Dec 2009 01:24:58 +0000 Subject: regenerate Python-ast.c --- Python/Python-ast.c | 544 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 455 insertions(+), 89 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index e03dac0bb5..05fa5416de 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -3374,13 +3374,18 @@ int obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena) { PyObject* tmp = NULL; + int isinstance; if (obj == Py_None) { *out = NULL; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Module_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Module_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { asdl_seq* body; if (PyObject_HasAttrString(obj, "body")) { @@ -3412,7 +3417,11 @@ obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Interactive_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Interactive_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { asdl_seq* body; if (PyObject_HasAttrString(obj, "body")) { @@ -3444,7 +3453,11 @@ obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Expression_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Expression_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty body; if (PyObject_HasAttrString(obj, "body")) { @@ -3463,7 +3476,11 @@ obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Suite_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Suite_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { asdl_seq* body; if (PyObject_HasAttrString(obj, "body")) { @@ -3508,6 +3525,7 @@ int obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) { PyObject* tmp = NULL; + int isinstance; int lineno; int col_offset; @@ -3540,7 +3558,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"col_offset\" missing from stmt"); return 1; } - if (PyObject_IsInstance(obj, (PyObject*)FunctionDef_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)FunctionDef_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { identifier name; arguments_ty args; asdl_seq* body; @@ -3637,7 +3659,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)ClassDef_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)ClassDef_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { identifier name; asdl_seq* bases; asdl_seq* keywords; @@ -3785,7 +3811,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Return_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Return_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty value; if (PyObject_HasAttrString(obj, "value")) { @@ -3803,7 +3833,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Delete_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Delete_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { asdl_seq* targets; if (PyObject_HasAttrString(obj, "targets")) { @@ -3835,7 +3869,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Assign_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Assign_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { asdl_seq* targets; expr_ty value; @@ -3880,7 +3918,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)AugAssign_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)AugAssign_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty target; operator_ty op; expr_ty value; @@ -3925,7 +3967,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)For_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)For_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty target; expr_ty iter; asdl_seq* body; @@ -4010,7 +4056,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)While_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)While_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty test; asdl_seq* body; asdl_seq* orelse; @@ -4081,7 +4131,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)If_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)If_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty test; asdl_seq* body; asdl_seq* orelse; @@ -4152,7 +4206,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)With_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)With_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty context_expr; expr_ty optional_vars; asdl_seq* body; @@ -4210,7 +4268,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Raise_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Raise_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty exc; expr_ty cause; @@ -4240,7 +4302,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)TryExcept_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)TryExcept_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { asdl_seq* body; asdl_seq* handlers; asdl_seq* orelse; @@ -4325,7 +4391,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)TryFinally_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)TryFinally_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { asdl_seq* body; asdl_seq* finalbody; @@ -4383,7 +4453,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Assert_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Assert_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty test; expr_ty msg; @@ -4414,7 +4488,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Import_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Import_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { asdl_seq* names; if (PyObject_HasAttrString(obj, "names")) { @@ -4446,7 +4524,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)ImportFrom_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)ImportFrom_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { identifier module; asdl_seq* names; int level; @@ -4503,7 +4585,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Global_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Global_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { asdl_seq* names; if (PyObject_HasAttrString(obj, "names")) { @@ -4535,7 +4621,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Nonlocal_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Nonlocal_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { asdl_seq* names; if (PyObject_HasAttrString(obj, "names")) { @@ -4567,7 +4657,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Expr_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Expr_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty value; if (PyObject_HasAttrString(obj, "value")) { @@ -4586,19 +4680,31 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Pass_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Pass_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = Pass(lineno, col_offset, arena); if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Break_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Break_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = Break(lineno, col_offset, arena); if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Continue_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Continue_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = Continue(lineno, col_offset, arena); if (*out == NULL) goto failed; @@ -4617,6 +4723,7 @@ int obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) { PyObject* tmp = NULL; + int isinstance; int lineno; int col_offset; @@ -4649,7 +4756,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"col_offset\" missing from expr"); return 1; } - if (PyObject_IsInstance(obj, (PyObject*)BoolOp_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)BoolOp_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { boolop_ty op; asdl_seq* values; @@ -4694,7 +4805,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)BinOp_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)BinOp_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty left; operator_ty op; expr_ty right; @@ -4739,7 +4854,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)UnaryOp_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)UnaryOp_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { unaryop_ty op; expr_ty operand; @@ -4771,7 +4890,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Lambda_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Lambda_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { arguments_ty args; expr_ty body; @@ -4803,7 +4926,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)IfExp_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)IfExp_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty test; expr_ty body; expr_ty orelse; @@ -4848,7 +4975,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Dict_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Dict_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { asdl_seq* keys; asdl_seq* values; @@ -4906,7 +5037,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Set_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Set_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { asdl_seq* elts; if (PyObject_HasAttrString(obj, "elts")) { @@ -4938,7 +5073,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)ListComp_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)ListComp_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty elt; asdl_seq* generators; @@ -4983,7 +5122,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)SetComp_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)SetComp_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty elt; asdl_seq* generators; @@ -5028,7 +5171,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)DictComp_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)DictComp_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty key; expr_ty value; asdl_seq* generators; @@ -5087,7 +5234,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)GeneratorExp_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)GeneratorExp_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty elt; asdl_seq* generators; @@ -5132,7 +5283,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Yield_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Yield_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty value; if (PyObject_HasAttrString(obj, "value")) { @@ -5150,7 +5305,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Compare_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Compare_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty left; asdl_int_seq* ops; asdl_seq* comparators; @@ -5222,7 +5381,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Call_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Call_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty func; asdl_seq* args; asdl_seq* keywords; @@ -5318,7 +5481,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Num_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Num_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { object n; if (PyObject_HasAttrString(obj, "n")) { @@ -5337,7 +5504,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Str_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Str_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { string s; if (PyObject_HasAttrString(obj, "s")) { @@ -5356,7 +5527,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Bytes_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Bytes_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { string s; if (PyObject_HasAttrString(obj, "s")) { @@ -5375,13 +5550,21 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Ellipsis_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Ellipsis_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = Ellipsis(lineno, col_offset, arena); if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Attribute_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Attribute_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty value; identifier attr; expr_context_ty ctx; @@ -5426,7 +5609,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Subscript_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Subscript_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty value; slice_ty slice; expr_context_ty ctx; @@ -5471,7 +5658,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Starred_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Starred_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty value; expr_context_ty ctx; @@ -5503,7 +5694,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Name_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Name_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { identifier id; expr_context_ty ctx; @@ -5535,7 +5730,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)List_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)List_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { asdl_seq* elts; expr_context_ty ctx; @@ -5580,7 +5779,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Tuple_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Tuple_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { asdl_seq* elts; expr_context_ty ctx; @@ -5638,28 +5841,53 @@ int obj2ast_expr_context(PyObject* obj, expr_context_ty* out, PyArena* arena) { PyObject* tmp = NULL; + int isinstance; - if (PyObject_IsInstance(obj, (PyObject*)Load_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)Load_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = Load; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Store_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)Store_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = Store; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Del_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)Del_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = Del; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)AugLoad_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)AugLoad_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = AugLoad; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)AugStore_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)AugStore_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = AugStore; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Param_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)Param_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = Param; return 0; } @@ -5676,13 +5904,18 @@ int obj2ast_slice(PyObject* obj, slice_ty* out, PyArena* arena) { PyObject* tmp = NULL; + int isinstance; if (obj == Py_None) { *out = NULL; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Slice_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Slice_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty lower; expr_ty upper; expr_ty step; @@ -5724,7 +5957,11 @@ obj2ast_slice(PyObject* obj, slice_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)ExtSlice_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)ExtSlice_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { asdl_seq* dims; if (PyObject_HasAttrString(obj, "dims")) { @@ -5756,7 +5993,11 @@ obj2ast_slice(PyObject* obj, slice_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Index_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)Index_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty value; if (PyObject_HasAttrString(obj, "value")) { @@ -5788,12 +6029,21 @@ int obj2ast_boolop(PyObject* obj, boolop_ty* out, PyArena* arena) { PyObject* tmp = NULL; + int isinstance; - if (PyObject_IsInstance(obj, (PyObject*)And_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)And_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = And; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Or_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)Or_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = Or; return 0; } @@ -5810,52 +6060,101 @@ int obj2ast_operator(PyObject* obj, operator_ty* out, PyArena* arena) { PyObject* tmp = NULL; + int isinstance; - if (PyObject_IsInstance(obj, (PyObject*)Add_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)Add_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = Add; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Sub_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)Sub_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = Sub; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Mult_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)Mult_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = Mult; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Div_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)Div_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = Div; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Mod_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)Mod_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = Mod; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Pow_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)Pow_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = Pow; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)LShift_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)LShift_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = LShift; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)RShift_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)RShift_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = RShift; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)BitOr_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)BitOr_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = BitOr; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)BitXor_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)BitXor_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = BitXor; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)BitAnd_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)BitAnd_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = BitAnd; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)FloorDiv_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)FloorDiv_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = FloorDiv; return 0; } @@ -5872,20 +6171,37 @@ int obj2ast_unaryop(PyObject* obj, unaryop_ty* out, PyArena* arena) { PyObject* tmp = NULL; + int isinstance; - if (PyObject_IsInstance(obj, (PyObject*)Invert_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)Invert_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = Invert; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Not_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)Not_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = Not; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)UAdd_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)UAdd_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = UAdd; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)USub_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)USub_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = USub; return 0; } @@ -5902,44 +6218,85 @@ int obj2ast_cmpop(PyObject* obj, cmpop_ty* out, PyArena* arena) { PyObject* tmp = NULL; + int isinstance; - if (PyObject_IsInstance(obj, (PyObject*)Eq_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)Eq_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = Eq; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)NotEq_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)NotEq_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = NotEq; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Lt_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)Lt_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = Lt; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)LtE_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)LtE_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = LtE; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Gt_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)Gt_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = Gt; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)GtE_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)GtE_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = GtE; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)Is_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)Is_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = Is; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)IsNot_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)IsNot_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = IsNot; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)In_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)In_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = In; return 0; } - if (PyObject_IsInstance(obj, (PyObject*)NotIn_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject *)NotIn_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { *out = NotIn; return 0; } @@ -6020,6 +6377,7 @@ int obj2ast_excepthandler(PyObject* obj, excepthandler_ty* out, PyArena* arena) { PyObject* tmp = NULL; + int isinstance; int lineno; int col_offset; @@ -6052,7 +6410,11 @@ obj2ast_excepthandler(PyObject* obj, excepthandler_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"col_offset\" missing from excepthandler"); return 1; } - if (PyObject_IsInstance(obj, (PyObject*)ExceptHandler_type)) { + isinstance = PyObject_IsInstance(obj, (PyObject*)ExceptHandler_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { expr_ty type; identifier name; asdl_seq* body; @@ -6629,11 +6991,15 @@ mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode) PyObject *req_type[] = {(PyObject*)Module_type, (PyObject*)Expression_type, (PyObject*)Interactive_type}; char *req_name[] = {"Module", "Expression", "Interactive"}; + int isinstance; assert(0 <= mode && mode <= 2); init_types(); - if (!PyObject_IsInstance(ast, req_type[mode])) { + isinstance = PyObject_IsInstance(ast, req_type[mode]); + if (isinstance == -1) + return NULL; + if (!isinstance) { PyErr_Format(PyExc_TypeError, "expected %s node, got %.400s", req_name[mode], Py_TYPE(ast)->tp_name); return NULL; -- cgit v1.2.1 From 88202a78eb41f31614a85886eeabca53cc9b9880 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sat, 19 Dec 2009 21:19:35 +0000 Subject: Fix typo (reported by terlop on IRC) --- Python/bltinmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 5710c0724c..7fe164f5de 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -804,7 +804,7 @@ builtin_exec(PyObject *self, PyObject *args) PyDoc_STRVAR(exec_doc, "exec(object[, globals[, locals]])\n\ \n\ -Read and execute code from a object, which can be a string or a code\n\ +Read and execute code from an object, which can be a string or a code\n\ object.\n\ The globals and locals are dictionaries, defaulting to the current\n\ globals and locals. If only globals is given, locals defaults to it."); -- cgit v1.2.1 From 55c2beb32c9e81c113dcc4e505cd5cc2808f5597 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Mon, 21 Dec 2009 15:27:41 +0000 Subject: Merged revisions 76978 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r76978 | mark.dickinson | 2009-12-21 15:22:00 +0000 (Mon, 21 Dec 2009) | 3 lines Issue #7518: Move substitute definitions of C99 math functions from pymath.c to Modules/_math.c. ........ --- Python/pymath.c | 199 -------------------------------------------------------- 1 file changed, 199 deletions(-) (limited to 'Python') diff --git a/Python/pymath.c b/Python/pymath.c index db2920ce20..83105f2668 100644 --- a/Python/pymath.c +++ b/Python/pymath.c @@ -77,202 +77,3 @@ round(double x) return copysign(y, x); } #endif /* HAVE_ROUND */ - -#ifndef HAVE_LOG1P -#include - -double -log1p(double x) -{ - /* For x small, we use the following approach. Let y be the nearest - float to 1+x, then - - 1+x = y * (1 - (y-1-x)/y) - - so log(1+x) = log(y) + log(1-(y-1-x)/y). Since (y-1-x)/y is tiny, - the second term is well approximated by (y-1-x)/y. If abs(x) >= - DBL_EPSILON/2 or the rounding-mode is some form of round-to-nearest - then y-1-x will be exactly representable, and is computed exactly - by (y-1)-x. - - If abs(x) < DBL_EPSILON/2 and the rounding mode is not known to be - round-to-nearest then this method is slightly dangerous: 1+x could - be rounded up to 1+DBL_EPSILON instead of down to 1, and in that - case y-1-x will not be exactly representable any more and the - result can be off by many ulps. But this is easily fixed: for a - floating-point number |x| < DBL_EPSILON/2., the closest - floating-point number to log(1+x) is exactly x. - */ - - double y; - if (fabs(x) < DBL_EPSILON/2.) { - return x; - } else if (-0.5 <= x && x <= 1.) { - /* WARNING: it's possible than an overeager compiler - will incorrectly optimize the following two lines - to the equivalent of "return log(1.+x)". If this - happens, then results from log1p will be inaccurate - for small x. */ - y = 1.+x; - return log(y)-((y-1.)-x)/y; - } else { - /* NaNs and infinities should end up here */ - return log(1.+x); - } -} -#endif /* HAVE_LOG1P */ - -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -static const double ln2 = 6.93147180559945286227E-01; -static const double two_pow_m28 = 3.7252902984619141E-09; /* 2**-28 */ -static const double two_pow_p28 = 268435456.0; /* 2**28 */ -static const double zero = 0.0; - -/* asinh(x) - * Method : - * Based on - * asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ] - * we have - * asinh(x) := x if 1+x*x=1, - * := sign(x)*(log(x)+ln2)) for large |x|, else - * := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else - * := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2))) - */ - -#ifndef HAVE_ASINH -double -asinh(double x) -{ - double w; - double absx = fabs(x); - - if (Py_IS_NAN(x) || Py_IS_INFINITY(x)) { - return x+x; - } - if (absx < two_pow_m28) { /* |x| < 2**-28 */ - return x; /* return x inexact except 0 */ - } - if (absx > two_pow_p28) { /* |x| > 2**28 */ - w = log(absx)+ln2; - } - else if (absx > 2.0) { /* 2 < |x| < 2**28 */ - w = log(2.0*absx + 1.0 / (sqrt(x*x + 1.0) + absx)); - } - else { /* 2**-28 <= |x| < 2= */ - double t = x*x; - w = log1p(absx + t / (1.0 + sqrt(1.0 + t))); - } - return copysign(w, x); - -} -#endif /* HAVE_ASINH */ - -/* acosh(x) - * Method : - * Based on - * acosh(x) = log [ x + sqrt(x*x-1) ] - * we have - * acosh(x) := log(x)+ln2, if x is large; else - * acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else - * acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1. - * - * Special cases: - * acosh(x) is NaN with signal if x<1. - * acosh(NaN) is NaN without signal. - */ - -#ifndef HAVE_ACOSH -double -acosh(double x) -{ - if (Py_IS_NAN(x)) { - return x+x; - } - if (x < 1.) { /* x < 1; return a signaling NaN */ - errno = EDOM; -#ifdef Py_NAN - return Py_NAN; -#else - return (x-x)/(x-x); -#endif - } - else if (x >= two_pow_p28) { /* x > 2**28 */ - if (Py_IS_INFINITY(x)) { - return x+x; - } else { - return log(x)+ln2; /* acosh(huge)=log(2x) */ - } - } - else if (x == 1.) { - return 0.0; /* acosh(1) = 0 */ - } - else if (x > 2.) { /* 2 < x < 2**28 */ - double t = x*x; - return log(2.0*x - 1.0 / (x + sqrt(t - 1.0))); - } - else { /* 1 < x <= 2 */ - double t = x - 1.0; - return log1p(t + sqrt(2.0*t + t*t)); - } -} -#endif /* HAVE_ACOSH */ - -/* atanh(x) - * Method : - * 1.Reduced x to positive by atanh(-x) = -atanh(x) - * 2.For x>=0.5 - * 1 2x x - * atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------) - * 2 1 - x 1 - x - * - * For x<0.5 - * atanh(x) = 0.5*log1p(2x+2x*x/(1-x)) - * - * Special cases: - * atanh(x) is NaN if |x| >= 1 with signal; - * atanh(NaN) is that NaN with no signal; - * - */ - -#ifndef HAVE_ATANH -double -atanh(double x) -{ - double absx; - double t; - - if (Py_IS_NAN(x)) { - return x+x; - } - absx = fabs(x); - if (absx >= 1.) { /* |x| >= 1 */ - errno = EDOM; -#ifdef Py_NAN - return Py_NAN; -#else - return x/zero; -#endif - } - if (absx < two_pow_m28) { /* |x| < 2**-28 */ - return x; - } - if (absx < 0.5) { /* |x| < 0.5 */ - t = absx+absx; - t = 0.5 * log1p(t + t*absx / (1.0 - absx)); - } - else { /* 0.5 <= |x| <= 1.0 */ - t = 0.5 * log1p((absx + absx) / (1.0 - absx)); - } - return copysign(t, x); -} -#endif /* HAVE_ATANH */ -- cgit v1.2.1 From 18813c701326a0dd4d3ae7af16c969cb1c97586e Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Mon, 28 Dec 2009 08:41:01 +0000 Subject: Merged revisions 77088 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77088 | georg.brandl | 2009-12-28 09:34:58 +0100 (Mo, 28 Dez 2009) | 1 line #7033: add new API function PyErr_NewExceptionWithDoc, for easily giving new exceptions a docstring. ........ --- Python/errors.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'Python') diff --git a/Python/errors.c b/Python/errors.c index 2169a1ab7a..42e0e6f3d5 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -693,6 +693,41 @@ PyErr_NewException(const char *name, PyObject *base, PyObject *dict) return result; } + +/* Create an exception with docstring */ +PyObject * +PyErr_NewExceptionWithDoc(const char *name, const char *doc, + PyObject *base, PyObject *dict) +{ + int result; + PyObject *ret = NULL; + PyObject *mydict = NULL; /* points to the dict only if we create it */ + PyObject *docobj; + + if (dict == NULL) { + dict = mydict = PyDict_New(); + if (dict == NULL) { + return NULL; + } + } + + if (doc != NULL) { + docobj = PyUnicode_FromString(doc); + if (docobj == NULL) + goto failure; + result = PyDict_SetItemString(dict, "__doc__", docobj); + Py_DECREF(docobj); + if (result < 0) + goto failure; + } + + ret = PyErr_NewException(name, base, dict); + failure: + Py_XDECREF(mydict); + return ret; +} + + /* Call when an exception has occurred but there is no way for Python to handle it. Examples: exception in __del__ or during GC. */ void -- cgit v1.2.1 From 4322db87021e6153bd752526c97cf21506c68037 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 30 Dec 2009 19:44:54 +0000 Subject: Merged revisions 77157 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77157 | benjamin.peterson | 2009-12-30 13:34:10 -0600 (Wed, 30 Dec 2009) | 5 lines check if the attribute is set before deleting it with T_OBJECT_EX (fixes #7604) Also, add a note to the docs about the better behavior of T_OBJECT_EX as compared to T_OBJECT. ........ --- Python/structmember.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'Python') diff --git a/Python/structmember.c b/Python/structmember.c index 9f08a6baf8..8edc354106 100644 --- a/Python/structmember.c +++ b/Python/structmember.c @@ -104,17 +104,27 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v) { PyObject *oldv; + addr += l->offset; + if ((l->flags & READONLY) || l->type == T_STRING) { PyErr_SetString(PyExc_AttributeError, "readonly 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; + if (v == NULL) { + if (l->type == T_OBJECT_EX) { + /* Check if the attribute is set. */ + if (*(PyObject **)addr == NULL) { + PyErr_SetString(PyExc_AttributeError, l->name); + return -1; + } + } + else if (l->type != T_OBJECT) { + PyErr_SetString(PyExc_TypeError, + "can't delete numeric/char attribute"); + return -1; + } } - addr += l->offset; switch (l->type) { case T_BOOL:{ if (!PyBool_Check(v)) { -- cgit v1.2.1 From 4292056641b7f20b0b7bf37792efad1822b0c8b7 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 1 Jan 2010 04:47:54 +0000 Subject: Merged revisions 77203 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77203 | benjamin.peterson | 2009-12-31 22:00:55 -0600 (Thu, 31 Dec 2009) | 1 line update copyright year ........ --- Python/getcopyright.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/getcopyright.c b/Python/getcopyright.c index 8864cdbbc0..a5e7fa6396 100644 --- a/Python/getcopyright.c +++ b/Python/getcopyright.c @@ -4,7 +4,7 @@ static char cprt[] = "\ -Copyright (c) 2001-2009 Python Software Foundation.\n\ +Copyright (c) 2001-2010 Python Software Foundation.\n\ All Rights Reserved.\n\ \n\ Copyright (c) 2000 BeOpen.com.\n\ -- cgit v1.2.1 From b663f1e205cdb4abdc00fe7479abe443d9127d83 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Fri, 1 Jan 2010 19:27:32 +0000 Subject: Merged revisions 77218 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77218 | mark.dickinson | 2010-01-01 17:27:30 +0000 (Fri, 01 Jan 2010) | 5 lines Issue #5080: turn the DeprecationWarning from float arguments passed to integer PyArg_Parse* format codes into a TypeError. Add a DeprecationWarning for floats passed with the 'L' format code, which didn't previously have a warning. ........ --- Python/getargs.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index b69aaed56c..39be98c03f 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -582,6 +582,19 @@ converterr(const char *expected, PyObject *arg, char *msgbuf, size_t bufsize) #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_warning(PyObject *arg) +{ + if (PyFloat_Check(arg) && + PyErr_Warn(PyExc_DeprecationWarning, + "integer argument expected, got float" )) + return 1; + else + return 0; +} + /* Explicitly check for float arguments when integers are expected. Return 1 for error, 0 if ok. */ static int @@ -777,7 +790,10 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, #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 ); + PY_LONG_LONG ival; + if (float_argument_warning(arg)) + return converterr("long", arg, msgbuf, bufsize); + ival = PyLong_AsLongLong(arg); if (ival == (PY_LONG_LONG)-1 && PyErr_Occurred() ) { return converterr("long", arg, msgbuf, bufsize); } else { -- cgit v1.2.1 From d86186593208acb29685901cf885a1c4c7746ef3 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Mon, 4 Jan 2010 21:33:31 +0000 Subject: Merged revisions 77302 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77302 | mark.dickinson | 2010-01-04 21:32:02 +0000 (Mon, 04 Jan 2010) | 1 line Fix typo in comment. ........ --- Python/dtoa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/dtoa.c b/Python/dtoa.c index 1cac941748..4f8bab7860 100644 --- a/Python/dtoa.c +++ b/Python/dtoa.c @@ -927,7 +927,7 @@ b2d(Bigint *a, int *e) Given a finite nonzero double d, return an odd Bigint b and exponent *e such that fabs(d) = b * 2**e. On return, *bbits gives the number of - significant bits of e; that is, 2**(*bbits-1) <= b < 2**(*bbits). + significant bits of b; that is, 2**(*bbits-1) <= b < 2**(*bbits). If d is zero, then b == 0, *e == -1010, *bbits = 0. */ -- cgit v1.2.1 From dbecfa36f4a0861c393109ea23dbceae96701486 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Tue, 12 Jan 2010 23:04:19 +0000 Subject: Merged revisions 77410,77421,77450-77451 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77410 | mark.dickinson | 2010-01-10 13:06:31 +0000 (Sun, 10 Jan 2010) | 1 line Remove unused BCinfo fields and an unused macro. ........ r77421 | mark.dickinson | 2010-01-11 17:15:13 +0000 (Mon, 11 Jan 2010) | 1 line Change a variable type to avoid signed overflow; replace repeated '19999' constant by a define. ........ r77450 | mark.dickinson | 2010-01-12 22:23:56 +0000 (Tue, 12 Jan 2010) | 4 lines Issue #7632: Fix a problem with _Py_dg_strtod that could lead to crashes in debug builds, for certain long numeric strings corresponding to subnormal values. ........ r77451 | mark.dickinson | 2010-01-12 22:55:51 +0000 (Tue, 12 Jan 2010) | 2 lines Issue #7632: Fix a bug in dtoa.c that could lead to incorrectly-rounded results. ........ --- Python/dtoa.c | 89 +++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 53 insertions(+), 36 deletions(-) (limited to 'Python') diff --git a/Python/dtoa.c b/Python/dtoa.c index 4f8bab7860..1fe20f4f53 100644 --- a/Python/dtoa.c +++ b/Python/dtoa.c @@ -200,10 +200,11 @@ typedef union { double d; ULong L[2]; } U; #define STRTOD_DIGLIM 40 #endif -#ifdef DIGLIM_DEBUG -extern int strtod_diglim; -#else -#define strtod_diglim STRTOD_DIGLIM +/* maximum permitted exponent value for strtod; exponents larger than + MAX_ABS_EXP in absolute value get truncated to +-MAX_ABS_EXP. MAX_ABS_EXP + should fit into an int. */ +#ifndef MAX_ABS_EXP +#define MAX_ABS_EXP 19999U #endif /* The following definition of Storeinc is appropriate for MIPS processors. @@ -269,8 +270,7 @@ extern int strtod_diglim; typedef struct BCinfo BCinfo; struct BCinfo { - int dp0, dp1, dplen, dsign, e0, inexact; - int nd, nd0, rounding, scale, uflchk; + int dp0, dp1, dplen, dsign, e0, nd, nd0, scale; }; #define FFFFFFFF 0xffffffffUL @@ -1130,6 +1130,26 @@ quorem(Bigint *b, Bigint *S) return q; } +/* version of ulp(x) that takes bc.scale into account. + + Assuming that x is finite and nonzero, and x / 2^bc.scale is exactly + representable as a double, sulp(x) is equivalent to 2^bc.scale * ulp(x / + 2^bc.scale). */ + +static double +sulp(U *x, BCinfo *bc) +{ + U u; + + if (bc->scale && 2*P + 1 - ((word0(x) & Exp_mask) >> Exp_shift) > 0) { + /* rv/2^bc->scale is subnormal */ + word0(&u) = (P+2)*Exp_msk1; + word1(&u) = 0; + return u.d; + } + else + return ulp(x); +} /* return 0 on success, -1 on failure */ @@ -1142,7 +1162,7 @@ bigcomp(U *rv, const char *s0, BCinfo *bc) dsign = bc->dsign; nd = bc->nd; nd0 = bc->nd0; - p5 = nd + bc->e0 - 1; + p5 = nd + bc->e0; speccase = 0; if (rv->d == 0.) { /* special case: value near underflow-to-zero */ /* threshold was rounded to zero */ @@ -1227,17 +1247,21 @@ bigcomp(U *rv, const char *s0, BCinfo *bc) } } - /* Now b/d = exactly half-way between the two floating-point values */ - /* on either side of the input string. Compute first digit of b/d. */ - - if (!(dig = quorem(b,d))) { - b = multadd(b, 10, 0); /* very unlikely */ - if (b == NULL) { - Bfree(d); - return -1; - } - dig = quorem(b,d); + /* Now 10*b/d = exactly half-way between the two floating-point values + on either side of the input string. If b >= d, round down. */ + if (cmp(b, d) >= 0) { + dd = -1; + goto ret; } + + /* Compute first digit of 10*b/d. */ + b = multadd(b, 10, 0); + if (b == NULL) { + Bfree(d); + return -1; + } + dig = quorem(b, d); + assert(dig < 10); /* Compare b/d with s0 */ @@ -1285,12 +1309,12 @@ bigcomp(U *rv, const char *s0, BCinfo *bc) else if (dd < 0) { if (!dsign) /* does not happen for round-near */ retlow1: - dval(rv) -= ulp(rv); + dval(rv) -= sulp(rv, bc); } else if (dd > 0) { if (dsign) { rethi1: - dval(rv) += ulp(rv); + dval(rv) += sulp(rv, bc); } } else { @@ -1312,13 +1336,12 @@ _Py_dg_strtod(const char *s00, char **se) int esign, i, j, k, nd, nd0, nf, nz, nz0, sign; const char *s, *s0, *s1; double aadj, aadj1; - Long L; U aadj2, adj, rv, rv0; - ULong y, z; + ULong y, z, L; BCinfo bc; Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; - sign = nz0 = nz = bc.dplen = bc.uflchk = 0; + sign = nz0 = nz = bc.dplen = 0; dval(&rv) = 0.; for(s = s00;;s++) switch(*s) { case '-': @@ -1413,11 +1436,11 @@ _Py_dg_strtod(const char *s00, char **se) s1 = s; while((c = *++s) >= '0' && c <= '9') L = 10*L + c - '0'; - if (s - s1 > 8 || L > 19999) + if (s - s1 > 8 || L > MAX_ABS_EXP) /* Avoid confusion from exponents * so large that e might overflow. */ - e = 19999; /* safe for 16 bit ints */ + e = (int)MAX_ABS_EXP; /* safe for 16 bit ints */ else e = (int)L; if (esign) @@ -1555,11 +1578,11 @@ _Py_dg_strtod(const char *s00, char **se) /* Put digits into bd: true value = bd * 10^e */ bc.nd = nd; - bc.nd0 = nd0; /* Only needed if nd > strtod_diglim, but done here */ + bc.nd0 = nd0; /* Only needed if nd > STRTOD_DIGLIM, but done here */ /* to silence an erroneous warning about bc.nd0 */ /* possibly not being initialized. */ - if (nd > strtod_diglim) { - /* ASSERT(strtod_diglim >= 18); 18 == one more than the */ + if (nd > STRTOD_DIGLIM) { + /* ASSERT(STRTOD_DIGLIM >= 18); 18 == one more than the */ /* minimum number of decimal digits to distinguish double values */ /* in IEEE arithmetic. */ i = j = 18; @@ -1767,10 +1790,8 @@ _Py_dg_strtod(const char *s00, char **se) /* accept rv */ break; /* rv = smallest denormal */ - if (bc.nd >nd) { - bc.uflchk = 1; + if (bc.nd >nd) break; - } goto undfl; } } @@ -1786,10 +1807,8 @@ _Py_dg_strtod(const char *s00, char **se) else { dval(&rv) -= ulp(&rv); if (!dval(&rv)) { - if (bc.nd >nd) { - bc.uflchk = 1; + if (bc.nd >nd) break; - } goto undfl; } } @@ -1801,10 +1820,8 @@ _Py_dg_strtod(const char *s00, char **se) aadj = aadj1 = 1.; else if (word1(&rv) || word0(&rv) & Bndry_mask) { if (word1(&rv) == Tiny1 && !word0(&rv)) { - if (bc.nd >nd) { - bc.uflchk = 1; + if (bc.nd >nd) break; - } goto undfl; } aadj = 1.; -- cgit v1.2.1 From 96553e7070ed19ab1d169f199ae0e23641a93bfd Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Thu, 14 Jan 2010 15:37:49 +0000 Subject: Merged revisions 77477-77478,77481-77483,77490-77493 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77477 | mark.dickinson | 2010-01-13 18:21:53 +0000 (Wed, 13 Jan 2010) | 1 line Add comments explaining the role of the bigcomp function in dtoa.c. ........ r77478 | mark.dickinson | 2010-01-13 19:02:37 +0000 (Wed, 13 Jan 2010) | 1 line Clarify that sulp expects a nonnegative input, but that +0.0 is fine. ........ r77481 | mark.dickinson | 2010-01-13 20:55:03 +0000 (Wed, 13 Jan 2010) | 1 line Simplify and annotate the bigcomp function, removing unused special cases. ........ r77482 | mark.dickinson | 2010-01-13 22:15:53 +0000 (Wed, 13 Jan 2010) | 1 line Fix buggy comparison: LHS of comparison was being treated as unsigned. ........ r77483 | mark.dickinson | 2010-01-13 22:20:10 +0000 (Wed, 13 Jan 2010) | 1 line More dtoa.c cleanup; remove the need for bc.dplen, bc.dp0 and bc.dp1. ........ r77490 | mark.dickinson | 2010-01-14 13:02:36 +0000 (Thu, 14 Jan 2010) | 1 line Fix off-by-one error introduced in r77483. I have a test for this, but it currently fails due to a different dtoa.c bug; I'll add the test once that bug is fixed. ........ r77491 | mark.dickinson | 2010-01-14 13:14:49 +0000 (Thu, 14 Jan 2010) | 1 line Issue 7632: fix a dtoa.c bug (bug 6) causing incorrect rounding. Tests to follow. ........ r77492 | mark.dickinson | 2010-01-14 14:40:20 +0000 (Thu, 14 Jan 2010) | 1 line Issue 7632: fix incorrect rounding for long input strings with values very close to a power of 2. (See Bug 4 in the tracker discussion.) ........ r77493 | mark.dickinson | 2010-01-14 15:22:33 +0000 (Thu, 14 Jan 2010) | 1 line Issue #7632: add tests for bugs fixed so far. ........ --- Python/dtoa.c | 258 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 145 insertions(+), 113 deletions(-) (limited to 'Python') diff --git a/Python/dtoa.c b/Python/dtoa.c index 1fe20f4f53..51895c7789 100644 --- a/Python/dtoa.c +++ b/Python/dtoa.c @@ -270,7 +270,7 @@ typedef union { double d; ULong L[2]; } U; typedef struct BCinfo BCinfo; struct BCinfo { - int dp0, dp1, dplen, dsign, e0, nd, nd0, scale; + int dsign, e0, nd, nd0, scale; }; #define FFFFFFFF 0xffffffffUL @@ -437,7 +437,7 @@ multadd(Bigint *b, int m, int a) /* multiply by m and add a */ NULL on failure. */ static Bigint * -s2b(const char *s, int nd0, int nd, ULong y9, int dplen) +s2b(const char *s, int nd0, int nd, ULong y9) { Bigint *b; int i, k; @@ -451,18 +451,16 @@ s2b(const char *s, int nd0, int nd, ULong y9, int dplen) b->x[0] = y9; b->wds = 1; - i = 9; - if (9 < nd0) { - s += 9; - do { - b = multadd(b, 10, *s++ - '0'); - if (b == NULL) - return NULL; - } while(++i < nd0); - s += dplen; + if (nd <= 9) + return b; + + s += 9; + for (i = 9; i < nd0; i++) { + b = multadd(b, 10, *s++ - '0'); + if (b == NULL) + return NULL; } - else - s += dplen + 9; + s++; for(; i < nd; i++) { b = multadd(b, 10, *s++ - '0'); if (b == NULL) @@ -1130,76 +1128,120 @@ quorem(Bigint *b, Bigint *S) return q; } -/* version of ulp(x) that takes bc.scale into account. +/* sulp(x) is a version of ulp(x) that takes bc.scale into account. - Assuming that x is finite and nonzero, and x / 2^bc.scale is exactly - representable as a double, sulp(x) is equivalent to 2^bc.scale * ulp(x / - 2^bc.scale). */ + Assuming that x is finite and nonnegative (positive zero is fine + here) and x / 2^bc.scale is exactly representable as a double, + sulp(x) is equivalent to 2^bc.scale * ulp(x / 2^bc.scale). */ static double sulp(U *x, BCinfo *bc) { U u; - if (bc->scale && 2*P + 1 - ((word0(x) & Exp_mask) >> Exp_shift) > 0) { + if (bc->scale && 2*P + 1 > (int)((word0(x) & Exp_mask) >> Exp_shift)) { /* rv/2^bc->scale is subnormal */ word0(&u) = (P+2)*Exp_msk1; word1(&u) = 0; return u.d; } - else + else { + assert(word0(x) || word1(x)); /* x != 0.0 */ return ulp(x); + } } -/* return 0 on success, -1 on failure */ +/* The bigcomp function handles some hard cases for strtod, for inputs + with more than STRTOD_DIGLIM digits. It's called once an initial + estimate for the double corresponding to the input string has + already been obtained by the code in _Py_dg_strtod. + + The bigcomp function is only called after _Py_dg_strtod has found a + double value rv such that either rv or rv + 1ulp represents the + correctly rounded value corresponding to the original string. It + determines which of these two values is the correct one by + computing the decimal digits of rv + 0.5ulp and comparing them with + the corresponding digits of s0. + + In the following, write dv for the absolute value of the number represented + by the input string. + + Inputs: + + s0 points to the first significant digit of the input string. + + rv is a (possibly scaled) estimate for the closest double value to the + value represented by the original input to _Py_dg_strtod. If + bc->scale is nonzero, then rv/2^(bc->scale) is the approximation to + the input value. + + bc is a struct containing information gathered during the parsing and + estimation steps of _Py_dg_strtod. Description of fields follows: + + bc->dsign is 1 if rv < decimal value, 0 if rv >= decimal value. In + normal use, it should almost always be 1 when bigcomp is entered. + + bc->e0 gives the exponent of the input value, such that dv = (integer + given by the bd->nd digits of s0) * 10**e0 + + bc->nd gives the total number of significant digits of s0. It will + be at least 1. + + bc->nd0 gives the number of significant digits of s0 before the + decimal separator. If there's no decimal separator, bc->nd0 == + bc->nd. + + bc->scale is the value used to scale rv to avoid doing arithmetic with + subnormal values. It's either 0 or 2*P (=106). + + Outputs: + + On successful exit, rv/2^(bc->scale) is the closest double to dv. + + Returns 0 on success, -1 on failure (e.g., due to a failed malloc call). */ static int bigcomp(U *rv, const char *s0, BCinfo *bc) { Bigint *b, *d; - int b2, bbits, d2, dd, dig, dsign, i, j, nd, nd0, p2, p5, speccase; + int b2, bbits, d2, dd, i, nd, nd0, odd, p2, p5; - dsign = bc->dsign; + dd = 0; /* silence compiler warning about possibly unused variable */ nd = bc->nd; nd0 = bc->nd0; p5 = nd + bc->e0; - speccase = 0; - if (rv->d == 0.) { /* special case: value near underflow-to-zero */ - /* threshold was rounded to zero */ - b = i2b(1); + if (rv->d == 0.) { + /* special case because d2b doesn't handle 0.0 */ + b = i2b(0); if (b == NULL) return -1; - p2 = Emin - P + 1; - bbits = 1; - word0(rv) = (P+2) << Exp_shift; - i = 0; - { - speccase = 1; - --p2; - dsign = 0; - goto have_i; - } + p2 = Emin - P + 1; /* = -1074 for IEEE 754 binary64 */ + bbits = 0; } - else - { + else { b = d2b(rv, &p2, &bbits); if (b == NULL) return -1; + p2 -= bc->scale; } - p2 -= bc->scale; - /* floor(log2(rv)) == bbits - 1 + p2 */ - /* Check for denormal case. */ + /* now rv/2^(bc->scale) = b * 2**p2, and b has bbits significant bits */ + + /* Replace (b, p2) by (b << i, p2 - i), with i the largest integer such + that b << i has at most P significant bits and p2 - i >= Emin - P + + 1. */ i = P - bbits; - if (i > (j = P - Emin - 1 + p2)) { - i = j; - } - { - b = lshift(b, ++i); - if (b == NULL) - return -1; - b->x[0] |= 1; - } - have_i: + if (i > p2 - (Emin - P + 1)) + i = p2 - (Emin - P + 1); + /* increment i so that we shift b by an extra bit; then or-ing a 1 into + the lsb of b gives us rv/2^(bc->scale) + 0.5ulp. */ + b = lshift(b, ++i); + if (b == NULL) + return -1; + /* record whether the lsb of rv/2^(bc->scale) is odd: in the exact halfway + case, this is used for round to even. */ + odd = b->x[0] & 2; + b->x[0] |= 1; + p2 -= p5 + i; d = i2b(1); if (d == NULL) { @@ -1247,92 +1289,58 @@ bigcomp(U *rv, const char *s0, BCinfo *bc) } } - /* Now 10*b/d = exactly half-way between the two floating-point values - on either side of the input string. If b >= d, round down. */ + /* if b >= d, round down */ if (cmp(b, d) >= 0) { dd = -1; goto ret; } - - /* Compute first digit of 10*b/d. */ - b = multadd(b, 10, 0); - if (b == NULL) { - Bfree(d); - return -1; - } - dig = quorem(b, d); - assert(dig < 10); /* Compare b/d with s0 */ - - assert(nd > 0); - dd = 9999; /* silence gcc compiler warning */ - for(i = 0; i < nd0; ) { - if ((dd = s0[i++] - '0' - dig)) - goto ret; - if (!b->x[0] && b->wds == 1) { - if (i < nd) - dd = 1; - goto ret; - } + for(i = 0; i < nd0; i++) { b = multadd(b, 10, 0); if (b == NULL) { Bfree(d); return -1; } - dig = quorem(b,d); - } - for(j = bc->dp1; i++ < nd;) { - if ((dd = s0[j++] - '0' - dig)) + dd = *s0++ - '0' - quorem(b, d); + if (dd) goto ret; if (!b->x[0] && b->wds == 1) { - if (i < nd) + if (i < nd - 1) dd = 1; goto ret; } + } + s0++; + for(; i < nd; i++) { b = multadd(b, 10, 0); if (b == NULL) { Bfree(d); return -1; } - dig = quorem(b,d); + dd = *s0++ - '0' - quorem(b, d); + if (dd) + goto ret; + if (!b->x[0] && b->wds == 1) { + if (i < nd - 1) + dd = 1; + goto ret; + } } if (b->x[0] || b->wds > 1) dd = -1; ret: Bfree(b); Bfree(d); - if (speccase) { - if (dd <= 0) - rv->d = 0.; - } - else if (dd < 0) { - if (!dsign) /* does not happen for round-near */ - retlow1: - dval(rv) -= sulp(rv, bc); - } - else if (dd > 0) { - if (dsign) { - rethi1: - dval(rv) += sulp(rv, bc); - } - } - else { - /* Exact half-way case: apply round-even rule. */ - if (word1(rv) & 1) { - if (dsign) - goto rethi1; - goto retlow1; - } - } - + if (dd > 0 || (dd == 0 && odd)) + dval(rv) += sulp(rv, bc); return 0; } double _Py_dg_strtod(const char *s00, char **se) { - int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, e, e1, error; + int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dp0, dp1, dplen, e, e1, error; int esign, i, j, k, nd, nd0, nf, nz, nz0, sign; const char *s, *s0, *s1; double aadj, aadj1; @@ -1341,7 +1349,7 @@ _Py_dg_strtod(const char *s00, char **se) BCinfo bc; Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; - sign = nz0 = nz = bc.dplen = 0; + sign = nz0 = nz = dplen = 0; dval(&rv) = 0.; for(s = s00;;s++) switch(*s) { case '-': @@ -1380,11 +1388,11 @@ _Py_dg_strtod(const char *s00, char **se) else if (nd < 16) z = 10*z + c - '0'; nd0 = nd; - bc.dp0 = bc.dp1 = s - s0; + dp0 = dp1 = s - s0; if (c == '.') { c = *++s; - bc.dp1 = s - s0; - bc.dplen = bc.dp1 - bc.dp0; + dp1 = s - s0; + dplen = 1; if (!nd) { for(; c == '0'; c = *++s) nz++; @@ -1587,10 +1595,10 @@ _Py_dg_strtod(const char *s00, char **se) /* in IEEE arithmetic. */ i = j = 18; if (i > nd0) - j += bc.dplen; + j += dplen; for(;;) { - if (--j <= bc.dp1 && j >= bc.dp0) - j = bc.dp0 - 1; + if (--j <= dp1 && j >= dp0) + j = dp0 - 1; if (s0[j] != '0') break; --i; @@ -1603,11 +1611,11 @@ _Py_dg_strtod(const char *s00, char **se) y = 0; for(i = 0; i < nd0; ++i) y = 10*y + s0[i] - '0'; - for(j = bc.dp1; i < nd; ++i) + for(j = dp1; i < nd; ++i) y = 10*y + s0[j++] - '0'; } } - bd0 = s2b(s0, nd0, nd, y, bc.dplen); + bd0 = s2b(s0, nd0, nd, y); if (bd0 == NULL) goto failed_malloc; @@ -1730,6 +1738,30 @@ _Py_dg_strtod(const char *s00, char **se) if (bc.nd > nd && i <= 0) { if (bc.dsign) break; /* Must use bigcomp(). */ + + /* Here rv overestimates the truncated decimal value by at most + 0.5 ulp(rv). Hence rv either overestimates the true decimal + value by <= 0.5 ulp(rv), or underestimates it by some small + amount (< 0.1 ulp(rv)); either way, rv is within 0.5 ulps of + the true decimal value, so it's possible to exit. + + Exception: if scaled rv is a normal exact power of 2, but not + DBL_MIN, then rv - 0.5 ulp(rv) takes us all the way down to the + next double, so the correctly rounded result is either rv - 0.5 + ulp(rv) or rv; in this case, use bigcomp to distinguish. */ + + if (!word1(&rv) && !(word0(&rv) & Bndry_mask)) { + /* rv can't be 0, since it's an overestimate for some + nonzero value. So rv is a normal power of 2. */ + j = (int)(word0(&rv) & Exp_mask) >> Exp_shift; + /* rv / 2^bc.scale = 2^(j - 1023 - bc.scale); use bigcomp if + rv / 2^bc.scale >= 2^-1021. */ + if (j - bc.scale >= 2) { + dval(&rv) -= 0.5 * sulp(&rv, &bc); + break; + } + } + { bc.nd = nd; i = -1; /* Discarded digits make delta smaller. */ -- cgit v1.2.1 From 5de672538756075dc18260da81681bc22f8d43ff Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sat, 16 Jan 2010 18:10:25 +0000 Subject: Merged revisions 77519,77530,77533 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77519 | mark.dickinson | 2010-01-16 10:44:00 +0000 (Sat, 16 Jan 2010) | 5 lines Issue #7632: Fix a serious wrong output bug for string -> float conversion. Also remove some now unused variables, and add comments clarifying the possible outputs of the parsing section of _Py_dg_strtod. Thanks Eric Smith for reviewing. ........ r77530 | mark.dickinson | 2010-01-16 17:57:49 +0000 (Sat, 16 Jan 2010) | 3 lines Issue #7632: Fix one more case of incorrect rounding for str -> float conversion (see bug 5 in the issue tracker). ........ r77533 | mark.dickinson | 2010-01-16 18:06:17 +0000 (Sat, 16 Jan 2010) | 1 line Fix multiple uses of variable 'L' in _Py_dg_strtod, where one use requires an unsigned long and the other a signed long. See also r77421. ........ --- Python/dtoa.c | 126 +++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 89 insertions(+), 37 deletions(-) (limited to 'Python') diff --git a/Python/dtoa.c b/Python/dtoa.c index 51895c7789..9eb8cdba89 100644 --- a/Python/dtoa.c +++ b/Python/dtoa.c @@ -1340,16 +1340,17 @@ bigcomp(U *rv, const char *s0, BCinfo *bc) double _Py_dg_strtod(const char *s00, char **se) { - int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dp0, dp1, dplen, e, e1, error; + int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, e, e1, error; int esign, i, j, k, nd, nd0, nf, nz, nz0, sign; const char *s, *s0, *s1; double aadj, aadj1; U aadj2, adj, rv, rv0; - ULong y, z, L; + ULong y, z, abse; + Long L; BCinfo bc; Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; - sign = nz0 = nz = dplen = 0; + sign = nz0 = nz = 0; dval(&rv) = 0.; for(s = s00;;s++) switch(*s) { case '-': @@ -1381,18 +1382,11 @@ _Py_dg_strtod(const char *s00, char **se) goto ret; } s0 = s; - y = z = 0; for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) - if (nd < 9) - y = 10*y + c - '0'; - else if (nd < 16) - z = 10*z + c - '0'; + ; nd0 = nd; - dp0 = dp1 = s - s0; if (c == '.') { c = *++s; - dp1 = s - s0; - dplen = 1; if (!nd) { for(; c == '0'; c = *++s) nz++; @@ -1409,15 +1403,7 @@ _Py_dg_strtod(const char *s00, char **se) nz++; if (c -= '0') { nf += nz; - for(i = 1; i < nz; i++) - if (nd++ < 9) - y *= 10; - else if (nd <= DBL_DIG + 1) - z *= 10; - if (nd++ < 9) - y = 10*y + c; - else if (nd <= DBL_DIG + 1) - z = 10*z + c; + nd += nz; nz = 0; } } @@ -1440,17 +1426,17 @@ _Py_dg_strtod(const char *s00, char **se) while(c == '0') c = *++s; if (c > '0' && c <= '9') { - L = c - '0'; + abse = c - '0'; s1 = s; while((c = *++s) >= '0' && c <= '9') - L = 10*L + c - '0'; - if (s - s1 > 8 || L > MAX_ABS_EXP) + abse = 10*abse + c - '0'; + if (s - s1 > 8 || abse > MAX_ABS_EXP) /* Avoid confusion from exponents * so large that e might overflow. */ e = (int)MAX_ABS_EXP; /* safe for 16 bit ints */ else - e = (int)L; + e = (int)abse; if (esign) e = -e; } @@ -1468,15 +1454,78 @@ _Py_dg_strtod(const char *s00, char **se) } goto ret; } - bc.e0 = e1 = e -= nf; + e -= nf; + if (!nd0) + nd0 = nd; + + /* strip trailing zeros */ + for (i = nd; i > 0; ) { + /* scan back until we hit a nonzero digit. significant digit 'i' + is s0[i] if i < nd0, s0[i+1] if i >= nd0. */ + --i; + if (s0[i < nd0 ? i : i+1] != '0') { + ++i; + break; + } + } + e += nd - i; + nd = i; + if (nd0 > nd) + nd0 = nd; /* Now we have nd0 digits, starting at s0, followed by a * decimal point, followed by nd-nd0 digits. The number we're * after is the integer represented by those digits times * 10**e */ - if (!nd0) - nd0 = nd; + bc.e0 = e1 = e; + + /* Summary of parsing results. The parsing stage gives values + * s0, nd0, nd, e, sign, where: + * + * - s0 points to the first significant digit of the input string s00; + * + * - nd is the total number of significant digits (here, and + * below, 'significant digits' means the set of digits of the + * significand of the input that remain after ignoring leading + * and trailing zeros. + * + * - nd0 indicates the position of the decimal point (if + * present): so the nd significant digits are in s0[0:nd0] and + * s0[nd0+1:nd+1] using the usual Python half-open slice + * notation. (If nd0 < nd, then s0[nd0] necessarily contains + * a '.' character; if nd0 == nd, then it could be anything.) + * + * - e is the adjusted exponent: the absolute value of the number + * represented by the original input string is n * 10**e, where + * n is the integer represented by the concatenation of + * s0[0:nd0] and s0[nd0+1:nd+1] + * + * - sign gives the sign of the input: 1 for negative, 0 for positive + * + * - the first and last significant digits are nonzero + */ + + /* put first DBL_DIG+1 digits into integer y and z. + * + * - y contains the value represented by the first min(9, nd) + * significant digits + * + * - if nd > 9, z contains the value represented by significant digits + * with indices in [9, min(16, nd)). So y * 10**(min(16, nd) - 9) + z + * gives the value represented by the first min(16, nd) sig. digits. + */ + + y = z = 0; + for (i = 0; i < nd; i++) { + if (i < 9) + y = 10*y + s0[i < nd0 ? i : i+1] - '0'; + else if (i < DBL_DIG+1) + z = 10*z + s0[i < nd0 ? i : i+1] - '0'; + else + break; + } + k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; dval(&rv) = y; if (k > 9) { @@ -1593,15 +1642,18 @@ _Py_dg_strtod(const char *s00, char **se) /* ASSERT(STRTOD_DIGLIM >= 18); 18 == one more than the */ /* minimum number of decimal digits to distinguish double values */ /* in IEEE arithmetic. */ - i = j = 18; - if (i > nd0) - j += dplen; - for(;;) { - if (--j <= dp1 && j >= dp0) - j = dp0 - 1; - if (s0[j] != '0') - break; + + /* Truncate input to 18 significant digits, then discard any trailing + zeros on the result by updating nd, nd0, e and y suitably. (There's + no need to update z; it's not reused beyond this point.) */ + for (i = 18; i > 0; ) { + /* scan back until we hit a nonzero digit. significant digit 'i' + is s0[i] if i < nd0, s0[i+1] if i >= nd0. */ --i; + if (s0[i < nd0 ? i : i+1] != '0') { + ++i; + break; + } } e += nd - i; nd = i; @@ -1611,8 +1663,8 @@ _Py_dg_strtod(const char *s00, char **se) y = 0; for(i = 0; i < nd0; ++i) y = 10*y + s0[i] - '0'; - for(j = dp1; i < nd; ++i) - y = 10*y + s0[j++] - '0'; + for(; i < nd; ++i) + y = 10*y + s0[i+1] - '0'; } } bd0 = s2b(s0, nd0, nd, y); -- cgit v1.2.1 From 21626fd023758b13af68da0aaf036123fd60b6a7 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sat, 16 Jan 2010 18:37:38 +0000 Subject: Issue #6690: Optimize the bytecode for expressions such as `x in {1, 2, 3}`, where the right hand operand is a set of constants, by turning the set into a frozenset and pre-building it as a constant. The comparison operation is made against the constant instead of building a new set each time it is executed (a similar optimization already existed which turned a list of constants into a pre-built tuple). Patch and additional tests by Dave Malcolm. --- Python/peephole.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/peephole.c b/Python/peephole.c index 104db8cb97..eeb31d54bd 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -31,7 +31,8 @@ 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. + Also works for BUILD_LIST and BUILT_SET when followed by an "in" or "not in" + test; for BUILD_SET it assembles a frozenset rather than a tuple. */ static int tuple_of_constants(unsigned char *codestr, Py_ssize_t n, PyObject *consts) @@ -41,7 +42,7 @@ tuple_of_constants(unsigned char *codestr, Py_ssize_t n, PyObject *consts) /* Pre-conditions */ assert(PyList_CheckExact(consts)); - assert(codestr[n*3] == BUILD_TUPLE || codestr[n*3] == BUILD_LIST); + assert(codestr[n*3] == BUILD_TUPLE || codestr[n*3] == BUILD_LIST || codestr[n*3] == BUILD_SET); assert(GETARG(codestr, (n*3)) == n); for (i=0 ; i= 0 && j <= lastlc && ((opcode == BUILD_TUPLE && ISBASICBLOCK(blocks, h, 3*(j+1))) || - (opcode == BUILD_LIST && + ((opcode == BUILD_LIST || opcode == BUILD_SET) && codestr[i+3]==COMPARE_OP && ISBASICBLOCK(blocks, h, 3*(j+2)) && (GETARG(codestr,i+3)==6 || -- cgit v1.2.1 From dd07a1204d269415dd0860614dfd0852a52bdc8c Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sun, 17 Jan 2010 14:39:12 +0000 Subject: Merged revisions 77578 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77578 | mark.dickinson | 2010-01-17 13:37:57 +0000 (Sun, 17 Jan 2010) | 2 lines Issue #7632: Fix a memory leak in _Py_dg_strtod. ........ --- Python/dtoa.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/dtoa.c b/Python/dtoa.c index 9eb8cdba89..24ce922607 100644 --- a/Python/dtoa.c +++ b/Python/dtoa.c @@ -1939,8 +1939,14 @@ _Py_dg_strtod(const char *s00, char **se) dval(&rv) += adj.d; if ((word0(&rv) & Exp_mask) >= Exp_msk1*(DBL_MAX_EXP+Bias-P)) { - if (word0(&rv0) == Big0 && word1(&rv0) == Big1) + if (word0(&rv0) == Big0 && word1(&rv0) == Big1) { + Bfree(bb); + Bfree(bd); + Bfree(bs); + Bfree(bd0); + Bfree(delta); goto ovfl; + } word0(&rv) = Big0; word1(&rv) = Big1; goto cont; -- cgit v1.2.1 From 18773a0cb1d9fb999fcf45227e3bc09e4876293f Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sun, 17 Jan 2010 21:02:55 +0000 Subject: Merged revisions 77589 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77589 | mark.dickinson | 2010-01-17 20:57:56 +0000 (Sun, 17 Jan 2010) | 7 lines Issue #7632: When Py_USING_MEMORY_DEBUGGER is defined, disable the private memory allocation scheme in dtoa.c, along with a piece of code that caches powers of 5 for future use. This makes it easier to detect dtoa.c memory leaks with Valgrind or similar tools. Patch by Stefan Krah. ........ --- Python/dtoa.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) (limited to 'Python') diff --git a/Python/dtoa.c b/Python/dtoa.c index 24ce922607..de3ca9e4c7 100644 --- a/Python/dtoa.c +++ b/Python/dtoa.c @@ -308,6 +308,8 @@ Bigint { typedef struct Bigint Bigint; +#ifndef Py_USING_MEMORY_DEBUGGER + /* Memory management: memory is allocated from, and returned to, Kmax+1 pools of memory, where pool k (0 <= k <= Kmax) is for Bigints b with b->maxwds == 1 << k. These pools are maintained as linked lists, with freelist[k] @@ -375,6 +377,48 @@ Bfree(Bigint *v) } } +#else + +/* Alternative versions of Balloc and Bfree that use PyMem_Malloc and + PyMem_Free directly in place of the custom memory allocation scheme above. + These are provided for the benefit of memory debugging tools like + Valgrind. */ + +/* Allocate space for a Bigint with up to 1<k = k; + rv->maxwds = x; + rv->sign = rv->wds = 0; + return rv; +} + +/* Free a Bigint allocated with Balloc */ + +static void +Bfree(Bigint *v) +{ + if (v) { + FREE((void*)v); + } +} + +#endif /* Py_USING_MEMORY_DEBUGGER */ + #define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \ y->wds*sizeof(Long) + 2*sizeof(int)) @@ -652,6 +696,8 @@ mult(Bigint *a, Bigint *b) return c; } +#ifndef Py_USING_MEMORY_DEBUGGER + /* p5s is a linked list of powers of 5 of the form 5**(2**i), i >= 2 */ static Bigint *p5s; @@ -711,6 +757,58 @@ pow5mult(Bigint *b, int k) return b; } +#else + +/* Version of pow5mult that doesn't cache powers of 5. Provided for + the benefit of memory debugging tools like Valgrind. */ + +static Bigint * +pow5mult(Bigint *b, int k) +{ + Bigint *b1, *p5, *p51; + int i; + static int p05[3] = { 5, 25, 125 }; + + if ((i = k & 3)) { + b = multadd(b, p05[i-1], 0); + if (b == NULL) + return NULL; + } + + if (!(k >>= 2)) + return b; + p5 = i2b(625); + if (p5 == NULL) { + Bfree(b); + return NULL; + } + + for(;;) { + if (k & 1) { + b1 = mult(b, p5); + Bfree(b); + b = b1; + if (b == NULL) { + Bfree(p5); + return NULL; + } + } + if (!(k >>= 1)) + break; + p51 = mult(p5, p5); + Bfree(p5); + p5 = p51; + if (p5 == NULL) { + Bfree(b); + return NULL; + } + } + Bfree(p5); + return b; +} + +#endif /* Py_USING_MEMORY_DEBUGGER */ + /* shift a Bigint b left by k bits. Return a pointer to the shifted result, or NULL on failure. If the returned pointer is distinct from b then the original b will have been Bfree'd. Ignores the sign of b. */ -- cgit v1.2.1 From 27a31683236fbfb6d7ba3a1b8041cb8690381a6b Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Thu, 21 Jan 2010 19:51:08 +0000 Subject: Merged revisions 77614-77616,77663 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77614 | mark.dickinson | 2010-01-20 17:36:31 +0000 (Wed, 20 Jan 2010) | 5 lines Various dtoa.c cleanups. 1. Despagghetify _Py_dg_strtod parsing code and exit points. 2. Simplify bigcomp comparison loop. 3. Don't set ERANGE on _Py_dg_strtod underflow (it was set inconsistently anyway). 4. Remove unused dsign field from BCinfo struct. ........ r77615 | mark.dickinson | 2010-01-20 18:02:41 +0000 (Wed, 20 Jan 2010) | 1 line Don't try to put a value into a NULL pointer. ........ r77616 | mark.dickinson | 2010-01-20 21:23:25 +0000 (Wed, 20 Jan 2010) | 1 line Additional explanatory comments for _Py_dg_strtod. ........ r77663 | mark.dickinson | 2010-01-21 17:02:53 +0000 (Thu, 21 Jan 2010) | 1 line Additional testcases for strtod. ........ --- Python/dtoa.c | 424 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 239 insertions(+), 185 deletions(-) (limited to 'Python') diff --git a/Python/dtoa.c b/Python/dtoa.c index de3ca9e4c7..9ca2dd95a0 100644 --- a/Python/dtoa.c +++ b/Python/dtoa.c @@ -270,7 +270,7 @@ typedef union { double d; ULong L[2]; } U; typedef struct BCinfo BCinfo; struct BCinfo { - int dsign, e0, nd, nd0, scale; + int e0, nd, nd0, scale; }; #define FFFFFFFF 0xffffffffUL @@ -967,8 +967,8 @@ diff(Bigint *a, Bigint *b) return c; } -/* Given a positive normal double x, return the difference between x and the next - double up. Doesn't give correct results for subnormals. */ +/* Given a positive normal double x, return the difference between x and the + next double up. Doesn't give correct results for subnormals. */ static double ulp(U *x) @@ -1276,9 +1276,6 @@ sulp(U *x, BCinfo *bc) bc is a struct containing information gathered during the parsing and estimation steps of _Py_dg_strtod. Description of fields follows: - bc->dsign is 1 if rv < decimal value, 0 if rv >= decimal value. In - normal use, it should almost always be 1 when bigcomp is entered. - bc->e0 gives the exponent of the input value, such that dv = (integer given by the bd->nd digits of s0) * 10**e0 @@ -1387,47 +1384,37 @@ bigcomp(U *rv, const char *s0, BCinfo *bc) } } - /* if b >= d, round down */ - if (cmp(b, d) >= 0) { + /* Compare s0 with b/d: set dd to -1, 0, or 1 according as s0 < b/d, s0 == + * b/d, or s0 > b/d. Here the digits of s0 are thought of as representing + * a number in the range [0.1, 1). */ + if (cmp(b, d) >= 0) + /* b/d >= 1 */ dd = -1; - goto ret; - } + else { + i = 0; + for(;;) { + b = multadd(b, 10, 0); + if (b == NULL) { + Bfree(d); + return -1; + } + dd = s0[i < nd0 ? i : i+1] - '0' - quorem(b, d); + i++; - /* Compare b/d with s0 */ - for(i = 0; i < nd0; i++) { - b = multadd(b, 10, 0); - if (b == NULL) { - Bfree(d); - return -1; - } - dd = *s0++ - '0' - quorem(b, d); - if (dd) - goto ret; - if (!b->x[0] && b->wds == 1) { - if (i < nd - 1) - dd = 1; - goto ret; - } - } - s0++; - for(; i < nd; i++) { - b = multadd(b, 10, 0); - if (b == NULL) { - Bfree(d); - return -1; - } - dd = *s0++ - '0' - quorem(b, d); - if (dd) - goto ret; - if (!b->x[0] && b->wds == 1) { - if (i < nd - 1) - dd = 1; - goto ret; + if (dd) + break; + if (!b->x[0] && b->wds == 1) { + /* b/d == 0 */ + dd = i < nd; + break; + } + if (!(i < nd)) { + /* b/d != 0, but digits of s0 exhausted */ + dd = -1; + break; + } } } - if (b->x[0] || b->wds > 1) - dd = -1; - ret: Bfree(b); Bfree(d); if (dd > 0 || (dd == 0 && odd)) @@ -1438,128 +1425,130 @@ bigcomp(U *rv, const char *s0, BCinfo *bc) double _Py_dg_strtod(const char *s00, char **se) { - int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, e, e1, error; - int esign, i, j, k, nd, nd0, nf, nz, nz0, sign; + int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, e, e1, error; + int esign, i, j, k, lz, nd, nd0, sign; const char *s, *s0, *s1; double aadj, aadj1; U aadj2, adj, rv, rv0; - ULong y, z, abse; + ULong y, z, abs_exp; Long L; BCinfo bc; Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; - sign = nz0 = nz = 0; dval(&rv) = 0.; - for(s = s00;;s++) switch(*s) { - case '-': - sign = 1; - /* no break */ - case '+': - if (*++s) - goto break2; - /* no break */ - case 0: - goto ret0; - /* modify original dtoa.c so that it doesn't accept leading whitespace - case '\t': - case '\n': - case '\v': - case '\f': - case '\r': - case ' ': - continue; - */ - default: - goto break2; - } - break2: - if (*s == '0') { - nz0 = 1; - while(*++s == '0') ; - if (!*s) - goto ret; + + /* Start parsing. */ + c = *(s = s00); + + /* Parse optional sign, if present. */ + sign = 0; + switch (c) { + case '-': + sign = 1; + /* no break */ + case '+': + c = *++s; } - s0 = s; - for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) - ; - nd0 = nd; + + /* Skip leading zeros: lz is true iff there were leading zeros. */ + s1 = s; + while (c == '0') + c = *++s; + lz = s != s1; + + /* Point s0 at the first nonzero digit (if any). nd0 will be the position + of the point relative to s0. nd will be the total number of digits + ignoring leading zeros. */ + s0 = s1 = s; + while ('0' <= c && c <= '9') + c = *++s; + nd0 = nd = s - s1; + + /* Parse decimal point and following digits. */ if (c == '.') { c = *++s; if (!nd) { - for(; c == '0'; c = *++s) - nz++; - if (c > '0' && c <= '9') { - s0 = s; - nf += nz; - nz = 0; - goto have_dig; - } - goto dig_done; - } - for(; c >= '0' && c <= '9'; c = *++s) { - have_dig: - nz++; - if (c -= '0') { - nf += nz; - nd += nz; - nz = 0; - } + s1 = s; + while (c == '0') + c = *++s; + lz = lz || s != s1; + nd0 -= s - s1; + s0 = s; } + s1 = s; + while ('0' <= c && c <= '9') + c = *++s; + nd += s - s1; + } + + /* Now lz is true if and only if there were leading zero digits, and nd + gives the total number of digits ignoring leading zeros. A valid input + must have at least one digit. */ + if (!nd && !lz) { + if (se) + *se = (char *)s00; + goto parse_error; } - dig_done: + + /* Parse exponent. */ e = 0; if (c == 'e' || c == 'E') { - if (!nd && !nz && !nz0) { - goto ret0; - } s00 = s; + c = *++s; + + /* Exponent sign. */ esign = 0; - switch(c = *++s) { + switch (c) { case '-': esign = 1; + /* no break */ case '+': c = *++s; } - if (c >= '0' && c <= '9') { - while(c == '0') - c = *++s; - if (c > '0' && c <= '9') { - abse = c - '0'; - s1 = s; - while((c = *++s) >= '0' && c <= '9') - abse = 10*abse + c - '0'; - if (s - s1 > 8 || abse > MAX_ABS_EXP) - /* Avoid confusion from exponents - * so large that e might overflow. - */ - e = (int)MAX_ABS_EXP; /* safe for 16 bit ints */ - else - e = (int)abse; - if (esign) - e = -e; - } - else - e = 0; + + /* Skip zeros. lz is true iff there are leading zeros. */ + s1 = s; + while (c == '0') + c = *++s; + lz = s != s1; + + /* Get absolute value of the exponent. */ + s1 = s; + abs_exp = 0; + while ('0' <= c && c <= '9') { + abs_exp = 10*abs_exp + (c - '0'); + c = *++s; } + + /* abs_exp will be correct modulo 2**32. But 10**9 < 2**32, so if + there are at most 9 significant exponent digits then overflow is + impossible. */ + if (s - s1 > 9 || abs_exp > MAX_ABS_EXP) + e = (int)MAX_ABS_EXP; else + e = (int)abs_exp; + if (esign) + e = -e; + + /* A valid exponent must have at least one digit. */ + if (s == s1 && !lz) s = s00; } - if (!nd) { - if (!nz && !nz0) { - ret0: - s = s00; - sign = 0; - } - goto ret; - } - e -= nf; - if (!nd0) + + /* Adjust exponent to take into account position of the point. */ + e -= nd - nd0; + if (nd0 <= 0) nd0 = nd; - /* strip trailing zeros */ + /* Finished parsing. Set se to indicate how far we parsed */ + if (se) + *se = (char *)s; + + /* If all digits were zero, exit with return value +-0.0. Otherwise, + strip trailing zeros: scan back until we hit a nonzero digit. */ + if (!nd) + goto ret; for (i = nd; i > 0; ) { - /* scan back until we hit a nonzero digit. significant digit 'i' - is s0[i] if i < nd0, s0[i+1] if i >= nd0. */ --i; if (s0[i < nd0 ? i : i+1] != '0') { ++i; @@ -1571,28 +1560,21 @@ _Py_dg_strtod(const char *s00, char **se) if (nd0 > nd) nd0 = nd; - /* Now we have nd0 digits, starting at s0, followed by a - * decimal point, followed by nd-nd0 digits. The number we're - * after is the integer represented by those digits times - * 10**e */ - - bc.e0 = e1 = e; - - /* Summary of parsing results. The parsing stage gives values - * s0, nd0, nd, e, sign, where: + /* Summary of parsing results. After parsing, and dealing with zero + * inputs, we have values s0, nd0, nd, e, sign, where: * - * - s0 points to the first significant digit of the input string s00; + * - s0 points to the first significant digit of the input string * * - nd is the total number of significant digits (here, and * below, 'significant digits' means the set of digits of the * significand of the input that remain after ignoring leading - * and trailing zeros. + * and trailing zeros). * - * - nd0 indicates the position of the decimal point (if - * present): so the nd significant digits are in s0[0:nd0] and - * s0[nd0+1:nd+1] using the usual Python half-open slice - * notation. (If nd0 < nd, then s0[nd0] necessarily contains - * a '.' character; if nd0 == nd, then it could be anything.) + * - nd0 indicates the position of the decimal point, if present; it + * satisfies 1 <= nd0 <= nd. The nd significant digits are in + * s0[0:nd0] and s0[nd0+1:nd+1] using the usual Python half-open slice + * notation. (If nd0 < nd, then s0[nd0] contains a '.' character; if + * nd0 == nd, then s0[nd0] could be any non-digit character.) * * - e is the adjusted exponent: the absolute value of the number * represented by the original input string is n * 10**e, where @@ -1614,6 +1596,7 @@ _Py_dg_strtod(const char *s00, char **se) * gives the value represented by the first min(16, nd) sig. digits. */ + bc.e0 = e1 = e; y = z = 0; for (i = 0; i < nd; i++) { if (i < 9) @@ -1666,14 +1649,8 @@ _Py_dg_strtod(const char *s00, char **se) if ((i = e1 & 15)) dval(&rv) *= tens[i]; if (e1 &= ~15) { - if (e1 > DBL_MAX_10_EXP) { - ovfl: - errno = ERANGE; - /* Can't trust HUGE_VAL */ - word0(&rv) = Exp_mask; - word1(&rv) = 0; - goto ret; - } + if (e1 > DBL_MAX_10_EXP) + goto ovfl; e1 >>= 4; for(j = 0; e1 > 1; j++, e1 >>= 1) if (e1 & 1) @@ -1695,6 +1672,16 @@ _Py_dg_strtod(const char *s00, char **se) } } else if (e1 < 0) { + /* The input decimal value lies in [10**e1, 10**(e1+16)). + + If e1 <= -512, underflow immediately. + If e1 <= -256, set bc.scale to 2*P. + + So for input value < 1e-256, bc.scale is always set; + for input value >= 1e-240, bc.scale is never set. + For input values in [1e-256, 1e-240), bc.scale may or may + not be set. */ + e1 = -e1; if ((i = e1 & 15)) dval(&rv) /= tens[i]; @@ -1719,12 +1706,8 @@ _Py_dg_strtod(const char *s00, char **se) else word1(&rv) &= 0xffffffff << j; } - if (!dval(&rv)) { - undfl: - dval(&rv) = 0.; - errno = ERANGE; - goto ret; - } + if (!dval(&rv)) + goto undfl; } } @@ -1769,7 +1752,34 @@ _Py_dg_strtod(const char *s00, char **se) if (bd0 == NULL) goto failed_malloc; + /* Notation for the comments below. Write: + + - dv for the absolute value of the number represented by the original + decimal input string. + + - if we've truncated dv, write tdv for the truncated value. + Otherwise, set tdv == dv. + + - srv for the quantity rv/2^bc.scale; so srv is the current binary + approximation to tdv (and dv). It should be exactly representable + in an IEEE 754 double. + */ + for(;;) { + + /* This is the main correction loop for _Py_dg_strtod. + + We've got a decimal value tdv, and a floating-point approximation + srv=rv/2^bc.scale to tdv. The aim is to determine whether srv is + close enough (i.e., within 0.5 ulps) to tdv, and to compute a new + approximation if not. + + To determine whether srv is close enough to tdv, compute integers + bd, bb and bs proportional to tdv, srv and 0.5 ulp(srv) + respectively, and then use integer arithmetic to determine whether + |tdv - srv| is less than, equal to, or greater than 0.5 ulp(srv). + */ + bd = Balloc(bd0->k); if (bd == NULL) { Bfree(bd0); @@ -1782,6 +1792,7 @@ _Py_dg_strtod(const char *s00, char **se) Bfree(bd0); goto failed_malloc; } + /* tdv = bd * 10^e; srv = bb * 2^(bbe - scale) */ bs = i2b(1); if (bs == NULL) { Bfree(bb); @@ -1802,6 +1813,17 @@ _Py_dg_strtod(const char *s00, char **se) bb2 += bbe; else bd2 -= bbe; + + /* At this stage e = bd2 - bb2 + bbe = bd5 - bb5, so: + + tdv = bd * 2^(bbe + bd2 - bb2) * 5^(bd5 - bb5) + srv = bb * 2^(bbe - scale). + + Compute j such that + + 0.5 ulp(srv) = 2^(bbe - scale - j) + */ + bs2 = bb2; j = bbe - bc.scale; i = j + bbbits - 1; /* logb(rv) */ @@ -1809,9 +1831,26 @@ _Py_dg_strtod(const char *s00, char **se) j += P - Emin; else j = P + 1 - bbbits; + + /* Now we have: + + M * tdv = bd * 2^(bd2 + scale + j) * 5^bd5 + M * srv = bb * 2^(bb2 + j) * 5^bb5 + M * 0.5 ulp(srv) = 2^bs2 * 5^bb5 + + where M is the constant (currently) represented by 2^(j + scale + + bb2 - bbe) * 5^bb5. + */ + bb2 += j; bd2 += j; bd2 += bc.scale; + + /* After the adjustments above, tdv, srv and 0.5 ulp(srv) are + proportional to: bd * 2^bd2 * 5^bd5, bb * 2^bb2 * 5^bb5, and + bs * 2^bs2 * 5^bb5, respectively. */ + + /* Remove excess powers of 2. i = min(bb2, bd2, bs2). */ i = bb2 < bd2 ? bb2 : bd2; if (i > bs2) i = bs2; @@ -1820,6 +1859,8 @@ _Py_dg_strtod(const char *s00, char **se) bd2 -= i; bs2 -= i; } + + /* Scale bb, bd, bs by the appropriate powers of 2 and 5. */ if (bb5 > 0) { bs = pow5mult(bs, bb5); if (bs == NULL) { @@ -1874,6 +1915,11 @@ _Py_dg_strtod(const char *s00, char **se) goto failed_malloc; } } + + /* Now bd, bb and bs are scaled versions of tdv, srv and 0.5 ulp(srv), + respectively. Compute the difference |tdv - srv|, and compare + with 0.5 ulp(srv). */ + delta = diff(bb, bd); if (delta == NULL) { Bfree(bb); @@ -1882,11 +1928,11 @@ _Py_dg_strtod(const char *s00, char **se) Bfree(bd0); goto failed_malloc; } - bc.dsign = delta->sign; + dsign = delta->sign; delta->sign = 0; i = cmp(delta, bs); if (bc.nd > nd && i <= 0) { - if (bc.dsign) + if (dsign) break; /* Must use bigcomp(). */ /* Here rv overestimates the truncated decimal value by at most @@ -1908,7 +1954,7 @@ _Py_dg_strtod(const char *s00, char **se) rv / 2^bc.scale >= 2^-1021. */ if (j - bc.scale >= 2) { dval(&rv) -= 0.5 * sulp(&rv, &bc); - break; + break; /* Use bigcomp. */ } } @@ -1922,7 +1968,7 @@ _Py_dg_strtod(const char *s00, char **se) /* Error is less than half an ulp -- check for * special case of mantissa a power of two. */ - if (bc.dsign || word1(&rv) || word0(&rv) & Bndry_mask + if (dsign || word1(&rv) || word0(&rv) & Bndry_mask || (word0(&rv) & Exp_mask) <= (2*P+1)*Exp_msk1 ) { break; @@ -1945,7 +1991,7 @@ _Py_dg_strtod(const char *s00, char **se) } if (i == 0) { /* exactly half-way between */ - if (bc.dsign) { + if (dsign) { if ((word0(&rv) & Bndry_mask1) == Bndry_mask1 && word1(&rv) == ( (bc.scale && @@ -1957,7 +2003,7 @@ _Py_dg_strtod(const char *s00, char **se) + Exp_msk1 ; word1(&rv) = 0; - bc.dsign = 0; + dsign = 0; break; } } @@ -1972,7 +2018,7 @@ _Py_dg_strtod(const char *s00, char **se) /* accept rv */ break; /* rv = smallest denormal */ - if (bc.nd >nd) + if (bc.nd > nd) break; goto undfl; } @@ -1984,7 +2030,7 @@ _Py_dg_strtod(const char *s00, char **se) } if (!(word1(&rv) & LSB)) break; - if (bc.dsign) + if (dsign) dval(&rv) += ulp(&rv); else { dval(&rv) -= ulp(&rv); @@ -1994,11 +2040,11 @@ _Py_dg_strtod(const char *s00, char **se) goto undfl; } } - bc.dsign = 1 - bc.dsign; + dsign = 1 - dsign; break; } if ((aadj = ratio(delta, bs)) <= 2.) { - if (bc.dsign) + if (dsign) aadj = aadj1 = 1.; else if (word1(&rv) || word0(&rv) & Bndry_mask) { if (word1(&rv) == Tiny1 && !word0(&rv)) { @@ -2022,7 +2068,7 @@ _Py_dg_strtod(const char *s00, char **se) } else { aadj *= 0.5; - aadj1 = bc.dsign ? aadj : -aadj; + aadj1 = dsign ? aadj : -aadj; if (Flt_Rounds == 0) aadj1 += 0.5; } @@ -2058,7 +2104,7 @@ _Py_dg_strtod(const char *s00, char **se) if ((z = (ULong)aadj) <= 0) z = 1; aadj = z; - aadj1 = bc.dsign ? aadj : -aadj; + aadj1 = dsign ? aadj : -aadj; } dval(&aadj2) = aadj1; word0(&aadj2) += (2*P+1)*Exp_msk1 - y; @@ -2075,7 +2121,7 @@ _Py_dg_strtod(const char *s00, char **se) L = (Long)aadj; aadj -= L; /* The tolerances below are conservative. */ - if (bc.dsign || word1(&rv) || word0(&rv) & Bndry_mask) { + if (dsign || word1(&rv) || word0(&rv) & Bndry_mask) { if (aadj < .4999999 || aadj > .5000001) break; } @@ -2104,20 +2150,28 @@ _Py_dg_strtod(const char *s00, char **se) word0(&rv0) = Exp_1 - 2*P*Exp_msk1; word1(&rv0) = 0; dval(&rv) *= dval(&rv0); - /* try to avoid the bug of testing an 8087 register value */ - if (!(word0(&rv) & Exp_mask)) - errno = ERANGE; } + ret: - if (se) - *se = (char *)s; return sign ? -dval(&rv) : dval(&rv); + parse_error: + return 0.0; + failed_malloc: - if (se) - *se = (char *)s00; errno = ENOMEM; return -1.0; + + undfl: + return sign ? -0.0 : 0.0; + + ovfl: + errno = ERANGE; + /* Can't trust HUGE_VAL */ + word0(&rv) = Exp_mask; + word1(&rv) = 0; + return sign ? -dval(&rv) : dval(&rv); + } static char * -- cgit v1.2.1 From f4faa93ccec9921e76dd64e010a76b11e503bb3e Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sun, 24 Jan 2010 10:16:29 +0000 Subject: Merged revisions 77691,77698,77713-77714 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77691 | mark.dickinson | 2010-01-22 16:18:09 +0000 (Fri, 22 Jan 2010) | 1 line Correct typo in comment. ........ r77698 | mark.dickinson | 2010-01-22 17:04:07 +0000 (Fri, 22 Jan 2010) | 3 lines Issue #7743: Fix a potential incorrect rounding bug in dtoa.c (2nd bug in issue 7743). ........ r77713 | mark.dickinson | 2010-01-23 20:48:56 +0000 (Sat, 23 Jan 2010) | 3 lines Issue #7743: Add checks for zero inputs to the lshift and mult functions; this fixes the first bug described in issue #7743. ........ r77714 | mark.dickinson | 2010-01-23 21:25:53 +0000 (Sat, 23 Jan 2010) | 1 line dtoa.c fix from upstream that fixes incorrectly rounded results for certain subnormals that are also halfway cases. ........ --- Python/dtoa.c | 189 ++++++++++++++++++++++++++++++++++-------------------- Python/pystrtod.c | 2 +- 2 files changed, 122 insertions(+), 69 deletions(-) (limited to 'Python') diff --git a/Python/dtoa.c b/Python/dtoa.c index 9ca2dd95a0..4b2c6c36e3 100644 --- a/Python/dtoa.c +++ b/Python/dtoa.c @@ -235,6 +235,7 @@ typedef union { double d; ULong L[2]; } U; #define Bias 1023 #define Emax 1023 #define Emin (-1022) +#define Etiny (-1074) /* smallest denormal is 2**Etiny */ #define Exp_1 0x3ff00000 #define Exp_11 0x3ff00000 #define Ebits 11 @@ -244,7 +245,6 @@ typedef union { double d; ULong L[2]; } U; #define Bletch 0x10 #define Bndry_mask 0xfffff #define Bndry_mask1 0xfffff -#define LSB 1 #define Sign_bit 0x80000000 #define Log2P 1 #define Tiny0 0 @@ -622,6 +622,15 @@ mult(Bigint *a, Bigint *b) ULong z2; #endif + if ((!a->x[0] && a->wds == 1) || (!b->x[0] && b->wds == 1)) { + c = Balloc(0); + if (c == NULL) + return NULL; + c->wds = 1; + c->x[0] = 0; + return c; + } + if (a->wds < b->wds) { c = a; a = b; @@ -820,6 +829,9 @@ lshift(Bigint *b, int k) Bigint *b1; ULong *x, *x1, *xe, z; + if (!k || (!b->x[0] && b->wds == 1)) + return b; + n = k >> 5; k1 = b->k; n1 = n + b->wds + 1; @@ -1019,6 +1031,76 @@ b2d(Bigint *a, int *e) return dval(&d); } +/* Convert a scaled double to a Bigint plus an exponent. Similar to d2b, + except that it accepts the scale parameter used in _Py_dg_strtod (which + should be either 0 or 2*P), and the normalization for the return value is + different (see below). On input, d should be finite and nonnegative, and d + / 2**scale should be exactly representable as an IEEE 754 double. + + Returns a Bigint b and an integer e such that + + dval(d) / 2**scale = b * 2**e. + + Unlike d2b, b is not necessarily odd: b and e are normalized so + that either 2**(P-1) <= b < 2**P and e >= Etiny, or b < 2**P + and e == Etiny. This applies equally to an input of 0.0: in that + case the return values are b = 0 and e = Etiny. + + The above normalization ensures that for all possible inputs d, + 2**e gives ulp(d/2**scale). + + Returns NULL on failure. +*/ + +static Bigint * +sd2b(U *d, int scale, int *e) +{ + Bigint *b; + + b = Balloc(1); + if (b == NULL) + return NULL; + + /* First construct b and e assuming that scale == 0. */ + b->wds = 2; + b->x[0] = word1(d); + b->x[1] = word0(d) & Frac_mask; + *e = Etiny - 1 + (int)((word0(d) & Exp_mask) >> Exp_shift); + if (*e < Etiny) + *e = Etiny; + else + b->x[1] |= Exp_msk1; + + /* Now adjust for scale, provided that b != 0. */ + if (scale && (b->x[0] || b->x[1])) { + *e -= scale; + if (*e < Etiny) { + scale = Etiny - *e; + *e = Etiny; + /* We can't shift more than P-1 bits without shifting out a 1. */ + assert(0 < scale && scale <= P - 1); + if (scale >= 32) { + /* The bits shifted out should all be zero. */ + assert(b->x[0] == 0); + b->x[0] = b->x[1]; + b->x[1] = 0; + scale -= 32; + } + if (scale) { + /* The bits shifted out should all be zero. */ + assert(b->x[0] << (32 - scale) == 0); + b->x[0] = (b->x[0] >> scale) | (b->x[1] << (32 - scale)); + b->x[1] >>= scale; + } + } + } + /* Ensure b is normalized. */ + if (!b->x[1]) + b->wds = 1; + + return b; +} + /* Convert a double to a Bigint plus an exponent. Return NULL on failure. Given a finite nonzero double d, return an odd Bigint b and exponent *e @@ -1028,7 +1110,6 @@ b2d(Bigint *a, int *e) If d is zero, then b == 0, *e == -1010, *bbits = 0. */ - static Bigint * d2b(U *d, int *e, int *bits) { @@ -1299,45 +1380,29 @@ static int bigcomp(U *rv, const char *s0, BCinfo *bc) { Bigint *b, *d; - int b2, bbits, d2, dd, i, nd, nd0, odd, p2, p5; + int b2, d2, dd, i, nd, nd0, odd, p2, p5; dd = 0; /* silence compiler warning about possibly unused variable */ nd = bc->nd; nd0 = bc->nd0; p5 = nd + bc->e0; - if (rv->d == 0.) { - /* special case because d2b doesn't handle 0.0 */ - b = i2b(0); - if (b == NULL) - return -1; - p2 = Emin - P + 1; /* = -1074 for IEEE 754 binary64 */ - bbits = 0; - } - else { - b = d2b(rv, &p2, &bbits); - if (b == NULL) - return -1; - p2 -= bc->scale; - } - /* now rv/2^(bc->scale) = b * 2**p2, and b has bbits significant bits */ - - /* Replace (b, p2) by (b << i, p2 - i), with i the largest integer such - that b << i has at most P significant bits and p2 - i >= Emin - P + - 1. */ - i = P - bbits; - if (i > p2 - (Emin - P + 1)) - i = p2 - (Emin - P + 1); - /* increment i so that we shift b by an extra bit; then or-ing a 1 into - the lsb of b gives us rv/2^(bc->scale) + 0.5ulp. */ - b = lshift(b, ++i); + b = sd2b(rv, bc->scale, &p2); if (b == NULL) return -1; + /* record whether the lsb of rv/2^(bc->scale) is odd: in the exact halfway case, this is used for round to even. */ - odd = b->x[0] & 2; + odd = b->x[0] & 1; + + /* left shift b by 1 bit and or a 1 into the least significant bit; + this gives us b * 2**p2 = rv/2^(bc->scale) + 0.5 ulp. */ + b = lshift(b, 1); + if (b == NULL) + return -1; b->x[0] |= 1; + p2--; - p2 -= p5 + i; + p2 -= p5; d = i2b(1); if (d == NULL) { Bfree(b); @@ -1425,8 +1490,8 @@ bigcomp(U *rv, const char *s0, BCinfo *bc) double _Py_dg_strtod(const char *s00, char **se) { - int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, e, e1, error; - int esign, i, j, k, lz, nd, nd0, sign; + int bb2, bb5, bbe, bd2, bd5, bs2, c, dsign, e, e1, error; + int esign, i, j, k, lz, nd, nd0, odd, sign; const char *s, *s0, *s1; double aadj, aadj1; U aadj2, adj, rv, rv0; @@ -1786,13 +1851,17 @@ _Py_dg_strtod(const char *s00, char **se) goto failed_malloc; } Bcopy(bd, bd0); - bb = d2b(&rv, &bbe, &bbbits); /* rv = bb * 2^bbe */ + bb = sd2b(&rv, bc.scale, &bbe); /* srv = bb * 2^bbe */ if (bb == NULL) { Bfree(bd); Bfree(bd0); goto failed_malloc; } - /* tdv = bd * 10^e; srv = bb * 2^(bbe - scale) */ + /* Record whether lsb of bb is odd, in case we need this + for the round-to-even step later. */ + odd = bb->x[0] & 1; + + /* tdv = bd * 10**e; srv = bb * 2**bbe */ bs = i2b(1); if (bs == NULL) { Bfree(bb); @@ -1813,44 +1882,28 @@ _Py_dg_strtod(const char *s00, char **se) bb2 += bbe; else bd2 -= bbe; - - /* At this stage e = bd2 - bb2 + bbe = bd5 - bb5, so: - - tdv = bd * 2^(bbe + bd2 - bb2) * 5^(bd5 - bb5) - srv = bb * 2^(bbe - scale). - - Compute j such that - - 0.5 ulp(srv) = 2^(bbe - scale - j) - */ - bs2 = bb2; - j = bbe - bc.scale; - i = j + bbbits - 1; /* logb(rv) */ - if (i < Emin) /* denormal */ - j += P - Emin; - else - j = P + 1 - bbbits; + bb2++; + bd2++; - /* Now we have: + /* At this stage bd5 - bb5 == e == bd2 - bb2 + bbe, bb2 - bs2 == 1, + and bs == 1, so: - M * tdv = bd * 2^(bd2 + scale + j) * 5^bd5 - M * srv = bb * 2^(bb2 + j) * 5^bb5 - M * 0.5 ulp(srv) = 2^bs2 * 5^bb5 + tdv == bd * 10**e = bd * 2**(bbe - bb2 + bd2) * 5**(bd5 - bb5) + srv == bb * 2**bbe = bb * 2**(bbe - bb2 + bb2) + 0.5 ulp(srv) == 2**(bbe-1) = bs * 2**(bbe - bb2 + bs2) - where M is the constant (currently) represented by 2^(j + scale + - bb2 - bbe) * 5^bb5. - */ + It follows that: - bb2 += j; - bd2 += j; - bd2 += bc.scale; + M * tdv = bd * 2**bd2 * 5**bd5 + M * srv = bb * 2**bb2 * 5**bb5 + M * 0.5 ulp(srv) = bs * 2**bs2 * 5**bb5 - /* After the adjustments above, tdv, srv and 0.5 ulp(srv) are - proportional to: bd * 2^bd2 * 5^bd5, bb * 2^bb2 * 5^bb5, and - bs * 2^bs2 * 5^bb5, respectively. */ + for some constant M. (Actually, M == 2**(bb2 - bbe) * 5**bb5, but + this fact is not needed below.) + */ - /* Remove excess powers of 2. i = min(bb2, bd2, bs2). */ + /* Remove factor of 2**i, where i = min(bb2, bd2, bs2). */ i = bb2 < bd2 ? bb2 : bd2; if (i > bs2) i = bs2; @@ -2028,12 +2081,12 @@ _Py_dg_strtod(const char *s00, char **se) word1(&rv) = 0xffffffff; break; } - if (!(word1(&rv) & LSB)) + if (!odd) break; if (dsign) - dval(&rv) += ulp(&rv); + dval(&rv) += sulp(&rv, &bc); else { - dval(&rv) -= ulp(&rv); + dval(&rv) -= sulp(&rv, &bc); if (!dval(&rv)) { if (bc.nd >nd) break; diff --git a/Python/pystrtod.c b/Python/pystrtod.c index d1eb71d7b8..5543c58b5a 100644 --- a/Python/pystrtod.c +++ b/Python/pystrtod.c @@ -104,7 +104,7 @@ _PyOS_ascii_strtod(const char *nptr, char **endptr) _Py_SET_53BIT_PRECISION_END; if (*endptr == nptr) - /* string might represent and inf or nan */ + /* string might represent an inf or nan */ result = _Py_parse_inf_or_nan(nptr, endptr); return result; -- cgit v1.2.1 From 50693e14ea5773ef348871831209ceb662eef201 Mon Sep 17 00:00:00 2001 From: Eric Smith Date: Wed, 27 Jan 2010 00:44:57 +0000 Subject: Merged revisions 77763 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77763 | eric.smith | 2010-01-26 19:28:29 -0500 (Tue, 26 Jan 2010) | 1 line Issue #7766: Change sys.getwindowsversion() return value to a named tuple and add the additional members returned in an OSVERSIONINFOEX structure. The new members are service_pack_major, service_pack_minor, suite_mask, and product_type. ........ --- Python/sysmodule.c | 75 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 62 insertions(+), 13 deletions(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 84813baee5..f1cbbba48b 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -597,26 +597,65 @@ recursion from causing an overflow of the C stack and crashing Python." 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\ -" +Return information about the running version of Windows as a named tuple.\n\ +The members are named: major, minor, build, platform, service_pack,\n\ +service_pack_major, service_pack_minor, suite_mask, and product_type. For\n\ +backward compatibiliy, only the first 5 items are available by indexing.\n\ +All elements are numbers, except service_pack which is a string. Platform\n\ +may be 0 for win32s, 1 for Windows 9x/ME, 2 for Windows NT/2000/XP/Vista/7,\n\ +3 for Windows CE. Product_type may be 1 for a workstation, 2 for a domain\n\ +controller, 3 for a server." ); +static PyTypeObject WindowsVersionType = {0, 0, 0, 0, 0, 0}; + +static PyStructSequence_Field windows_version_fields[] = { + {"major", "Major version number"}, + {"minor", "Minor version number"}, + {"build", "Build number"}, + {"platform", "Operating system platform"}, + {"service_pack", "Latest Service Pack installed on the system"}, + {"service_pack_major", "Service Pack major version number"}, + {"service_pack_minor", "Service Pack minor version number"}, + {"suite_mask", "Bit mask identifying available product suites"}, + {"product_type", "System product type"}, + {0} +}; + +static PyStructSequence_Desc windows_version_desc = { + "sys.getwindowsversion", /* name */ + getwindowsversion_doc, /* doc */ + windows_version_fields, /* fields */ + 5 /* For backward compatibility, + only the first 5 items are accessible + via indexing, the rest are name only */ +}; + static PyObject * sys_getwindowsversion(PyObject *self) { - OSVERSIONINFO ver; + PyObject *version; + int pos = 0; + OSVERSIONINFOEX ver; ver.dwOSVersionInfoSize = sizeof(ver); - if (!GetVersionEx(&ver)) + if (!GetVersionEx((OSVERSIONINFO*) &ver)) return PyErr_SetFromWindowsErr(0); - return Py_BuildValue("HHHHs", - ver.dwMajorVersion, - ver.dwMinorVersion, - ver.dwBuildNumber, - ver.dwPlatformId, - ver.szCSDVersion); + + version = PyStructSequence_New(&WindowsVersionType); + if (version == NULL) + return NULL; + + PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwMajorVersion)); + PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwMinorVersion)); + PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwBuildNumber)); + PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwPlatformId)); + PyStructSequence_SET_ITEM(version, pos++, PyUnicode_FromString(ver.szCSDVersion)); + PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wServicePackMajor)); + PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wServicePackMinor)); + PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wSuiteMask)); + PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wProductType)); + + return version; } #endif /* MS_WINDOWS */ @@ -1488,6 +1527,16 @@ _PySys_Init(void) FlagsType.tp_init = NULL; FlagsType.tp_new = NULL; + +#if defined(MS_WINDOWS) + /* getwindowsversion */ + if (WindowsVersionType.tp_name == 0) + PyStructSequence_InitType(&WindowsVersionType, &windows_version_desc); + /* prevent user from creating new instances */ + WindowsVersionType.tp_init = NULL; + WindowsVersionType.tp_new = NULL; +#endif + /* float repr style: 0.03 (short) vs 0.029999999999999999 (legacy) */ #ifndef PY_NO_SHORT_FLOAT_REPR SET_SYS_FROM_STRING("float_repr_style", -- cgit v1.2.1 From 6cc9873a4b514dcc85dc5d424d4a90a79d7e8c74 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Thu, 11 Feb 2010 02:31:04 +0000 Subject: fix comment --- Python/ceval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 321ab54d31..5d1fb285be 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2601,7 +2601,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) SET_VALUE(7, tb); SET_VALUE(6, exc); SET_VALUE(5, tp); - /* UNWIND_EXCEPT_BLOCK will pop this off. */ + /* UNWIND_EXCEPT_HANDLER will pop this off. */ SET_FOURTH(NULL); /* We just shifted the stack down, so we have to tell the except handler block that the -- cgit v1.2.1 From 75d25fbf44339e820b967664e1800deaedb44d58 Mon Sep 17 00:00:00 2001 From: Eric Smith Date: Mon, 22 Feb 2010 14:58:30 +0000 Subject: Issue #5988: Delete deprecated functions PyOS_ascii_formatd, PyOS_ascii_strtod, and PyOS_ascii_atof. --- Python/pystrtod.c | 75 +++++++++---------------------------------------------- 1 file changed, 12 insertions(+), 63 deletions(-) (limited to 'Python') diff --git a/Python/pystrtod.c b/Python/pystrtod.c index 5543c58b5a..a1d7ff09fc 100644 --- a/Python/pystrtod.c +++ b/Python/pystrtod.c @@ -58,7 +58,7 @@ _Py_parse_inf_or_nan(const char *p, char **endptr) } /** - * PyOS_ascii_strtod: + * _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. @@ -88,7 +88,7 @@ _Py_parse_inf_or_nan(const char *p, char **endptr) #ifndef PY_NO_SHORT_FLOAT_REPR -double +static double _PyOS_ascii_strtod(const char *nptr, char **endptr) { double result; @@ -121,7 +121,7 @@ _PyOS_ascii_strtod(const char *nptr, char **endptr) correctly rounded results. */ -double +static double _PyOS_ascii_strtod(const char *nptr, char **endptr) { char *fail_pos; @@ -270,48 +270,10 @@ _PyOS_ascii_strtod(const char *nptr, char **endptr) #endif -/* PyOS_ascii_strtod is DEPRECATED in Python 3.1 */ - -double -PyOS_ascii_strtod(const char *nptr, char **endptr) -{ - char *fail_pos; - const char *p; - double x; - - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "PyOS_ascii_strtod and PyOS_ascii_atof are " - "deprecated. Use PyOS_string_to_double " - "instead.", 1) < 0) - return -1.0; - - /* _PyOS_ascii_strtod already does everything that we want, - except that it doesn't parse leading whitespace */ - p = nptr; - while (Py_ISSPACE(*p)) - p++; - x = _PyOS_ascii_strtod(p, &fail_pos); - if (fail_pos == p) - fail_pos = (char *)nptr; - if (endptr) - *endptr = (char *)fail_pos; - return x; -} - -/* PyOS_ascii_strtod is DEPRECATED in Python 3.1 */ - -double -PyOS_ascii_atof(const char *nptr) -{ - return PyOS_ascii_strtod(nptr, NULL); -} - -/* PyOS_string_to_double is the recommended replacement for the deprecated - PyOS_ascii_strtod and PyOS_ascii_atof functions. It converts a - null-terminated byte string s (interpreted as a string of ASCII characters) - to a float. The string should not have leading or trailing whitespace (in - contrast, PyOS_ascii_strtod allows leading whitespace but not trailing - whitespace). The conversion is independent of the current locale. +/* PyOS_string_to_double converts a null-terminated byte string s (interpreted + as a string of ASCII characters) to a float. The string should not have + leading or trailing whitespace. The conversion is independent of the + current locale. If endptr is NULL, try to convert the whole string. Raise ValueError and return -1.0 if the string is not a valid representation of a floating-point @@ -369,6 +331,8 @@ PyOS_string_to_double(const char *s, return result; } +#ifdef PY_NO_SHORT_FLOAT_REPR + /* Given a string that may have a decimal point in the current locale, change it back to a dot. Since the string cannot get longer, no need for a maximum buffer size parameter. */ @@ -618,12 +582,13 @@ ensure_decimal_point(char* buffer, size_t buf_size, int precision) #define FLOAT_FORMATBUFLEN 120 /** - * PyOS_ascii_formatd: + * _PyOS_ascii_formatd: * @buffer: A buffer to place the resulting string in * @buf_size: The length of the buffer. * @format: The printf()-style format to use for the * code to use for converting. * @d: The #gdouble to convert + * @precision: The precision to use when formatting. * * Converts a #gdouble to a string, using the '.' as * decimal point. To format the number you pass in @@ -636,7 +601,7 @@ ensure_decimal_point(char* buffer, size_t buf_size, int precision) * Return value: The pointer to the buffer with the converted string. * On failure returns NULL but does not set any Python exception. **/ -char * +static char * _PyOS_ascii_formatd(char *buffer, size_t buf_size, const char *format, @@ -716,22 +681,6 @@ _PyOS_ascii_formatd(char *buffer, return buffer; } -char * -PyOS_ascii_formatd(char *buffer, - size_t buf_size, - const char *format, - double d) -{ - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "PyOS_ascii_formatd is deprecated, " - "use PyOS_double_to_string instead", 1) < 0) - return NULL; - - return _PyOS_ascii_formatd(buffer, buf_size, format, d, -1); -} - -#ifdef PY_NO_SHORT_FLOAT_REPR - /* The fallback code to use if _Py_dg_dtoa is not available. */ PyAPI_FUNC(char *) PyOS_double_to_string(double val, -- cgit v1.2.1 From 645dfdaf4fe8885ff0025acdbb47acae699e6e89 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Mon, 22 Feb 2010 19:41:37 +0000 Subject: Poor PLAN9, it isn't supported --- Python/errors.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'Python') diff --git a/Python/errors.c b/Python/errors.c index 42e0e6f3d5..062658d737 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -360,25 +360,17 @@ PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject) PyObject *message; PyObject *v; int i = errno; -#ifdef PLAN9 - char errbuf[ERRMAX]; -#else #ifndef MS_WINDOWS char *s; #else WCHAR *s_buf = NULL; #endif /* Unix/Windows */ -#endif /* PLAN 9*/ #ifdef EINTR if (i == EINTR && PyErr_CheckSignals()) return NULL; #endif -#ifdef PLAN9 - rerrstr(errbuf, sizeof errbuf); - message = PyUnicode_DecodeUTF8(errbuf, strlen(errbuf), "ignore"); -#else #ifndef MS_WINDOWS if (i == 0) s = "Error"; /* Sometimes errno didn't get set */ @@ -425,7 +417,6 @@ PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject) } } #endif /* Unix/Windows */ -#endif /* PLAN 9*/ if (message == NULL) { -- cgit v1.2.1 From 7fc1caed37e14732a95513b5bc081dd5dcab65da Mon Sep 17 00:00:00 2001 From: "Andrew M. Kuchling" Date: Mon, 22 Feb 2010 23:26:10 +0000 Subject: #4532: fixes to make 3.x compile on QNX 6.3.2 (reported by Matt Kraai) --- Python/pythonrun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 3764740e81..b99a541d54 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -180,7 +180,7 @@ Py_InitializeEx(int install_sigs) return; initialized = 1; -#ifdef HAVE_SETLOCALE +#if defined(HAVE_LANGINFO_H) && defined(HAVE_SETLOCALE) /* Set up the LC_CTYPE locale, so we can obtain the locale's charset without having to switch locales. */ -- cgit v1.2.1 From a1f698754bc05deaea56dba1e7d61b9f476862b0 Mon Sep 17 00:00:00 2001 From: Amaury Forgeot d'Arc Date: Wed, 24 Feb 2010 00:10:48 +0000 Subject: Merged revisions 78393 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ........ r78393 | amaury.forgeotdarc | 2010-02-24 00:19:39 +0100 (mer., 24 févr. 2010) | 2 lines #4852: Remove dead code in every thread implementation, unused for many years. ........ --- Python/thread_cthread.h | 50 ++------------------ Python/thread_foobar.h | 44 +---------------- Python/thread_lwp.h | 40 +--------------- Python/thread_nt.h | 10 ---- Python/thread_os2.h | 46 ++---------------- Python/thread_pth.h | 39 +--------------- Python/thread_pthread.h | 46 ++---------------- Python/thread_sgi.h | 122 ++---------------------------------------------- Python/thread_solaris.h | 50 ++------------------ Python/thread_wince.h | 41 ++-------------- 10 files changed, 24 insertions(+), 464 deletions(-) (limited to 'Python') diff --git a/Python/thread_cthread.h b/Python/thread_cthread.h index ca776c6363..71634122c0 100644 --- a/Python/thread_cthread.h +++ b/Python/thread_cthread.h @@ -50,58 +50,14 @@ PyThread_get_thread_ident(void) 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)); + dprintf(("PyThread_exit_thread called\n")); 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); + exit(0); + cthread_exit(0); } -#endif /* NO_EXIT_PROG */ /* * Lock support. diff --git a/Python/thread_foobar.h b/Python/thread_foobar.h index 67491a167d..1b993d1e79 100644 --- a/Python/thread_foobar.h +++ b/Python/thread_foobar.h @@ -29,53 +29,13 @@ PyThread_get_thread_ident(void) 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)); + dprintf(("PyThread_exit_thread called\n")); 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); + exit(0); } -#endif /* NO_EXIT_PROG */ /* * Lock support. diff --git a/Python/thread_lwp.h b/Python/thread_lwp.h index e93d65aa30..93d8295556 100644 --- a/Python/thread_lwp.h +++ b/Python/thread_lwp.h @@ -47,50 +47,14 @@ long PyThread_get_thread_ident(void) return tid.thread_id; } -static void do_PyThread_exit_thread(int no_cleanup) +void PyThread_exit_thread(void) { dprintf(("PyThread_exit_thread called\n")); if (!initialized) - if (no_cleanup) - _exit(0); - else - exit(0); + 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. */ diff --git a/Python/thread_nt.h b/Python/thread_nt.h index 633fe4018f..0c5d1929c3 100644 --- a/Python/thread_nt.h +++ b/Python/thread_nt.h @@ -203,16 +203,6 @@ PyThread_exit_thread(void) #endif } -#ifndef NO_EXIT_PROG -void -PyThread_exit_prog(int status) -{ - dprintf(("PyThread_exit_prog(%d) called\n", status)); - if (!initialized) - exit(status); -} -#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 diff --git a/Python/thread_os2.h b/Python/thread_os2.h index 12eeed51c4..eee8de6337 100644 --- a/Python/thread_os2.h +++ b/Python/thread_os2.h @@ -68,56 +68,16 @@ PyThread_get_thread_ident(void) #endif } -static void -do_PyThread_exit_thread(int no_cleanup) +void +PyThread_exit_thread(void) { dprintf(("%ld: PyThread_exit_thread called\n", PyThread_get_thread_ident())); if (!initialized) - if (no_cleanup) - _exit(0); - else - exit(0); + 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 diff --git a/Python/thread_pth.h b/Python/thread_pth.h index 8c7dbe9257..f11e4848d9 100644 --- a/Python/thread_pth.h +++ b/Python/thread_pth.h @@ -74,49 +74,14 @@ long PyThread_get_thread_ident(void) return (long) *(long *) &threadid; } -static void do_PyThread_exit_thread(int no_cleanup) +void PyThread_exit_thread(void) { dprintf(("PyThread_exit_thread called\n")); if (!initialized) { - if (no_cleanup) - _exit(0); - else - exit(0); + 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. */ diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index 60d2fb216e..4305a198ba 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -225,55 +225,15 @@ PyThread_get_thread_ident(void) #endif } -static void -do_PyThread_exit_thread(int no_cleanup) +void +PyThread_exit_thread(void) { dprintf(("PyThread_exit_thread called\n")); if (!initialized) { - if (no_cleanup) - _exit(0); - else - exit(0); + 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 /* diff --git a/Python/thread_sgi.h b/Python/thread_sgi.h index 234665848b..4f4b210a28 100644 --- a/Python/thread_sgi.h +++ b/Python/thread_sgi.h @@ -17,9 +17,6 @@ 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 { @@ -27,53 +24,11 @@ static struct pidlist { 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 */ @@ -93,16 +48,6 @@ static void PyThread__init_thread(void) 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 */ @@ -227,46 +172,24 @@ long PyThread_get_thread_ident(void) return getpid(); } -static void do_PyThread_exit_thread(int no_cleanup) +void PyThread_exit_thread(void) { dprintf(("PyThread_exit_thread called\n")); if (!initialized) - if (no_cleanup) - _exit(0); - else - exit(0); + 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); + exit(exit_status); } if (usunsetlock(count_lock) < 0) perror("usunsetlock (count_lock)"); @@ -283,50 +206,11 @@ static void do_PyThread_exit_thread(int no_cleanup) 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. */ diff --git a/Python/thread_solaris.h b/Python/thread_solaris.h index ff3e6f3591..59ca0025a7 100644 --- a/Python/thread_solaris.h +++ b/Python/thread_solaris.h @@ -64,58 +64,14 @@ PyThread_get_thread_ident(void) 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)); + dprintf(("PyThread_exit_thread called\n")); 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); + exit(0); + thr_exit(0); } -#endif /* NO_EXIT_PROG */ /* * Lock support. diff --git a/Python/thread_wince.h b/Python/thread_wince.h index e16f5d1415..f8cf2cf937 100644 --- a/Python/thread_wince.h +++ b/Python/thread_wince.h @@ -53,48 +53,13 @@ long PyThread_get_thread_ident(void) 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)); + dprintf(("%ld: PyThread_exit_thread called\n", PyThread_get_thread_ident())); 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); + exit(0); + _endthread(); } -#endif /* NO_EXIT_PROG */ /* * Lock support. It has to be implemented using Mutexes, as -- cgit v1.2.1 From ffce33e4b5696d700c61a450b926545e7601e803 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 27 Feb 2010 17:40:01 +0000 Subject: only accept AttributeError as indicating no __prepare__ attribute on a metaclass, allowing lookup errors to propogate --- Python/bltinmodule.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 7fe164f5de..5c7138ec60 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -108,8 +108,16 @@ builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) } prep = PyObject_GetAttrString(meta, "__prepare__"); if (prep == NULL) { - PyErr_Clear(); - ns = PyDict_New(); + if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + ns = PyDict_New(); + } + else { + Py_DECREF(meta); + Py_XDECREF(mkw); + Py_DECREF(bases); + return NULL; + } } else { PyObject *pargs = PyTuple_Pack(2, name, bases); -- cgit v1.2.1 From d59642d984d0ffa149f3759832bab6e18325f3c5 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 27 Feb 2010 17:41:13 +0000 Subject: check PyDict_New() for error --- Python/bltinmodule.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 5c7138ec60..a928fc45cf 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -131,12 +131,12 @@ builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) ns = PyEval_CallObjectWithKeywords(prep, pargs, mkw); Py_DECREF(pargs); Py_DECREF(prep); - if (ns == NULL) { - Py_DECREF(meta); - Py_XDECREF(mkw); - Py_DECREF(bases); - return NULL; - } + } + if (ns == NULL) { + Py_DECREF(meta); + Py_XDECREF(mkw); + Py_DECREF(bases); + return NULL; } cell = PyObject_CallFunctionObjArgs(func, ns, NULL); if (cell != NULL) { -- cgit v1.2.1 From d521456a459cf82f6ae77b07deee97fc9899cec8 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Mon, 1 Mar 2010 02:09:17 +0000 Subject: Strip out trailing whitespace. --- Python/import.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 8321b14929..2640cdbf57 100644 --- a/Python/import.c +++ b/Python/import.c @@ -19,7 +19,7 @@ #include #endif #ifdef __cplusplus -extern "C" { +extern "C" { #endif #ifdef MS_WINDOWS @@ -530,7 +530,7 @@ PyImport_GetMagicNumber(void) 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(). + _PyImport_FindExtension(). Modules which do support multiple multiple initialization set their m_size field to a non-negative number (indicating the size @@ -566,7 +566,7 @@ _PyImport_FixupExtension(PyObject *mod, char *name, char *filename) } if (def->m_size == -1) { if (def->m_base.m_copy) { - /* Somebody already imported the module, + /* Somebody already imported the module, likely under a different name. XXX this should really not happen. */ Py_DECREF(def->m_base.m_copy); @@ -624,7 +624,7 @@ _PyImport_FindExtension(char *name, char *filename) PySys_WriteStderr("import %s # previously loaded (%s)\n", name, filename); return mod; - + } @@ -862,7 +862,7 @@ parse_source_module(const char *pathname, FILE *fp) flags.cf_flags = 0; mod = PyParser_ASTFromFile(fp, pathname, NULL, - Py_file_input, 0, 0, &flags, + Py_file_input, 0, 0, &flags, NULL, arena); if (mod) { co = PyAST_Compile(mod, pathname, NULL, arena); @@ -920,7 +920,7 @@ write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat) mode_t mode = srcstat->st_mode & ~S_IEXEC; #else mode_t mode = srcstat->st_mode & ~S_IXUSR & ~S_IXGRP & ~S_IXOTH; -#endif +#endif fp = open_exclusive(cpathname, mode); if (fp == NULL) { @@ -1010,7 +1010,7 @@ load_source_module(char *name, char *pathname, FILE *fp) char *cpathname; PyCodeObject *co; PyObject *m; - + if (fstat(fileno(fp), &st) != 0) { PyErr_Format(PyExc_RuntimeError, "unable to get file status from '%s'", @@ -1383,7 +1383,7 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, if (!v) return NULL; if (PyUnicode_Check(v)) { - v = PyUnicode_AsEncodedString(v, + v = PyUnicode_AsEncodedString(v, Py_FileSystemDefaultEncoding, NULL); if (v == NULL) return NULL; @@ -1456,7 +1456,7 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, else { char warnstr[MAXPATHLEN+80]; sprintf(warnstr, "Not importing directory " - "'%.*s': missing __init__.py", + "'%.*s': missing __init__.py", MAXPATHLEN, buf); if (PyErr_WarnEx(PyExc_ImportWarning, warnstr, 1)) { @@ -2270,7 +2270,7 @@ get_parent(PyObject *globals, char *buf, Py_ssize_t *p_buflen, int level) modname = PyDict_GetItem(globals, namestr); if (modname == NULL || !PyUnicode_Check(modname)) return Py_None; - + modpath = PyDict_GetItem(globals, pathstr); if (modpath != NULL) { /* __path__ is set, so modname is already the package name */ @@ -2643,7 +2643,7 @@ PyImport_ReloadModule(PyObject *m) struct filedescr *fdp; FILE *fp = NULL; PyObject *newm; - + if (modules_reloading == NULL) { Py_FatalError("PyImport_ReloadModule: " "no modules_reloading dictionary!"); @@ -3039,8 +3039,8 @@ imp_load_compiled(PyObject *self, PyObject *args) PyObject *m; FILE *fp; if (!PyArg_ParseTuple(args, "ses|O:load_compiled", - &name, - Py_FileSystemDefaultEncoding, &pathname, + &name, + Py_FileSystemDefaultEncoding, &pathname, &fob)) return NULL; fp = get_file(pathname, fob, "rb"); @@ -3065,8 +3065,8 @@ imp_load_dynamic(PyObject *self, PyObject *args) PyObject *m; FILE *fp = NULL; if (!PyArg_ParseTuple(args, "ses|O:load_dynamic", - &name, - Py_FileSystemDefaultEncoding, &pathname, + &name, + Py_FileSystemDefaultEncoding, &pathname, &fob)) return NULL; if (fob) { @@ -3094,7 +3094,7 @@ imp_load_source(PyObject *self, PyObject *args) PyObject *m; FILE *fp; if (!PyArg_ParseTuple(args, "ses|O:load_source", - &name, + &name, Py_FileSystemDefaultEncoding, &pathname, &fob)) return NULL; @@ -3122,7 +3122,7 @@ imp_load_module(PyObject *self, PyObject *args) FILE *fp; if (!PyArg_ParseTuple(args, "sOes(ssi):load_module", - &name, &fob, + &name, &fob, Py_FileSystemDefaultEncoding, &pathname, &suffix, &mode, &type)) return NULL; @@ -3146,7 +3146,7 @@ imp_load_module(PyObject *self, PyObject *args) PyMem_Free(pathname); return NULL; } - } + } ret = load_module(name, fp, pathname, type, NULL); PyMem_Free(pathname); if (fp) @@ -3160,7 +3160,7 @@ imp_load_package(PyObject *self, PyObject *args) char *name; char *pathname; PyObject * ret; - if (!PyArg_ParseTuple(args, "ses:load_package", + if (!PyArg_ParseTuple(args, "ses:load_package", &name, Py_FileSystemDefaultEncoding, &pathname)) return NULL; ret = load_package(name, pathname); -- cgit v1.2.1 From fe4b328bd3f24f58880299ab2058a0b0c1fd9149 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Mon, 1 Mar 2010 06:18:41 +0000 Subject: Merged revisions 78527,78550 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r78527 | gregory.p.smith | 2010-02-28 17:22:39 -0800 (Sun, 28 Feb 2010) | 4 lines Issue #7242: On Solaris 9 and earlier calling os.fork() from within a thread could raise an incorrect RuntimeError about not holding the import lock. The import lock is now reinitialized after fork. ........ r78550 | gregory.p.smith | 2010-02-28 22:01:02 -0800 (Sun, 28 Feb 2010) | 2 lines Fix test to be skipped on windows. ........ --- Python/import.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 2640cdbf57..4785bca881 100644 --- a/Python/import.c +++ b/Python/import.c @@ -295,14 +295,18 @@ _PyImport_ReleaseLock(void) return 1; } -/* This function used to be called from PyOS_AfterFork to ensure that newly - created child processes do not share locks with the parent, but for some - reason only on AIX systems. Instead of re-initializing the lock, we now - acquire the import lock around fork() calls. */ +/* This function is called from PyOS_AfterFork to ensure that newly + created child processes do not share locks with the parent. + We now acquire the import lock around fork() calls but on some platforms + (Solaris 9 and earlier? see isue7242) that still left us with problems. */ void _PyImport_ReInitLock(void) { + if (import_lock != NULL) + import_lock = PyThread_allocate_lock(); + import_lock_thread = -1; + import_lock_level = 0; } #endif -- cgit v1.2.1 From feada8b7cac86cc6fc90f0509d1ab7fa04e60641 Mon Sep 17 00:00:00 2001 From: Florent Xicluna Date: Wed, 3 Mar 2010 11:54:54 +0000 Subject: Merged revisions 78620 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r78620 | florent.xicluna | 2010-03-03 12:49:53 +0100 (mer, 03 mar 2010) | 2 lines Revert a nonexistent docstring typo, r42805. ........ --- Python/sysmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index f1cbbba48b..490577d3e2 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -107,7 +107,7 @@ sys_displayhook(PyObject *self, PyObject *o) PyDoc_STRVAR(displayhook_doc, "displayhook(object) -> None\n" "\n" -"Print an object to sys.stdout and also save it in builtins.\n" +"Print an object to sys.stdout and also save it in builtins._\n" ); static PyObject * -- cgit v1.2.1 From c8b08e48e23aead070d8311341f5343638e0848b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 3 Mar 2010 23:28:07 +0000 Subject: Merged revisions 78638 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r78638 | victor.stinner | 2010-03-04 00:20:25 +0100 (jeu., 04 mars 2010) | 3 lines Issue #7544: Preallocate thread memory before creating the thread to avoid a fatal error in low memory condition. ........ --- Python/pystate.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'Python') diff --git a/Python/pystate.c b/Python/pystate.c index 78c501e4c5..eb2dfa6e3a 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -157,8 +157,8 @@ threadstate_getframe(PyThreadState *self) return self->frame; } -PyThreadState * -PyThreadState_New(PyInterpreterState *interp) +static PyThreadState * +new_threadstate(PyInterpreterState *interp, int init) { PyThreadState *tstate = (PyThreadState *)malloc(sizeof(PyThreadState)); @@ -198,9 +198,8 @@ PyThreadState_New(PyInterpreterState *interp) tstate->c_profileobj = NULL; tstate->c_traceobj = NULL; -#ifdef WITH_THREAD - _PyGILState_NoteThreadState(tstate); -#endif + if (init) + _PyThreadState_Init(tstate); HEAD_LOCK(); tstate->next = interp->tstate_head; @@ -211,6 +210,26 @@ PyThreadState_New(PyInterpreterState *interp) return tstate; } +PyThreadState * +PyThreadState_New(PyInterpreterState *interp) +{ + return new_threadstate(interp, 1); +} + +PyThreadState * +_PyThreadState_Prealloc(PyInterpreterState *interp) +{ + return new_threadstate(interp, 0); +} + +void +_PyThreadState_Init(PyThreadState *tstate) +{ +#ifdef WITH_THREAD + _PyGILState_NoteThreadState(tstate); +#endif +} + PyObject* PyState_FindModule(struct PyModuleDef* m) { -- cgit v1.2.1 From 551d9532a59ff7e9320b9fcc453c1cc39f6681e0 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 7 Mar 2010 17:10:51 +0000 Subject: prevent generator finalization from invalidating sys.exc_info() #7173 --- Python/ceval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 5d1fb285be..47c53cfa04 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1159,7 +1159,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) assert(stack_pointer != NULL); f->f_stacktop = NULL; /* remains NULL unless yield suspends frame */ - if (f->f_code->co_flags & CO_GENERATOR) { + if (co->co_flags & CO_GENERATOR && !throwflag) { if (f->f_exc_type != NULL && f->f_exc_type != Py_None) { /* We were in an except handler when we left, restore the exception state which was put aside -- cgit v1.2.1 From d1e45b1d11599db33a915fc9326285bfa896b2d7 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Thu, 11 Mar 2010 22:53:45 +0000 Subject: convert shebang lines: python -> python3 --- Python/makeopcodetargets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/makeopcodetargets.py b/Python/makeopcodetargets.py index a85ac52151..7180e9aa77 100755 --- a/Python/makeopcodetargets.py +++ b/Python/makeopcodetargets.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/env python3 """Generate C code for the jump table of the threaded code interpreter (for compilers supporting computed gotos or "labels-as-values", such as gcc). """ -- cgit v1.2.1 From ac71eae38f6433ec4a6064cb48d1a814d1b3eda9 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Thu, 11 Mar 2010 23:39:40 +0000 Subject: fix bootstrapping on machines with only 2.x installed --- Python/makeopcodetargets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/makeopcodetargets.py b/Python/makeopcodetargets.py index 7180e9aa77..a85ac52151 100755 --- a/Python/makeopcodetargets.py +++ b/Python/makeopcodetargets.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python3 +#! /usr/bin/env python """Generate C code for the jump table of the threaded code interpreter (for compilers supporting computed gotos or "labels-as-values", such as gcc). """ -- cgit v1.2.1 From 4211cfd22a40b91fc7e2d12e10835bd02f99ae39 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 12 Mar 2010 14:45:56 +0000 Subject: Merged revisions 78826 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r78826 | victor.stinner | 2010-03-10 23:30:19 +0100 (mer., 10 mars 2010) | 5 lines Issue #3137: Don't ignore errors at startup, especially a keyboard interrupt (SIGINT). If an error occurs while importing the site module, the error is printed and Python exits. Initialize the GIL before importing the site module. ........ --- Python/import.c | 2 -- Python/pythonrun.c | 25 +++++++++---------------- 2 files changed, 9 insertions(+), 18 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 4785bca881..8a948b98f8 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2774,8 +2774,6 @@ PyImport_Import(PyObject *module_name) } else { /* No globals -- use standard builtins, and fake globals */ - PyErr_Clear(); - builtins = PyImport_ImportModuleLevel("builtins", NULL, NULL, NULL, 0); if (builtins == NULL) diff --git a/Python/pythonrun.c b/Python/pythonrun.c index b99a541d54..cfa19b0708 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -296,13 +296,14 @@ Py_InitializeEx(int install_sigs) if (initstdio() < 0) Py_FatalError( "Py_Initialize: can't initialize sys standard streams"); - if (!Py_NoSiteFlag) - initsite(); /* Module site */ /* auto-thread-state API, if available */ #ifdef WITH_THREAD _PyGILState_Init(interp, tstate); #endif /* WITH_THREAD */ + + if (!Py_NoSiteFlag) + initsite(); /* Module site */ } void @@ -711,22 +712,12 @@ initmain(void) static void initsite(void) { - PyObject *m, *f; + PyObject *m; m = PyImport_ImportModule("site"); if (m == NULL) { - f = PySys_GetObject("stderr"); - if (f == NULL || f == Py_None) - return; - 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(); - } + PyErr_Print(); + Py_Finalize(); + exit(1); } else { Py_DECREF(m); @@ -1907,6 +1898,8 @@ err_input(perrdetail *err) char *msg = NULL; errtype = PyExc_SyntaxError; switch (err->error) { + case E_ERROR: + return; case E_SYNTAX: errtype = PyExc_IndentationError; if (err->expected == INDENT) -- cgit v1.2.1 From 1fe05e96ecf7cec6d9f5515c5784221d132081f1 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 12 Mar 2010 17:00:41 +0000 Subject: Issue #6697: use %U format instead of _PyUnicode_AsString(), because _PyUnicode_AsString() was not checked for error (NULL). The unicode string is no more truncated to 200 or 400 *bytes*. --- Python/ceval.c | 4 ++-- Python/import.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 47c53cfa04..4e9f77be8a 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3989,10 +3989,10 @@ update_keyword_args(PyObject *orig_kwdict, int nk, PyObject ***pp_stack, if (PyDict_GetItem(kwdict, key) != NULL) { PyErr_Format(PyExc_TypeError, "%.200s%s got multiple values " - "for keyword argument '%.200s'", + "for keyword argument '%U'", PyEval_GetFuncName(func), PyEval_GetFuncDesc(func), - _PyUnicode_AsString(key)); + key); Py_DECREF(key); Py_DECREF(value); Py_DECREF(kwdict); diff --git a/Python/import.c b/Python/import.c index 8a948b98f8..036d17e1be 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2691,8 +2691,8 @@ PyImport_ReloadModule(PyObject *m) parent = PyDict_GetItem(modules, parentname); if (parent == NULL) { PyErr_Format(PyExc_ImportError, - "reload(): parent %.200s not in sys.modules", - _PyUnicode_AsString(parentname)); + "reload(): parent %U not in sys.modules", + parentname); Py_DECREF(parentname); imp_modules_reloading_clear(); return NULL; -- cgit v1.2.1 From e9b66bcb7515e9541bd7e04e7107a763666edab5 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sat, 13 Mar 2010 13:23:05 +0000 Subject: Issue #8014: Fix incorrect error checks in structmember.c, and re-enable previously failing test_structmember.py tests. --- Python/structmember.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/structmember.c b/Python/structmember.c index 8edc354106..88ea6f8df7 100644 --- a/Python/structmember.c +++ b/Python/structmember.c @@ -187,12 +187,13 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v) } case T_UINT:{ unsigned long ulong_val = PyLong_AsUnsignedLong(v); - if ((ulong_val == (unsigned int)-1) && PyErr_Occurred()) { + if ((ulong_val == (unsigned long)-1) && PyErr_Occurred()) { /* XXX: For compatibility, accept negative int values as well. */ PyErr_Clear(); ulong_val = PyLong_AsLong(v); - if ((ulong_val == (unsigned int)-1) && PyErr_Occurred()) + if ((ulong_val == (unsigned long)-1) && + PyErr_Occurred()) return -1; *(unsigned int *)addr = (unsigned int)ulong_val; WARN("Writing negative value into unsigned field"); @@ -216,7 +217,7 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v) as well. */ PyErr_Clear(); *(unsigned long*)addr = PyLong_AsLong(v); - if ((*(unsigned long*)addr == (unsigned int)-1) + if ((*(unsigned long*)addr == (unsigned long)-1) && PyErr_Occurred()) return -1; WARN("Writing negative value into unsigned field"); -- cgit v1.2.1 From 227334cb2eacf4a9087140ef7726d6408b4798e5 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Sun, 14 Mar 2010 06:49:55 +0000 Subject: * Replaces the internals of the subprocess module from fork through exec on POSIX systems with a C extension module. This is required in order for the subprocess module to be made thread safe. The pure python implementation is retained so that it can continue to be used if for some reason the _posixsubprocess extension module is not available. The unittest executes tests on both code paths to guarantee compatibility. * Moves PyLong_FromPid and PyLong_AsPid from posixmodule.c into longobject.h. Code reviewed by jeffrey.yasskin at http://codereview.appspot.com/223077/show --- Python/pythonrun.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index cfa19b0708..2bdef981ad 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -2130,6 +2130,27 @@ initsigs(void) } +/* Restore signals that the interpreter has called SIG_IGN on to SIG_DFL. + * + * All of the code in this function must only use async-signal-safe functions, + * listed at `man 7 signal` or + * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html. + */ +void +_Py_RestoreSignals(void) +{ +#ifdef SIGPIPE + PyOS_setsig(SIGPIPE, SIG_DFL); +#endif +#ifdef SIGXFZ + PyOS_setsig(SIGXFZ, SIG_DFL); +#endif +#ifdef SIGXFSZ + PyOS_setsig(SIGXFSZ, SIG_DFL); +#endif +} + + /* * The file descriptor fd is considered ``interactive'' if either * a) isatty(fd) is TRUE, or @@ -2223,6 +2244,11 @@ PyOS_getsig(int sig) #endif } +/* + * All of the code in this function must only use async-signal-safe functions, + * listed at `man 7 signal` or + * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html. + */ PyOS_sighandler_t PyOS_setsig(int sig, PyOS_sighandler_t handler) { -- cgit v1.2.1 From 54c1aa548c9e58d197a9954e8ce8e39062441226 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 17 Mar 2010 20:56:58 +0000 Subject: Merged revisions 79034 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r79034 | benjamin.peterson | 2010-03-17 15:41:42 -0500 (Wed, 17 Mar 2010) | 1 line prevent lambda functions from having docstrings #8164 ........ --- Python/compile.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Python') diff --git a/Python/compile.c b/Python/compile.c index 2c58d449b5..62fa46c615 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1660,6 +1660,11 @@ compiler_lambda(struct compiler *c, expr_ty e) if (!compiler_enter_scope(c, name, (void *)e, e->lineno)) return 0; + /* Make None the first constant, so the lambda can't have a + docstring. */ + if (compiler_add_o(c, c->u->u_consts, Py_None) < 0) + return 0; + c->u->u_argcount = asdl_seq_LEN(args->args); c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs); VISIT_IN_SCOPE(c, expr, e->v.Lambda.body); -- cgit v1.2.1 From c6b4769c2bbc8eca3c03ef038da6267587adab5e Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 21 Mar 2010 21:00:50 +0000 Subject: Merged revisions 79205,79219,79228,79230,79232-79233,79235,79237 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r79205 | benjamin.peterson | 2010-03-21 12:34:54 -0500 (Sun, 21 Mar 2010) | 1 line rewrite a bit ........ r79219 | benjamin.peterson | 2010-03-21 14:24:08 -0500 (Sun, 21 Mar 2010) | 1 line flatten condition ........ r79228 | benjamin.peterson | 2010-03-21 14:35:39 -0500 (Sun, 21 Mar 2010) | 1 line remove pointless condition ........ r79230 | benjamin.peterson | 2010-03-21 14:39:52 -0500 (Sun, 21 Mar 2010) | 1 line co_varnames is certainly a tuple, so let's not waste time finding out ........ r79232 | benjamin.peterson | 2010-03-21 14:54:56 -0500 (Sun, 21 Mar 2010) | 1 line fix import ........ r79233 | benjamin.peterson | 2010-03-21 14:56:37 -0500 (Sun, 21 Mar 2010) | 1 line don't write duplicate tests ........ r79235 | benjamin.peterson | 2010-03-21 15:21:00 -0500 (Sun, 21 Mar 2010) | 4 lines improve error message from passing inadequate number of keyword arguments #6474 Note this removes the "non-keyword" or "keyword" phrases from these messages. ........ r79237 | benjamin.peterson | 2010-03-21 15:30:30 -0500 (Sun, 21 Mar 2010) | 1 line take into account keyword arguments when passing too many args ........ --- Python/ceval.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 4e9f77be8a..ae9ab47790 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3076,13 +3076,12 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, if (!(co->co_flags & CO_VARARGS)) { PyErr_Format(PyExc_TypeError, "%U() takes %s %d " - "%spositional argument%s (%d given)", + "argument%s (%d given)", co->co_name, defcount ? "at most" : "exactly", co->co_argcount, - kwcount ? "non-keyword " : "", co->co_argcount == 1 ? "" : "s", - argcount); + argcount + kwcount); goto fail; } n = co->co_argcount; @@ -3116,7 +3115,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, } /* Speed hack: do raw pointer compares. As names are normally interned this should almost always hit. */ - co_varnames = PySequence_Fast_ITEMS(co->co_varnames); + co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item; for (j = 0; j < co->co_argcount + co->co_kwonlyargcount; j++) { @@ -3148,10 +3147,10 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, keyword); goto fail; } - PyDict_SetItem(kwdict, keyword, value); - continue; } -kw_found: + PyDict_SetItem(kwdict, keyword, value); + continue; + kw_found: if (GETLOCAL(j) != NULL) { PyErr_Format(PyExc_TypeError, "%U() got multiple " @@ -3190,16 +3189,19 @@ kw_found: int m = co->co_argcount - defcount; for (i = argcount; i < m; i++) { if (GETLOCAL(i) == NULL) { + int j, given = 0; + for (j = 0; j < co->co_argcount; j++) + if (GETLOCAL(j)) + given++; PyErr_Format(PyExc_TypeError, "%U() takes %s %d " - "%spositional argument%s " + "argument%s " "(%d given)", co->co_name, ((co->co_flags & CO_VARARGS) || defcount) ? "at least" : "exactly", - m, kwcount ? "non-keyword " : "", - m == 1 ? "" : "s", i); + m, m == 1 ? "" : "s", given); goto fail; } } @@ -3216,14 +3218,12 @@ kw_found: } } } - else { - if (argcount > 0 || kwcount > 0) { - PyErr_Format(PyExc_TypeError, - "%U() takes no arguments (%d given)", - co->co_name, - argcount + kwcount); - goto fail; - } + else if (argcount > 0 || kwcount > 0) { + PyErr_Format(PyExc_TypeError, + "%U() takes no arguments (%d given)", + 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. */ -- cgit v1.2.1 From 4963f27d50f0bfaf33d7b0adf307c76c83a402ef Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 21 Mar 2010 21:08:54 +0000 Subject: cleanup a bit --- Python/ceval.c | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index ae9ab47790..9be0bd6fa6 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3041,6 +3041,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, register PyObject **fastlocals, **freevars; PyThreadState *tstate = PyThreadState_GET(); PyObject *x, *u; + int total_args = co->co_argcount + co->co_kwonlyargcount; if (globals == NULL) { PyErr_SetString(PyExc_SystemError, @@ -3057,9 +3058,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, fastlocals = f->f_localsplus; freevars = f->f_localsplus + co->co_nlocals; - if (co->co_argcount > 0 || - co->co_kwonlyargcount > 0 || - co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) { + if (total_args || co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) { int i; int n = argcount; PyObject *kwdict = NULL; @@ -3067,7 +3066,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, kwdict = PyDict_New(); if (kwdict == NULL) goto fail; - i = co->co_argcount + co->co_kwonlyargcount; + i = total_args; if (co->co_flags & CO_VARARGS) i++; SETLOCAL(i, kwdict); @@ -3095,7 +3094,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, u = PyTuple_New(argcount - n); if (u == NULL) goto fail; - SETLOCAL(co->co_argcount + co->co_kwonlyargcount, u); + SETLOCAL(total_args, u); for (i = n; i < argcount; i++) { x = args[i]; Py_INCREF(x); @@ -3116,17 +3115,13 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, /* Speed hack: do raw pointer compares. As names are normally interned this should almost always hit. */ co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item; - for (j = 0; - j < co->co_argcount + co->co_kwonlyargcount; - j++) { + for (j = 0; j < total_args; j++) { PyObject *nm = co_varnames[j]; if (nm == keyword) goto kw_found; } /* Slow fallback, just in case */ - for (j = 0; - j < co->co_argcount + co->co_kwonlyargcount; - j++) { + for (j = 0; j < total_args; j++) { PyObject *nm = co_varnames[j]; int cmp = PyObject_RichCompareBool( keyword, nm, Py_EQ); @@ -3138,15 +3133,13 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, /* Check errors from Compare */ if (PyErr_Occurred()) goto fail; - if (j >= co->co_argcount + co->co_kwonlyargcount) { - if (kwdict == NULL) { - PyErr_Format(PyExc_TypeError, - "%U() got an unexpected " - "keyword argument '%S'", - co->co_name, - keyword); - goto fail; - } + if (j >= total_args && kwdict == NULL) { + PyErr_Format(PyExc_TypeError, + "%U() got an unexpected " + "keyword argument '%S'", + co->co_name, + keyword); + goto fail; } PyDict_SetItem(kwdict, keyword, value); continue; @@ -3164,9 +3157,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, SETLOCAL(j, value); } if (co->co_kwonlyargcount > 0) { - for (i = co->co_argcount; - i < co->co_argcount + co->co_kwonlyargcount; - i++) { + for (i = co->co_argcount; i < total_args; i++) { PyObject *name, *def; if (GETLOCAL(i) != NULL) continue; @@ -3232,7 +3223,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, Py_UNICODE *cellname, *argname; PyObject *c; - nargs = co->co_argcount + co->co_kwonlyargcount; + nargs = total_args; if (co->co_flags & CO_VARARGS) nargs++; if (co->co_flags & CO_VARKEYWORDS) -- cgit v1.2.1 From 9b8e399aca3c1f9bbf05c84ed3c2bf926d15f68c Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 21 Mar 2010 21:12:03 +0000 Subject: Merged revisions 78028 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r78028 | benjamin.peterson | 2010-02-06 13:40:18 -0600 (Sat, 06 Feb 2010) | 1 line remove pointless error checking ........ --- Python/ceval.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 9be0bd6fa6..22c61550bf 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3130,9 +3130,6 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, else if (cmp < 0) goto fail; } - /* Check errors from Compare */ - if (PyErr_Occurred()) - goto fail; if (j >= total_args && kwdict == NULL) { PyErr_Format(PyExc_TypeError, "%U() got an unexpected " -- cgit v1.2.1 From 8095c719c74f3355af9e551f26f9475c77c22908 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 21 Mar 2010 21:16:24 +0000 Subject: count keyword only arguments as part of the total --- Python/ceval.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 22c61550bf..0bd785b57c 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3078,8 +3078,8 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, "argument%s (%d given)", co->co_name, defcount ? "at most" : "exactly", - co->co_argcount, - co->co_argcount == 1 ? "" : "s", + total_args, + total_args == 1 ? "" : "s", argcount + kwcount); goto fail; } -- cgit v1.2.1 From 32d30b04ab6ca4963988581ce5a84782aaa2cec3 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 21 Mar 2010 21:22:12 +0000 Subject: nest if for clarity --- Python/ceval.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 0bd785b57c..4e8557df9a 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3155,17 +3155,17 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, } if (co->co_kwonlyargcount > 0) { for (i = co->co_argcount; i < total_args; i++) { - PyObject *name, *def; + PyObject *name; if (GETLOCAL(i) != NULL) continue; name = PyTuple_GET_ITEM(co->co_varnames, i); - def = NULL; - if (kwdefs != NULL) - def = PyDict_GetItem(kwdefs, name); - if (def != NULL) { - Py_INCREF(def); - SETLOCAL(i, def); - continue; + if (kwdefs != NULL) { + PyObject *def = PyDict_GetItem(kwdefs, name); + if (def) { + Py_INCREF(def); + SETLOCAL(i, def); + continue; + } } PyErr_Format(PyExc_TypeError, "%U() needs keyword-only argument %S", -- cgit v1.2.1 From 4b21d8a77cec1113ab3cd3bd5ebd9ca96cefddc1 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 25 Mar 2010 00:30:28 +0000 Subject: Issue #8226: sys.setfilesystemencoding() raises a LookupError if the encoding is unknown. --- Python/bltinmodule.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index a928fc45cf..6b8600b0bd 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -29,7 +29,7 @@ int Py_HasFileSystemDefaultEncoding = 0; int _Py_SetFileSystemEncoding(PyObject *s) { - PyObject *defenc; + PyObject *defenc, *codec; if (!PyUnicode_Check(s)) { PyErr_BadInternalCall(); return -1; @@ -37,6 +37,10 @@ _Py_SetFileSystemEncoding(PyObject *s) defenc = _PyUnicode_AsDefaultEncodedString(s, NULL); if (!defenc) return -1; + codec = _PyCodec_Lookup(PyBytes_AsString(defenc)); + if (codec == NULL) + return -1; + Py_DECREF(codec); if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) /* A file system encoding was set at run-time */ free((char*)Py_FileSystemDefaultEncoding); -- cgit v1.2.1 From bc4b39dd71ac1884044e9c8da3d49f57afcc6400 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Thu, 25 Mar 2010 23:30:20 +0000 Subject: Merged revisions 79428 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r79428 | benjamin.peterson | 2010-03-25 18:27:16 -0500 (Thu, 25 Mar 2010) | 1 line make naming convention consistent ........ --- Python/import.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 036d17e1be..b046362818 100644 --- a/Python/import.c +++ b/Python/import.c @@ -661,7 +661,7 @@ PyImport_AddModule(const char *name) /* Remove name from sys.modules, if it's there. */ static void -_RemoveModule(const char *name) +remove_module(const char *name) { PyObject *modules = PyImport_GetModuleDict(); if (PyDict_GetItemString(modules, name) == NULL) @@ -735,7 +735,7 @@ PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname) return m; error: - _RemoveModule(name); + remove_module(name); return NULL; } -- cgit v1.2.1 From 5b4d0b722c2290cfa47f6568fd98a2be3da488fa Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Thu, 1 Apr 2010 16:53:15 +0000 Subject: Merged revisions 79555 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r79555 | antoine.pitrou | 2010-04-01 18:42:11 +0200 (jeu., 01 avril 2010) | 5 lines Issue #8276: PyEval_CallObject() is now only available in macro form. The function declaration, which was kept for backwards compatibility reasons, is now removed (the macro was introduced in 1997!). ........ --- Python/ceval.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 4e8557df9a..0c14eb08e1 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3695,18 +3695,7 @@ PyEval_MergeCompilerFlags(PyCompilerFlags *cf) /* 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) + The arg must be a tuple or NULL. The kw must be a dict or NULL. */ PyObject * PyEval_CallObjectWithKeywords(PyObject *func, PyObject *arg, PyObject *kw) -- cgit v1.2.1 From 9405a5b2ff79e52822ef35dd11912c857f5362c9 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 3 Apr 2010 01:40:24 +0000 Subject: Merged revisions 79642,79644 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r79642 | benjamin.peterson | 2010-04-02 20:08:34 -0500 (Fri, 02 Apr 2010) | 1 line split out large test function ........ r79644 | benjamin.peterson | 2010-04-02 20:28:57 -0500 (Fri, 02 Apr 2010) | 1 line give TypeError when trying to set T_STRING_INPLACE ........ --- Python/structmember.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/structmember.c b/Python/structmember.c index 88ea6f8df7..0ebd189795 100644 --- a/Python/structmember.c +++ b/Python/structmember.c @@ -106,7 +106,7 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v) addr += l->offset; - if ((l->flags & READONLY) || l->type == T_STRING) + if ((l->flags & READONLY)) { PyErr_SetString(PyExc_AttributeError, "readonly attribute"); return -1; @@ -266,6 +266,10 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v) *(char*)addr = string[0]; break; } + case T_STRING: + case T_STRING_INPLACE: + PyErr_SetString(PyExc_TypeError, "readonly attribute"); + return -1; #ifdef HAVE_LONG_LONG case T_LONGLONG:{ PY_LONG_LONG value; -- cgit v1.2.1 From 6814edddbb4ba9068a66934c81d483108af7b453 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 4 Apr 2010 23:09:06 +0000 Subject: Merged revisions 79763 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r79763 | benjamin.peterson | 2010-04-04 18:03:22 -0500 (Sun, 04 Apr 2010) | 1 line fix tabs ........ --- Python/structmember.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/structmember.c b/Python/structmember.c index 0ebd189795..9109f23540 100644 --- a/Python/structmember.c +++ b/Python/structmember.c @@ -267,7 +267,7 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v) break; } case T_STRING: - case T_STRING_INPLACE: + case T_STRING_INPLACE: PyErr_SetString(PyExc_TypeError, "readonly attribute"); return -1; #ifdef HAVE_LONG_LONG -- cgit v1.2.1 From fc37f3a644bf3c42ae60b1ce95381a9b2ba0a39d Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Tue, 6 Apr 2010 16:01:57 +0000 Subject: Merged revisions 79837 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r79837 | antoine.pitrou | 2010-04-06 17:38:25 +0200 (mar., 06 avril 2010) | 19 lines 14 years later, we still don't know what it's for. Spotted by the PyPy developers. Original commit is: branch: trunk user: guido date: Mon Aug 19 21:32:04 1996 +0200 files: Python/getargs.c description: [svn r6499] Support for keyword arguments (PyArg_ParseTupleAndKeywords) donated by Geoff Philbrick (slightly changed by me). Also a little change to make the file acceptable to K&R C compilers (HPUX, SunOS 4.x). ........ --- Python/getargs.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index 39be98c03f..17c5317d34 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1849,16 +1849,6 @@ skipitem(const char **p_format, va_list *p_va, int flags) (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); -- cgit v1.2.1 From 15801a1d52c25fa2a19d649ea2671080f138fca1 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Wed, 14 Apr 2010 15:44:10 +0000 Subject: Issue #7316: the acquire() method of lock objects in the :mod:`threading` module now takes an optional timeout argument in seconds. Timeout support relies on the system threading library, so as to avoid a semi-busy wait loop. --- Python/thread_nt.h | 33 ++++++++++++---- Python/thread_pthread.h | 101 ++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 107 insertions(+), 27 deletions(-) (limited to 'Python') diff --git a/Python/thread_nt.h b/Python/thread_nt.h index 0c5d1929c3..e2e4443d86 100644 --- a/Python/thread_nt.h +++ b/Python/thread_nt.h @@ -34,13 +34,13 @@ DeleteNonRecursiveMutex(PNRMUTEX mutex) } DWORD -EnterNonRecursiveMutex(PNRMUTEX mutex, BOOL wait) +EnterNonRecursiveMutex(PNRMUTEX mutex, DWORD milliseconds) { /* Assume that the thread waits successfully */ DWORD ret ; /* InterlockedIncrement(&mutex->owned) == 0 means that no thread currently owns the mutex */ - if (!wait) + if (milliseconds == 0) { if (InterlockedCompareExchange(&mutex->owned, 0, -1) != -1) return WAIT_TIMEOUT ; @@ -49,7 +49,7 @@ EnterNonRecursiveMutex(PNRMUTEX mutex, BOOL wait) else ret = InterlockedIncrement(&mutex->owned) ? /* Some thread owns the mutex, let's wait... */ - WaitForSingleObject(mutex->hevent, INFINITE) : WAIT_OBJECT_0 ; + WaitForSingleObject(mutex->hevent, milliseconds) : WAIT_OBJECT_0 ; mutex->thread_id = GetCurrentThreadId() ; /* We own it */ return ret ; @@ -239,18 +239,37 @@ PyThread_free_lock(PyThread_type_lock aLock) * if the lock has already been acquired by this thread! */ int -PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag) +PyThread_acquire_lock_timed(PyThread_type_lock aLock, PY_TIMEOUT_T microseconds) { int success ; + PY_TIMEOUT_T milliseconds; + + if (microseconds >= 0) { + milliseconds = microseconds / 1000; + if (microseconds % 1000 > 0) + ++milliseconds; + if ((DWORD) milliseconds != milliseconds) + Py_FatalError("Timeout too large for a DWORD, " + "please check PY_TIMEOUT_MAX"); + } + else + milliseconds = INFINITE; - dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n", PyThread_get_thread_ident(),aLock, waitflag)); + dprintf(("%ld: PyThread_acquire_lock_timed(%p, %lld) called\n", + PyThread_get_thread_ident(), aLock, microseconds)); - success = aLock && EnterNonRecursiveMutex((PNRMUTEX) aLock, (waitflag ? INFINITE : 0)) == WAIT_OBJECT_0 ; + success = aLock && EnterNonRecursiveMutex((PNRMUTEX) aLock, (DWORD) milliseconds) == WAIT_OBJECT_0 ; - dprintf(("%ld: PyThread_acquire_lock(%p, %d) -> %d\n", PyThread_get_thread_ident(),aLock, waitflag, success)); + dprintf(("%ld: PyThread_acquire_lock(%p, %lld) -> %d\n", + PyThread_get_thread_ident(), aLock, microseconds, success)); return success; } +int +PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag) +{ + return PyThread_acquire_lock_timed(aLock, waitflag ? -1 : 0); +} void PyThread_release_lock(PyThread_type_lock aLock) diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index 4305a198ba..6088c71fdb 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -83,6 +83,26 @@ #endif +/* We assume all modern POSIX systems have gettimeofday() */ +#ifdef GETTIMEOFDAY_NO_TZ +#define GETTIMEOFDAY(ptv) gettimeofday(ptv) +#else +#define GETTIMEOFDAY(ptv) gettimeofday(ptv, (struct timezone *)NULL) +#endif + +#define MICROSECONDS_TO_TIMESPEC(microseconds, ts) \ +do { \ + struct timeval tv; \ + GETTIMEOFDAY(&tv); \ + tv.tv_usec += microseconds % 1000000; \ + tv.tv_sec += microseconds / 1000000; \ + tv.tv_sec += tv.tv_usec / 1000000; \ + tv.tv_usec %= 1000000; \ + ts.tv_sec = tv.tv_sec; \ + ts.tv_nsec = tv.tv_usec * 1000; \ +} while(0) + + /* 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: @@ -295,34 +315,53 @@ fix_status(int status) return (status == -1) ? errno : status; } -int -PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) +int +PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds) { int success; sem_t *thelock = (sem_t *)lock; int status, error = 0; + struct timespec ts; - dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); + dprintf(("PyThread_acquire_lock_timed(%p, %lld) called\n", + lock, microseconds)); + if (microseconds > 0) + MICROSECONDS_TO_TIMESPEC(microseconds, ts); do { - if (waitflag) - status = fix_status(sem_wait(thelock)); - else + if (microseconds > 0) + status = fix_status(sem_timedwait(thelock, &ts)); + else if (microseconds == 0) status = fix_status(sem_trywait(thelock)); + else + status = fix_status(sem_wait(thelock)); } while (status == EINTR); /* Retry if interrupted by a signal */ - if (waitflag) { + if (microseconds > 0) { + if (status != ETIMEDOUT) + CHECK_STATUS("sem_timedwait"); + } + else if (microseconds == 0) { + if (status != EAGAIN) + CHECK_STATUS("sem_trywait"); + } + else { CHECK_STATUS("sem_wait"); - } else if (status != EAGAIN) { - CHECK_STATUS("sem_trywait"); } success = (status == 0) ? 1 : 0; - dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); + dprintf(("PyThread_acquire_lock_timed(%p, %lld) -> %d\n", + lock, microseconds, success)); return success; } +int +PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) +{ + return PyThread_acquire_lock_timed(lock, waitflag ? -1 : 0); +} + void PyThread_release_lock(PyThread_type_lock lock) { @@ -390,40 +429,62 @@ PyThread_free_lock(PyThread_type_lock lock) free((void *)thelock); } -int -PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) +int +PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds) { int success; pthread_lock *thelock = (pthread_lock *)lock; int status, error = 0; - dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); + dprintf(("PyThread_acquire_lock_timed(%p, %lld) called\n", + lock, microseconds)); status = pthread_mutex_lock( &thelock->mut ); CHECK_STATUS("pthread_mutex_lock[1]"); success = thelock->locked == 0; - if ( !success && waitflag ) { + if (!success && microseconds != 0) { + struct timespec ts; + if (microseconds > 0) + MICROSECONDS_TO_TIMESPEC(microseconds, ts); /* continue trying until we get the lock */ /* mut must be locked by me -- part of the condition * protocol */ - while ( thelock->locked ) { - status = pthread_cond_wait(&thelock->lock_released, - &thelock->mut); - CHECK_STATUS("pthread_cond_wait"); + while (thelock->locked) { + if (microseconds > 0) { + status = pthread_cond_timedwait( + &thelock->lock_released, + &thelock->mut, &ts); + if (status == ETIMEDOUT) + break; + CHECK_STATUS("pthread_cond_timed_wait"); + } + else { + status = pthread_cond_wait( + &thelock->lock_released, + &thelock->mut); + CHECK_STATUS("pthread_cond_wait"); + } } - success = 1; + success = (status == 0); } if (success) thelock->locked = 1; status = pthread_mutex_unlock( &thelock->mut ); CHECK_STATUS("pthread_mutex_unlock[1]"); if (error) success = 0; - dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); + dprintf(("PyThread_acquire_lock_timed(%p, %lld) -> %d\n", + lock, microseconds, success)); return success; } +int +PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) +{ + return PyThread_acquire_lock_timed(lock, waitflag ? -1 : 0); +} + void PyThread_release_lock(PyThread_type_lock lock) { -- cgit v1.2.1 From 4bd6574097d2cbd2e779196837124380e2dbe9bb Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Sat, 17 Apr 2010 00:19:56 +0000 Subject: PEP 3147 --- Python/import.c | 391 +++++++++++++++++++++++++++++++++++++++++++++++++---- Python/pythonrun.c | 2 + 2 files changed, 365 insertions(+), 28 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index b046362818..1cddcb0658 100644 --- a/Python/import.c +++ b/Python/import.c @@ -43,6 +43,15 @@ typedef unsigned short mode_t; The current working scheme is to increment the previous value by 10. + Starting with the adoption of PEP 3147 in Python 3.2, every bump in magic + number also includes a new "magic tag", i.e. a human readable string used + to represent the magic number in __pycache__ directories. When you change + the magic number, you must also set a new unique magic tag. Generally this + can be named after the Python major version of the magic number bump, but + it can really be anything, as long as it's different than anything else + that's come before. The tags are included in the following table, starting + with Python 3.2a0. + Known values: Python 1.5: 20121 Python 1.5.1: 20121 @@ -91,11 +100,18 @@ typedef unsigned short mode_t; Python 3.1a0: 3151 (optimize conditional branches: introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE) Python 3.2a0: 3160 (add SETUP_WITH) + tag: cpython-32 */ +/* If you change MAGIC, you must change TAG and you must insert the old value + into _PyMagicNumberTags below. +*/ #define MAGIC (3160 | ((long)'\r'<<16) | ((long)'\n'<<24)) -/* Magic word as global */ +#define TAG "cpython-32" +#define CACHEDIR "__pycache__" +/* Current magic word and string tag as globals. */ static long pyc_magic = MAGIC; +static const char *pyc_tag = TAG; /* See _PyImport_FixupExtension() below */ static PyObject *extensions = NULL; @@ -517,7 +533,7 @@ PyImport_Cleanup(void) } -/* Helper for pythonrun.c -- return magic number */ +/* Helper for pythonrun.c -- return magic number and tag. */ long PyImport_GetMagicNumber(void) @@ -526,6 +542,12 @@ PyImport_GetMagicNumber(void) } +const char * +PyImport_GetMagicTag(void) +{ + return pyc_tag; +} + /* 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 @@ -671,7 +693,10 @@ remove_module(const char *name) "sys.modules failed"); } -static PyObject * get_sourcefile(const char *file); +static PyObject * get_sourcefile(char *file); +static char *make_source_pathname(char *pathname, char *buf); +static char *make_compiled_pathname(char *pathname, char *buf, size_t buflen, + int debug); /* Execute a code object in a module and return the module object * WITH INCREMENTED REFERENCE COUNT. If an error occurs, name is @@ -679,15 +704,27 @@ static PyObject * get_sourcefile(const char *file); * in sys.modules. The caller may wish to restore the original * module object (if any) in this case; PyImport_ReloadModule is an * example. + * + * Note that PyImport_ExecCodeModuleWithPathnames() is the preferred, richer + * interface. The other two exist primarily for backward compatibility. */ PyObject * PyImport_ExecCodeModule(char *name, PyObject *co) { - return PyImport_ExecCodeModuleEx(name, co, (char *)NULL); + return PyImport_ExecCodeModuleWithPathnames( + name, co, (char *)NULL, (char *)NULL); } PyObject * PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname) +{ + return PyImport_ExecCodeModuleWithPathnames( + name, co, pathname, (char *)NULL); +} + +PyObject * +PyImport_ExecCodeModuleWithPathnames(char *name, PyObject *co, char *pathname, + char *cpathname) { PyObject *modules = PyImport_GetModuleDict(); PyObject *m, *d, *v; @@ -718,6 +755,20 @@ PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname) PyErr_Clear(); /* Not important enough to report */ Py_DECREF(v); + /* Remember the pyc path name as the __cached__ attribute. */ + if (cpathname == NULL) { + v = Py_None; + Py_INCREF(v); + } + else if ((v = PyUnicode_FromString(cpathname)) == NULL) { + PyErr_Clear(); /* Not important enough to report */ + v = Py_None; + Py_INCREF(v); + } + if (PyDict_SetItemString(d, "__cached__", v) != 0) + PyErr_Clear(); /* Not important enough to report */ + Py_DECREF(v); + v = PyEval_EvalCode((PyCodeObject *)co, d, d); if (v == NULL) goto error; @@ -740,32 +791,189 @@ PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname) } +/* Like strrchr(string, '/') but searches for the rightmost of either SEP + or ALTSEP, if the latter is defined. +*/ +static char * +rightmost_sep(char *s) +{ + char *found, c; + for (found = NULL; (c = *s); s++) { + if (c == SEP +#ifdef ALTSEP + || c == ALTSEP +#endif + ) + { + found = s; + } + } + return found; +} + + /* Given a pathname for a Python source file, fill a buffer with the pathname for the corresponding compiled file. Return the pathname for the compiled file, or NULL if there's no space in the buffer. Doesn't set an exception. */ static char * -make_compiled_pathname(char *pathname, char *buf, size_t buflen) +make_compiled_pathname(char *pathname, char *buf, size_t buflen, int debug) { + /* foo.py -> __pycache__/foo..pyc */ size_t len = strlen(pathname); - if (len+2 > buflen) + size_t i, save; + char *pos; + int sep = SEP; + + /* Sanity check that the buffer has roughly enough space to hold what + will eventually be the full path to the compiled file. The 5 extra + bytes include the slash afer __pycache__, the two extra dots, the + extra trailing character ('c' or 'o') and null. This isn't exact + because the contents of the buffer can affect how many actual + characters of the string get into the buffer. We'll do a final + sanity check before writing the extension to ensure we do not + overflow the buffer. + */ + if (len + strlen(CACHEDIR) + strlen(pyc_tag) + 5 > buflen) return NULL; -#ifdef MS_WINDOWS - /* Treat .pyw as if it were .py. The case of ".pyw" must match - that used in _PyImport_StandardFiletab. */ - if (len >= 4 && strcmp(&pathname[len-4], ".pyw") == 0) - --len; /* pretend 'w' isn't there */ + /* Find the last path separator and copy everything from the start of + the source string up to and including the separator. + */ + if ((pos = rightmost_sep(pathname)) == NULL) { + i = 0; + } + else { + sep = *pos; + i = pos - pathname + 1; + strncpy(buf, pathname, i); + } + + save = i; + buf[i++] = '\0'; + /* Add __pycache__/ */ + strcat(buf, CACHEDIR); + i += strlen(CACHEDIR) - 1; + buf[i++] = sep; + buf[i++] = '\0'; + /* Add the base filename, but remove the .py or .pyw extension, since + the tag name must go before the extension. + */ + strcat(buf, pathname + save); + if ((pos = strrchr(buf, '.')) != NULL) + *++pos = '\0'; + strcat(buf, pyc_tag); + /* The length test above assumes that we're only adding one character + to the end of what would normally be the extension. What if there + is no extension, or the string ends in '.' or '.p', and otherwise + fills the buffer? By appending 4 more characters onto the string + here, we could overrun the buffer. + + As a simple example, let's say buflen=32 and the input string is + 'xxx.py'. strlen() would be 6 and the test above would yield: + + (6 + 11 + 10 + 5 == 32) > 32 + + which is false and so the name mangling would continue. This would + be fine because we'd end up with this string in buf: + + __pycache__/xxx.cpython-32.pyc\0 + + strlen(of that) == 30 + the nul fits inside a 32 character buffer. + We can even handle an input string of say 'xxxxx' above because + that's (5 + 11 + 10 + 5 == 31) > 32 which is also false. Name + mangling that yields: + + __pycache__/xxxxxcpython-32.pyc\0 + + which is 32 characters including the nul, and thus fits in the + buffer. However, an input string of 'xxxxxx' would yield a result + string of: + + __pycache__/xxxxxxcpython-32.pyc\0 + + which is 33 characters long (including the nul), thus overflowing + the buffer, even though the first test would fail, i.e.: the input + string is also 6 characters long, so 32 > 32 is false. + + The reason the first test fails but we still overflow the buffer is + that the test above only expects to add one extra character to be + added to the extension, and here we're adding three (pyc). We + don't add the first dot, so that reclaims one of expected + positions, leaving us overflowing by 1 byte (3 extra - 1 reclaimed + dot - 1 expected extra == 1 overflowed). + + The best we can do is ensure that we still have enough room in the + target buffer before we write the extension. Because it's always + only the extension that can cause the overflow, and never the other + path bytes we've written, it's sufficient to just do one more test + here. Still, the assertion that follows can't hurt. + */ +#if 0 + printf("strlen(buf): %d; buflen: %d\n", (int)strlen(buf), (int)buflen); #endif - memcpy(buf, pathname, len); - buf[len] = Py_OptimizeFlag ? 'o' : 'c'; - buf[len+1] = '\0'; - + if (strlen(buf) + 5 > buflen) + return NULL; + strcat(buf, debug ? ".pyc" : ".pyo"); + assert(strlen(buf) < buflen); return buf; } +/* Given a pathname to a Python byte compiled file, return the path to the + source file, if the path matches the PEP 3147 format. This does not check + for any file existence, however, if the pyc file name does not match PEP + 3147 style, NULL is returned. buf must be at least as big as pathname; + the resulting path will always be shorter. */ + +static char * +make_source_pathname(char *pathname, char *buf) +{ + /* __pycache__/foo..pyc -> foo.py */ + size_t i, j; + char *left, *right, *dot0, *dot1, sep; + + /* Look back two slashes from the end. In between these two slashes + must be the string __pycache__ or this is not a PEP 3147 style + path. It's possible for there to be only one slash. + */ + if ((right = rightmost_sep(pathname)) == NULL) + return NULL; + sep = *right; + *right = '\0'; + left = rightmost_sep(pathname); + *right = sep; + if (left == NULL) + left = pathname; + else + left++; + if (right-left != strlen(CACHEDIR) || + strncmp(left, CACHEDIR, right-left) != 0) + return NULL; + + /* Now verify that the path component to the right of the last slash + has two dots in it. + */ + if ((dot0 = strchr(right + 1, '.')) == NULL) + return NULL; + if ((dot1 = strchr(dot0 + 1, '.')) == NULL) + return NULL; + /* Too many dots? */ + if (strchr(dot1 + 1, '.') != NULL) + return NULL; + + /* This is a PEP 3147 path. Start by copying everything from the + start of pathname up to and including the leftmost slash. Then + copy the file's basename, removing the magic tag and adding a .py + suffix. + */ + strncpy(buf, pathname, (i=left-pathname)); + strncpy(buf+i, right+1, (j=dot0-right)); + strcpy(buf+i+j, "py"); + return buf; +} + /* Given a pathname for a Python source file, its time of last modification, and a pathname for a compiled file, check whether the compiled file represents the same version of the source. If so, @@ -846,7 +1054,8 @@ load_compiled_module(char *name, char *cpathname, FILE *fp) if (Py_VerboseFlag) PySys_WriteStderr("import %s # precompiled from %s\n", name, cpathname); - m = PyImport_ExecCodeModuleEx(name, (PyObject *)co, cpathname); + m = PyImport_ExecCodeModuleWithPathnames( + name, (PyObject *)co, cpathname, cpathname); Py_DECREF(co); return m; @@ -919,12 +1128,41 @@ static void write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat) { FILE *fp; + char *dirpath; time_t mtime = srcstat->st_mtime; #ifdef MS_WINDOWS /* since Windows uses different permissions */ mode_t mode = srcstat->st_mode & ~S_IEXEC; + mode_t dirmode = srcstat->st_mode | S_IEXEC; /* XXX Is this correct + for Windows? + 2010-04-07 BAW */ #else mode_t mode = srcstat->st_mode & ~S_IXUSR & ~S_IXGRP & ~S_IXOTH; + mode_t dirmode = (srcstat->st_mode | + S_IXUSR | S_IXGRP | S_IXOTH | + S_IWUSR | S_IWGRP | S_IWOTH); #endif + int saved; + + /* Ensure that the __pycache__ directory exists. */ + dirpath = rightmost_sep(cpathname); + if (dirpath == NULL) { + if (Py_VerboseFlag) + PySys_WriteStderr( + "# no %s path found %s\n", + CACHEDIR, cpathname); + return; + } + saved = *dirpath; + *dirpath = '\0'; + /* XXX call os.mkdir() or maybe CreateDirectoryA() on Windows? */ + if (mkdir(cpathname, dirmode) < 0 && errno != EEXIST) { + *dirpath = saved; + if (Py_VerboseFlag) + PySys_WriteStderr( + "# cannot create cache dir %s\n", cpathname); + return; + } + *dirpath = saved; fp = open_exclusive(cpathname, mode); if (fp == NULL) { @@ -1032,8 +1270,8 @@ load_source_module(char *name, char *pathname, FILE *fp) return NULL; } #endif - cpathname = make_compiled_pathname(pathname, buf, - (size_t)MAXPATHLEN + 1); + cpathname = make_compiled_pathname( + pathname, buf, (size_t)MAXPATHLEN + 1, !Py_OptimizeFlag); if (cpathname != NULL && (fpc = check_compiled_module(pathname, st.st_mtime, cpathname))) { co = read_compiled_module(cpathname, fpc); @@ -1060,7 +1298,8 @@ load_source_module(char *name, char *pathname, FILE *fp) write_compiled_module(co, cpathname, &st); } } - m = PyImport_ExecCodeModuleEx(name, (PyObject *)co, pathname); + m = PyImport_ExecCodeModuleWithPathnames( + name, (PyObject *)co, pathname, cpathname); Py_DECREF(co); return m; @@ -1070,7 +1309,7 @@ load_source_module(char *name, char *pathname, FILE *fp) * Returns the path to the py file if available, else the given path */ static PyObject * -get_sourcefile(const char *file) +get_sourcefile(char *file) { char py[MAXPATHLEN + 1]; Py_ssize_t len; @@ -1087,8 +1326,15 @@ get_sourcefile(const char *file) return PyUnicode_DecodeFSDefault(file); } - strncpy(py, file, len-1); - py[len-1] = '\0'; + /* Start by trying to turn PEP 3147 path into source path. If that + * fails, just chop off the trailing character, i.e. legacy pyc path + * to py. + */ + if (make_source_pathname(file, py) == NULL) { + strncpy(py, file, len-1); + py[len-1] = '\0'; + } + if (stat(py, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) { u = PyUnicode_DecodeFSDefault(py); @@ -2813,16 +3059,28 @@ PyImport_Import(PyObject *module_name) */ static PyObject * -imp_get_magic(PyObject *self, PyObject *noargs) +imp_make_magic(long magic) { 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); + buf[0] = (char) ((magic >> 0) & 0xff); + buf[1] = (char) ((magic >> 8) & 0xff); + buf[2] = (char) ((magic >> 16) & 0xff); + buf[3] = (char) ((magic >> 24) & 0xff); return PyBytes_FromStringAndSize(buf, 4); +}; + +static PyObject * +imp_get_magic(PyObject *self, PyObject *noargs) +{ + return imp_make_magic(pyc_magic); +} + +static PyObject * +imp_get_tag(PyObject *self, PyObject *noargs) +{ + return PyUnicode_FromString(pyc_tag); } static PyObject * @@ -3190,6 +3448,75 @@ PyDoc_STRVAR(doc_reload, \n\ Reload the module. The module must have been successfully imported before."); +static PyObject * +imp_cache_from_source(PyObject *self, PyObject *args, PyObject *kws) +{ + static char *kwlist[] = {"path", "debug_override", NULL}; + + char buf[MAXPATHLEN+1]; + char *pathname, *cpathname; + PyObject *debug_override = Py_None; + int debug = !Py_OptimizeFlag; + + if (!PyArg_ParseTupleAndKeywords( + args, kws, "es|O", kwlist, + Py_FileSystemDefaultEncoding, &pathname, &debug_override)) + return NULL; + + if (debug_override != Py_None) + if ((debug = PyObject_IsTrue(debug_override)) < 0) + return NULL; + + cpathname = make_compiled_pathname(pathname, buf, MAXPATHLEN+1, debug); + PyMem_Free(pathname); + + if (cpathname == NULL) { + PyErr_Format(PyExc_SystemError, "path buffer too short"); + return NULL; + } + return PyUnicode_FromString(buf); +} + +PyDoc_STRVAR(doc_cache_from_source, +"Given the path to a .py file, return the path to its .pyc/.pyo file.\n\ +\n\ +The .py file does not need to exist; this simply returns the path to the\n\ +.pyc/.pyo file calculated as if the .py file were imported. The extension\n\ +will be .pyc unless __debug__ is not defined, then it will be .pyo.\n\ +\n\ +If debug_override is not None, then it must be a boolean and is taken as\n\ +the value of __debug__ instead."); + +static PyObject * +imp_source_from_cache(PyObject *self, PyObject *args, PyObject *kws) +{ + static char *kwlist[] = {"path", NULL}; + + char *pathname; + char buf[MAXPATHLEN+1]; + + if (!PyArg_ParseTupleAndKeywords( + args, kws, "es", kwlist, + Py_FileSystemDefaultEncoding, &pathname)) + return NULL; + + if (make_source_pathname(pathname, buf) == NULL) { + PyErr_Format(PyExc_ValueError, "Not a PEP 3147 pyc path: %s", + pathname); + PyMem_Free(pathname); + return NULL; + } + PyMem_Free(pathname); + return PyUnicode_FromString(buf); +} + +PyDoc_STRVAR(doc_source_from_cache, +"Given the path to a .pyc./.pyo file, return the path to its .py file.\n\ +\n\ +The .pyc/.pyo file does not need to exist; this simply returns the path to\n\ +the .py file calculated to correspond to the .pyc/.pyo file. If path\n\ +does not conform to PEP 3147 format, ValueError will be raised."); + /* Doc strings */ PyDoc_STRVAR(doc_imp, @@ -3212,6 +3539,10 @@ PyDoc_STRVAR(doc_get_magic, "get_magic() -> string\n\ Return the magic number for .pyc or .pyo files."); +PyDoc_STRVAR(doc_get_tag, +"get_tag() -> string\n\ +Return the magic tag 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\ @@ -3242,6 +3573,7 @@ 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_tag", imp_get_tag, METH_NOARGS, doc_get_tag}, {"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}, @@ -3249,6 +3581,10 @@ static PyMethodDef imp_methods[] = { {"acquire_lock", imp_acquire_lock, METH_NOARGS, doc_acquire_lock}, {"release_lock", imp_release_lock, METH_NOARGS, doc_release_lock}, {"reload", imp_reload, METH_O, doc_reload}, + {"cache_from_source", (PyCFunction)imp_cache_from_source, + METH_VARARGS | METH_KEYWORDS, doc_cache_from_source}, + {"source_from_cache", (PyCFunction)imp_source_from_cache, + METH_VARARGS | METH_KEYWORDS, doc_source_from_cache}, /* The rest are obsolete */ {"get_frozen_object", imp_get_frozen_object, METH_VARARGS}, {"is_frozen_package", imp_is_frozen_package, METH_VARARGS}, @@ -3436,7 +3772,6 @@ PyInit_imp(void) failure: Py_XDECREF(m); return NULL; - } diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 2bdef981ad..cc617be4d1 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1155,6 +1155,8 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, Py_DECREF(f); return -1; } + if (PyDict_SetItemString(d, "__cached__", Py_None) < 0) + return -1; set_file_name = 1; Py_DECREF(f); } -- cgit v1.2.1 From 0bd33e7b2ea42e3d245948120d02e36960982cb5 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Wed, 21 Apr 2010 22:56:22 +0000 Subject: Merged revisions 80325 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ........ r80325 | antoine.pitrou | 2010-04-22 00:53:29 +0200 (jeu., 22 avril 2010) | 6 lines Issue #7332: Remove the 16KB stack-based buffer in PyMarshal_ReadLastObjectFromFile, which doesn't bring any noticeable benefit compared to the dynamic memory allocation fallback. Patch by Charles-François Natali. ........ --- Python/marshal.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) (limited to 'Python') diff --git a/Python/marshal.c b/Python/marshal.c index 3391085ccb..90cd306a92 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -1078,23 +1078,13 @@ getfilesize(FILE *fp) 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) +/* REASONABLE_FILE_LIMIT is by defn something big enough for Tkinter.pyc. */ #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(filesize); + if (filesize > 0 && filesize <= REASONABLE_FILE_LIMIT) { + char* pBuf = (char *)PyMem_MALLOC(filesize); if (pBuf != NULL) { PyObject* v; size_t n; @@ -1102,8 +1092,7 @@ PyMarshal_ReadLastObjectFromFile(FILE *fp) is smaller than REASONABLE_FILE_LIMIT */ n = fread(pBuf, 1, (int)filesize, fp); v = PyMarshal_ReadObjectFromString(pBuf, n); - if (pBuf != buf) - PyMem_FREE(pBuf); + PyMem_FREE(pBuf); return v; } @@ -1114,7 +1103,6 @@ PyMarshal_ReadLastObjectFromFile(FILE *fp) */ return PyMarshal_ReadObjectFromFile(fp); -#undef SMALL_FILE_LIMIT #undef REASONABLE_FILE_LIMIT } -- cgit v1.2.1 From cb5af2523ff151d3de87f8905e7836c7d8926a2d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 23 Apr 2010 12:02:30 +0000 Subject: Issue #8124: PySys_WriteStdout() and PySys_WriteStderr() don't execute indirectly Python signal handlers anymore because mywrite() ignores exceptions (KeyboardInterrupt). --- Python/sysmodule.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 490577d3e2..8267369584 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1763,6 +1763,45 @@ PySys_SetArgv(int argc, wchar_t **argv) Py_DECREF(av); } +/* Reimplementation of PyFile_WriteString() no calling indirectly + PyErr_CheckSignals(): avoid the call to PyObject_Str(). */ + +static int +sys_pyfile_write(const char *text, PyObject *file) +{ + PyObject *unicode = NULL, *writer = NULL, *args = NULL, *result = NULL; + int err; + + unicode = PyUnicode_FromString(text); + if (unicode == NULL) + goto error; + + writer = PyObject_GetAttrString(file, "write"); + if (writer == NULL) + goto error; + + args = PyTuple_Pack(1, unicode); + if (args == NULL) + goto error; + + result = PyEval_CallObject(writer, args); + if (result == NULL) { + goto error; + } else { + err = 0; + goto finally; + } + +error: + err = -1; +finally: + Py_XDECREF(unicode); + Py_XDECREF(writer); + Py_XDECREF(args); + Py_XDECREF(result); + return err; +} + /* APIs to write to sys.stdout or sys.stderr using a printf-like interface. Adapted from code submitted by Just van Rossum. @@ -1774,6 +1813,10 @@ PySys_SetArgv(int argc, wchar_t **argv) there is a problem, they write to the real (C level) stdout or stderr; no exceptions are raised. + PyErr_CheckSignals() is not called to avoid the execution of the Python + signal handlers: they may raise a new exception whereas mywrite() ignores + all exceptions. + Both take a printf-style format string as their first argument followed by a variable length argument list determined by the format string. @@ -1799,13 +1842,13 @@ mywrite(char *name, FILE *fp, const char *format, va_list va) PyErr_Fetch(&error_type, &error_value, &error_traceback); file = PySys_GetObject(name); written = PyOS_vsnprintf(buffer, sizeof(buffer), format, va); - if (PyFile_WriteString(buffer, file) != 0) { + if (sys_pyfile_write(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) { + if (sys_pyfile_write(truncated, file) != 0) { PyErr_Clear(); fputs(truncated, fp); } -- cgit v1.2.1 From bb5f3669f8ead9897f824bf97375348d120eb008 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 24 Apr 2010 18:21:17 +0000 Subject: prevent the dict constructor from accepting non-string keyword args #8419 This adds PyArg_ValidateKeywordArguments, which checks that keyword arguments are all strings, using an optimized method if possible. --- Python/getargs.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index 17c5317d34..69f5018c4c 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1607,6 +1607,21 @@ _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *args, return retval; } +int +PyArg_ValidateKeywordArguments(PyObject *kwargs) +{ + if (!PyDict_CheckExact(kwargs)) { + PyErr_BadInternalCall(); + return 0; + } + if (!_PyDict_HasOnlyStringKeys(kwargs)) { + PyErr_SetString(PyExc_TypeError, + "keyword arguments must be strings"); + return 0; + } + return 1; +} + #define IS_END_OF_FORMAT(c) (c == '\0' || c == ';' || c == ':') static int -- cgit v1.2.1 From 8cc1fda6b8c2d74a3abd2b8a007880656add8997 Mon Sep 17 00:00:00 2001 From: Jeffrey Yasskin Date: Mon, 3 May 2010 19:29:34 +0000 Subject: Make (most of) Python's tests pass under Thread Sanitizer. http://code.google.com/p/data-race-test/wiki/ThreadSanitizer is a dynamic data race detector that runs on top of valgrind. With this patch, the binaries at http://code.google.com/p/data-race-test/wiki/ThreadSanitizer#Binaries pass many but not all of the Python tests. All of regrtest still passes outside of tsan. I've implemented part of the C1x atomic types so that we can explicitly mark variables that are used across threads, and get defined behavior as compilers advance. I've added tsan's client header and implementation to the codebase in dynamic_annotations.{h,c} (docs at http://code.google.com/p/data-race-test/wiki/DynamicAnnotations). Unfortunately, I haven't been able to get helgrind and drd to give sensible error messages, even when I use their client annotations, so I'm not supporting them. --- Python/ceval.c | 63 ++++++++++++------ Python/ceval_gil.h | 48 ++++++++------ Python/dynamic_annotations.c | 154 +++++++++++++++++++++++++++++++++++++++++++ Python/pystate.c | 37 ++++++----- Python/thread_pthread.h | 6 ++ 5 files changed, 253 insertions(+), 55 deletions(-) create mode 100644 Python/dynamic_annotations.c (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 0c14eb08e1..09f939ea8e 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -216,23 +216,46 @@ PyEval_GetCallStats(PyObject *self) #endif +/* This can set eval_breaker to 0 even though gil_drop_request became + 1. We believe this is all right because the eval loop will release + the GIL eventually anyway. */ #define COMPUTE_EVAL_BREAKER() \ - (eval_breaker = gil_drop_request | pendingcalls_to_do | pending_async_exc) + _Py_atomic_store_relaxed( \ + &eval_breaker, \ + _Py_atomic_load_relaxed(&gil_drop_request) | \ + _Py_atomic_load_relaxed(&pendingcalls_to_do) | \ + pending_async_exc) #define SET_GIL_DROP_REQUEST() \ - do { gil_drop_request = 1; eval_breaker = 1; } while (0) + do { \ + _Py_atomic_store_relaxed(&gil_drop_request, 1); \ + _Py_atomic_store_relaxed(&eval_breaker, 1); \ + } while (0) #define RESET_GIL_DROP_REQUEST() \ - do { gil_drop_request = 0; COMPUTE_EVAL_BREAKER(); } while (0) + do { \ + _Py_atomic_store_relaxed(&gil_drop_request, 0); \ + COMPUTE_EVAL_BREAKER(); \ + } while (0) +/* Pending calls are only modified under pending_lock */ #define SIGNAL_PENDING_CALLS() \ - do { pendingcalls_to_do = 1; eval_breaker = 1; } while (0) + do { \ + _Py_atomic_store_relaxed(&pendingcalls_to_do, 1); \ + _Py_atomic_store_relaxed(&eval_breaker, 1); \ + } while (0) #define UNSIGNAL_PENDING_CALLS() \ - do { pendingcalls_to_do = 0; COMPUTE_EVAL_BREAKER(); } while (0) + do { \ + _Py_atomic_store_relaxed(&pendingcalls_to_do, 0); \ + COMPUTE_EVAL_BREAKER(); \ + } while (0) #define SIGNAL_ASYNC_EXC() \ - do { pending_async_exc = 1; eval_breaker = 1; } while (0) + do { \ + pending_async_exc = 1; \ + _Py_atomic_store_relaxed(&eval_breaker, 1); \ + } while (0) #define UNSIGNAL_ASYNC_EXC() \ do { pending_async_exc = 0; COMPUTE_EVAL_BREAKER(); } while (0) @@ -249,13 +272,14 @@ static PyThread_type_lock pending_lock = 0; /* for pending calls */ static long main_thread = 0; /* This single variable consolidates all requests to break out of the fast path in the eval loop. */ -static volatile int eval_breaker = 0; -/* Request for droppping the GIL */ -static volatile int gil_drop_request = 0; -/* Request for running pending calls */ -static volatile int pendingcalls_to_do = 0; -/* Request for looking at the `async_exc` field of the current thread state */ -static volatile int pending_async_exc = 0; +static _Py_atomic_int eval_breaker = {0}; +/* Request for dropping the GIL */ +static _Py_atomic_int gil_drop_request = {0}; +/* Request for running pending calls. */ +static _Py_atomic_int pendingcalls_to_do = {0}; +/* Request for looking at the `async_exc` field of the current thread state. + Guarded by the GIL. */ +static int pending_async_exc = 0; #include "ceval_gil.h" @@ -293,7 +317,8 @@ PyEval_ReleaseLock(void) We therefore avoid PyThreadState_GET() which dumps a fatal error in debug mode. */ - drop_gil(_PyThreadState_Current); + drop_gil((PyThreadState*)_Py_atomic_load_relaxed( + &_PyThreadState_Current)); } void @@ -360,8 +385,8 @@ PyEval_ReInitThreads(void) } #else -static int eval_breaker = 0; -static int gil_drop_request = 0; +static _Py_atomic_int eval_breaker = {0}; +static _Py_atomic_int gil_drop_request = {0}; static int pending_async_exc = 0; #endif /* WITH_THREAD */ @@ -1217,7 +1242,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) async I/O handler); see Py_AddPendingCall() and Py_MakePendingCalls() above. */ - if (eval_breaker) { + if (_Py_atomic_load_relaxed(&eval_breaker)) { if (*next_instr == SETUP_FINALLY) { /* Make the last opcode before a try: finally: block uninterruptable. */ @@ -1227,13 +1252,13 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) #ifdef WITH_TSC ticked = 1; #endif - if (pendingcalls_to_do) { + if (_Py_atomic_load_relaxed(&pendingcalls_to_do)) { if (Py_MakePendingCalls() < 0) { why = WHY_EXCEPTION; goto on_error; } } - if (gil_drop_request) { + if (_Py_atomic_load_relaxed(&gil_drop_request)) { #ifdef WITH_THREAD /* Give another thread a chance */ if (PyThreadState_Swap(NULL) != tstate) diff --git a/Python/ceval_gil.h b/Python/ceval_gil.h index d4d6fdde6e..a284c5d8ce 100644 --- a/Python/ceval_gil.h +++ b/Python/ceval_gil.h @@ -207,14 +207,14 @@ do { \ #endif /* _POSIX_THREADS, NT_THREADS */ -/* Whether the GIL is already taken (-1 if uninitialized). This is volatile +/* Whether the GIL is already taken (-1 if uninitialized). This is atomic because it can be read without any lock taken in ceval.c. */ -static volatile int gil_locked = -1; +static _Py_atomic_int gil_locked = {-1}; /* Number of GIL switches since the beginning. */ static unsigned long gil_switch_number = 0; -/* Last thread holding / having held the GIL. This helps us know whether - anyone else was scheduled after we dropped the GIL. */ -static PyThreadState *gil_last_holder = NULL; +/* Last PyThreadState holding / having held the GIL. This helps us know + whether anyone else was scheduled after we dropped the GIL. */ +static _Py_atomic_address gil_last_holder = {NULL}; /* This condition variable allows one or several threads to wait until the GIL is released. In addition, the mutex also protects the above @@ -232,7 +232,7 @@ static MUTEX_T switch_mutex; static int gil_created(void) { - return gil_locked >= 0; + return _Py_atomic_load_explicit(&gil_locked, _Py_memory_order_acquire) >= 0; } static void create_gil(void) @@ -245,33 +245,37 @@ static void create_gil(void) #ifdef FORCE_SWITCHING COND_INIT(switch_cond); #endif - gil_locked = 0; - gil_last_holder = NULL; + _Py_atomic_store_relaxed(&gil_last_holder, NULL); + _Py_ANNOTATE_RWLOCK_CREATE(&gil_locked); + _Py_atomic_store_explicit(&gil_locked, 0, _Py_memory_order_release); } static void recreate_gil(void) { + _Py_ANNOTATE_RWLOCK_DESTROY(&gil_locked); create_gil(); } static void drop_gil(PyThreadState *tstate) { /* NOTE: tstate is allowed to be NULL. */ - if (!gil_locked) + if (!_Py_atomic_load_relaxed(&gil_locked)) Py_FatalError("drop_gil: GIL is not locked"); - if (tstate != NULL && tstate != gil_last_holder) + if (tstate != NULL && + tstate != _Py_atomic_load_relaxed(&gil_last_holder)) Py_FatalError("drop_gil: wrong thread state"); MUTEX_LOCK(gil_mutex); - gil_locked = 0; + _Py_ANNOTATE_RWLOCK_RELEASED(&gil_locked, /*is_write=*/1); + _Py_atomic_store_relaxed(&gil_locked, 0); COND_SIGNAL(gil_cond); MUTEX_UNLOCK(gil_mutex); #ifdef FORCE_SWITCHING - if (gil_drop_request && tstate != NULL) { + if (_Py_atomic_load_relaxed(&gil_drop_request) && tstate != NULL) { MUTEX_LOCK(switch_mutex); /* Not switched yet => wait */ - if (gil_last_holder == tstate) { + if (_Py_atomic_load_relaxed(&gil_last_holder) == tstate) { RESET_GIL_DROP_REQUEST(); /* NOTE: if COND_WAIT does not atomically start waiting when releasing the mutex, another thread can run through, take @@ -294,11 +298,11 @@ static void take_gil(PyThreadState *tstate) err = errno; MUTEX_LOCK(gil_mutex); - if (!gil_locked) + if (!_Py_atomic_load_relaxed(&gil_locked)) goto _ready; COND_RESET(gil_cond); - while (gil_locked) { + while (_Py_atomic_load_relaxed(&gil_locked)) { int timed_out = 0; unsigned long saved_switchnum; @@ -306,7 +310,9 @@ static void take_gil(PyThreadState *tstate) COND_TIMED_WAIT(gil_cond, gil_mutex, INTERVAL, timed_out); /* If we timed out and no switch occurred in the meantime, it is time to ask the GIL-holding thread to drop it. */ - if (timed_out && gil_locked && gil_switch_number == saved_switchnum) { + if (timed_out && + _Py_atomic_load_relaxed(&gil_locked) && + gil_switch_number == saved_switchnum) { SET_GIL_DROP_REQUEST(); } } @@ -316,17 +322,19 @@ _ready: MUTEX_LOCK(switch_mutex); #endif /* We now hold the GIL */ - gil_locked = 1; + _Py_atomic_store_relaxed(&gil_locked, 1); + _Py_ANNOTATE_RWLOCK_ACQUIRED(&gil_locked, /*is_write=*/1); - if (tstate != gil_last_holder) { - gil_last_holder = tstate; + if (tstate != _Py_atomic_load_relaxed(&gil_last_holder)) { + _Py_atomic_store_relaxed(&gil_last_holder, tstate); ++gil_switch_number; } + #ifdef FORCE_SWITCHING COND_SIGNAL(switch_cond); MUTEX_UNLOCK(switch_mutex); #endif - if (gil_drop_request) { + if (_Py_atomic_load_relaxed(&gil_drop_request)) { RESET_GIL_DROP_REQUEST(); } if (tstate->async_exc != NULL) { diff --git a/Python/dynamic_annotations.c b/Python/dynamic_annotations.c new file mode 100644 index 0000000000..10511da466 --- /dev/null +++ b/Python/dynamic_annotations.c @@ -0,0 +1,154 @@ +/* Copyright (c) 2008-2009, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * --- + * Author: Kostya Serebryany + */ + +#ifdef _MSC_VER +# include +#endif + +#ifdef __cplusplus +# error "This file should be built as pure C to avoid name mangling" +#endif + +#include +#include + +#include "dynamic_annotations.h" + +/* Each function is empty and called (via a macro) only in debug mode. + The arguments are captured by dynamic tools at runtime. */ + +#if DYNAMIC_ANNOTATIONS_ENABLED == 1 + +void AnnotateRWLockCreate(const char *file, int line, + const volatile void *lock){} +void AnnotateRWLockDestroy(const char *file, int line, + const volatile void *lock){} +void AnnotateRWLockAcquired(const char *file, int line, + const volatile void *lock, long is_w){} +void AnnotateRWLockReleased(const char *file, int line, + const volatile void *lock, long is_w){} +void AnnotateBarrierInit(const char *file, int line, + const volatile void *barrier, long count, + long reinitialization_allowed) {} +void AnnotateBarrierWaitBefore(const char *file, int line, + const volatile void *barrier) {} +void AnnotateBarrierWaitAfter(const char *file, int line, + const volatile void *barrier) {} +void AnnotateBarrierDestroy(const char *file, int line, + const volatile void *barrier) {} + +void AnnotateCondVarWait(const char *file, int line, + const volatile void *cv, + const volatile void *lock){} +void AnnotateCondVarSignal(const char *file, int line, + const volatile void *cv){} +void AnnotateCondVarSignalAll(const char *file, int line, + const volatile void *cv){} +void AnnotatePublishMemoryRange(const char *file, int line, + const volatile void *address, + long size){} +void AnnotateUnpublishMemoryRange(const char *file, int line, + const volatile void *address, + long size){} +void AnnotatePCQCreate(const char *file, int line, + const volatile void *pcq){} +void AnnotatePCQDestroy(const char *file, int line, + const volatile void *pcq){} +void AnnotatePCQPut(const char *file, int line, + const volatile void *pcq){} +void AnnotatePCQGet(const char *file, int line, + const volatile void *pcq){} +void AnnotateNewMemory(const char *file, int line, + const volatile void *mem, + long size){} +void AnnotateExpectRace(const char *file, int line, + const volatile void *mem, + const char *description){} +void AnnotateBenignRace(const char *file, int line, + const volatile void *mem, + const char *description){} +void AnnotateBenignRaceSized(const char *file, int line, + const volatile void *mem, + long size, + const char *description) {} +void AnnotateMutexIsUsedAsCondVar(const char *file, int line, + const volatile void *mu){} +void AnnotateTraceMemory(const char *file, int line, + const volatile void *arg){} +void AnnotateThreadName(const char *file, int line, + const char *name){} +void AnnotateIgnoreReadsBegin(const char *file, int line){} +void AnnotateIgnoreReadsEnd(const char *file, int line){} +void AnnotateIgnoreWritesBegin(const char *file, int line){} +void AnnotateIgnoreWritesEnd(const char *file, int line){} +void AnnotateIgnoreSyncBegin(const char *file, int line){} +void AnnotateIgnoreSyncEnd(const char *file, int line){} +void AnnotateEnableRaceDetection(const char *file, int line, int enable){} +void AnnotateNoOp(const char *file, int line, + const volatile void *arg){} +void AnnotateFlushState(const char *file, int line){} + +static int GetRunningOnValgrind(void) { +#ifdef RUNNING_ON_VALGRIND + if (RUNNING_ON_VALGRIND) return 1; +#endif + +#ifndef _MSC_VER + char *running_on_valgrind_str = getenv("RUNNING_ON_VALGRIND"); + if (running_on_valgrind_str) { + return strcmp(running_on_valgrind_str, "0") != 0; + } +#else + /* Visual Studio issues warnings if we use getenv, + * so we use GetEnvironmentVariableA instead. + */ + char value[100] = "1"; + int res = GetEnvironmentVariableA("RUNNING_ON_VALGRIND", + value, sizeof(value)); + /* value will remain "1" if res == 0 or res >= sizeof(value). The latter + * can happen only if the given value is long, in this case it can't be "0". + */ + if (res > 0 && !strcmp(value, "0")) + return 1; +#endif + return 0; +} + +/* See the comments in dynamic_annotations.h */ +int RunningOnValgrind(void) { + static volatile int running_on_valgrind = -1; + /* C doesn't have thread-safe initialization of statics, and we + don't want to depend on pthread_once here, so hack it. */ + int local_running_on_valgrind = running_on_valgrind; + if (local_running_on_valgrind == -1) + running_on_valgrind = local_running_on_valgrind = GetRunningOnValgrind(); + return local_running_on_valgrind; +} + +#endif /* DYNAMIC_ANNOTATIONS_ENABLED == 1 */ diff --git a/Python/pystate.c b/Python/pystate.c index eb2dfa6e3a..7154aeac24 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -47,7 +47,9 @@ static int autoTLSkey = 0; static PyInterpreterState *interp_head = NULL; -PyThreadState *_PyThreadState_Current = NULL; +/* Assuming the current thread holds the GIL, this is the + PyThreadState for the current thread. */ +_Py_atomic_address _PyThreadState_Current = {NULL}; PyThreadFrameGetter _PyThreadState_GetFrame = NULL; #ifdef WITH_THREAD @@ -334,7 +336,7 @@ tstate_delete_common(PyThreadState *tstate) void PyThreadState_Delete(PyThreadState *tstate) { - if (tstate == _PyThreadState_Current) + if (tstate == _Py_atomic_load_relaxed(&_PyThreadState_Current)) Py_FatalError("PyThreadState_Delete: tstate is still current"); tstate_delete_common(tstate); #ifdef WITH_THREAD @@ -348,11 +350,12 @@ PyThreadState_Delete(PyThreadState *tstate) void PyThreadState_DeleteCurrent() { - PyThreadState *tstate = _PyThreadState_Current; + PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed( + &_PyThreadState_Current); if (tstate == NULL) Py_FatalError( "PyThreadState_DeleteCurrent: no current tstate"); - _PyThreadState_Current = NULL; + _Py_atomic_store_relaxed(&_PyThreadState_Current, NULL); tstate_delete_common(tstate); if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate) PyThread_delete_key_value(autoTLSkey); @@ -364,19 +367,22 @@ PyThreadState_DeleteCurrent() PyThreadState * PyThreadState_Get(void) { - if (_PyThreadState_Current == NULL) + PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed( + &_PyThreadState_Current); + if (tstate == NULL) Py_FatalError("PyThreadState_Get: no current thread"); - return _PyThreadState_Current; + return tstate; } PyThreadState * PyThreadState_Swap(PyThreadState *newts) { - PyThreadState *oldts = _PyThreadState_Current; + PyThreadState *oldts = (PyThreadState*)_Py_atomic_load_relaxed( + &_PyThreadState_Current); - _PyThreadState_Current = newts; + _Py_atomic_store_relaxed(&_PyThreadState_Current, newts); /* It should not be possible for more than one thread state to be used for a thread. Check this the best we can in debug builds. @@ -405,16 +411,18 @@ PyThreadState_Swap(PyThreadState *newts) PyObject * PyThreadState_GetDict(void) { - if (_PyThreadState_Current == NULL) + PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed( + &_PyThreadState_Current); + if (tstate == NULL) return NULL; - if (_PyThreadState_Current->dict == NULL) { + if (tstate->dict == NULL) { PyObject *d; - _PyThreadState_Current->dict = d = PyDict_New(); + tstate->dict = d = PyDict_New(); if (d == NULL) PyErr_Clear(); } - return _PyThreadState_Current->dict; + return tstate->dict; } @@ -550,10 +558,7 @@ 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; + return tstate == _Py_atomic_load_relaxed(&_PyThreadState_Current); } /* Internal initialization/finalization functions called by diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index 6088c71fdb..f60f36dc2e 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -397,6 +397,12 @@ PyThread_allocate_lock(void) status = pthread_mutex_init(&lock->mut, pthread_mutexattr_default); CHECK_STATUS("pthread_mutex_init"); + /* Mark the pthread mutex underlying a Python mutex as + pure happens-before. We can't simply mark the + Python-level mutex as a mutex because it can be + acquired and released in different threads, which + will cause errors. */ + _Py_ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&lock->mut); status = pthread_cond_init(&lock->lock_released, pthread_condattr_default); -- cgit v1.2.1 From 77364e3ac948c1e156e4849f62b10f5df5fab9c2 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 3 May 2010 21:09:59 +0000 Subject: read eval_breaker with atomic api with computed gotos --- Python/ceval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 09f939ea8e..3bd0ce62ac 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -868,7 +868,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) #define DISPATCH() \ { \ - if (!eval_breaker) { \ + if (!_Py_atomic_load_relaxed(&eval_breaker)) { \ FAST_DISPATCH(); \ } \ continue; \ -- cgit v1.2.1 From 122aa3574de7e6b341502e5bfde280d2d47f7266 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 8 May 2010 00:07:07 +0000 Subject: err_input(): don't encode/decode the unicode message --- Python/pythonrun.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index cc617be4d1..225d178986 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1896,7 +1896,7 @@ static void err_input(perrdetail *err) { PyObject *v, *w, *errtype, *errtext; - PyObject* u = NULL; + PyObject *msg_obj = NULL; char *msg = NULL; errtype = PyExc_SyntaxError; switch (err->error) { @@ -1952,14 +1952,9 @@ err_input(perrdetail *err) case E_DECODE: { PyObject *type, *value, *tb; PyErr_Fetch(&type, &value, &tb); - if (value != NULL) { - u = PyObject_Str(value); - if (u != NULL) { - msg = _PyUnicode_AsString(u); - } - } - if (msg == NULL) - msg = "unknown decode error"; + msg = "unknown decode error"; + if (value != NULL) + msg_obj = PyObject_Str(value); Py_XDECREF(type); Py_XDECREF(value); Py_XDECREF(tb); @@ -1988,14 +1983,18 @@ err_input(perrdetail *err) } v = Py_BuildValue("(ziiN)", err->filename, err->lineno, err->offset, errtext); - w = NULL; - if (v != NULL) - w = Py_BuildValue("(sO)", msg, v); - Py_XDECREF(u); + if (v != NULL) { + if (msg_obj) + w = Py_BuildValue("(OO)", msg_obj, v); + else + w = Py_BuildValue("(sO)", msg, v); + } else + w = NULL; Py_XDECREF(v); PyErr_SetObject(errtype, w); Py_XDECREF(w); cleanup: + Py_XDECREF(msg_obj); if (err->text != NULL) { PyObject_FREE(err->text); err->text = NULL; -- cgit v1.2.1 From 95b5bbac56711054014d793264819be0b34c7764 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 8 May 2010 00:35:33 +0000 Subject: PyErr_SetFromErrnoWithFilename() decodes the filename using PyUnicode_DecodeFSDefault() instead of PyUnicode_FromString() --- Python/errors.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/errors.c b/Python/errors.c index 062658d737..274bdbe476 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -446,7 +446,7 @@ PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject) PyObject * PyErr_SetFromErrnoWithFilename(PyObject *exc, const char *filename) { - PyObject *name = filename ? PyUnicode_FromString(filename) : NULL; + PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL; PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name); Py_XDECREF(name); return result; -- cgit v1.2.1 From 30dd43e9dcd124029da3b83ace652cbebea43c7e Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Sun, 9 May 2010 03:18:57 +0000 Subject: Merged revisions 81007 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r81007 | jean-paul.calderone | 2010-05-08 16:06:02 -0400 (Sat, 08 May 2010) | 1 line Skip signal handler re-installation if it is not necessary. Issue 8354. ........ --- Python/pythonrun.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 225d178986..05a10c61c4 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -2254,6 +2254,10 @@ PyOS_sighandler_t PyOS_setsig(int sig, PyOS_sighandler_t handler) { #ifdef HAVE_SIGACTION + /* Some code in Modules/signalmodule.c depends on sigaction() being + * used here if HAVE_SIGACTION is defined. Fix that if this code + * changes to invalidate that assumption. + */ struct sigaction context, ocontext; context.sa_handler = handler; sigemptyset(&context.sa_mask); -- cgit v1.2.1 From 567b94adaaceb622c33f9be1998735dfb95f1707 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sun, 9 May 2010 15:52:27 +0000 Subject: Recorded merge of revisions 81029 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r81029 | antoine.pitrou | 2010-05-09 16:46:46 +0200 (dim., 09 mai 2010) | 3 lines Untabify C files. Will watch buildbots. ........ --- Python/_warnings.c | 80 +- Python/asdl.c | 88 +- Python/ast.c | 190 +- Python/bltinmodule.c | 3288 ++++++++++---------- Python/ceval.c | 7118 +++++++++++++++++++++---------------------- Python/codecs.c | 1044 +++---- Python/compile.c | 6416 +++++++++++++++++++------------------- Python/dynload_aix.c | 280 +- Python/dynload_hpux.c | 74 +- Python/dynload_next.c | 150 +- Python/dynload_os2.c | 58 +- Python/dynload_shlib.c | 152 +- Python/dynload_win.c | 420 +-- Python/errors.c | 1282 ++++---- Python/frozen.c | 28 +- Python/frozenmain.c | 154 +- Python/future.c | 232 +- Python/getargs.c | 3312 ++++++++++---------- Python/getcwd.c | 78 +- Python/getopt.c | 150 +- Python/import.c | 5480 ++++++++++++++++----------------- Python/importdl.c | 116 +- Python/importdl.h | 28 +- Python/makeopcodetargets.py | 2 +- Python/marshal.c | 2130 ++++++------- Python/modsupport.c | 968 +++--- Python/mysnprintf.c | 112 +- Python/mystrtoul.c | 440 +-- Python/opcode_targets.h | 512 ++-- Python/peephole.c | 1232 ++++---- Python/pyarena.c | 300 +- Python/pymath.c | 48 +- Python/pystate.c | 786 ++--- Python/pystrcmp.c | 24 +- Python/pystrtod.c | 1904 ++++++------ Python/pythonrun.c | 3272 ++++++++++---------- Python/structmember.c | 548 ++-- Python/symtable.c | 2614 ++++++++-------- Python/sysmodule.c | 1970 ++++++------ Python/thread.c | 264 +- Python/thread_cthread.h | 94 +- Python/thread_foobar.h | 44 +- Python/thread_lwp.h | 122 +- Python/thread_nt.h | 356 +-- Python/thread_os2.h | 280 +- Python/thread_pth.h | 192 +- Python/thread_pthread.h | 528 ++-- Python/thread_sgi.h | 358 +-- Python/thread_solaris.h | 142 +- Python/thread_wince.h | 70 +- Python/traceback.c | 560 ++-- 51 files changed, 25045 insertions(+), 25045 deletions(-) (limited to 'Python') diff --git a/Python/_warnings.c b/Python/_warnings.c index 35a840e3b4..c49f3f3223 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -85,10 +85,10 @@ get_default_action(void) default_action = get_warnings_attr("defaultaction"); if (default_action == NULL) { - if (PyErr_Occurred()) { - return NULL; - } - return _default_action; + if (PyErr_Occurred()) { + return NULL; + } + return _default_action; } Py_DECREF(_default_action); @@ -202,12 +202,12 @@ normalize_module(PyObject *filename) mod_str = _PyUnicode_AsString(filename); if (mod_str == NULL) - return NULL; + return NULL; len = PyUnicode_GetSize(filename); if (len < 0) return NULL; if (len >= 3 && - strncmp(mod_str + (len - 3), ".py", 3) == 0) { + strncmp(mod_str + (len - 3), ".py", 3) == 0) { module = PyUnicode_FromStringAndSize(mod_str, len-3); } else { @@ -243,15 +243,15 @@ static void show_warning(PyObject *filename, int lineno, PyObject *text, PyObject *category, PyObject *sourceline) { - PyObject *f_stderr; - PyObject *name; + PyObject *f_stderr; + PyObject *name; char lineno_str[128]; PyOS_snprintf(lineno_str, sizeof(lineno_str), ":%d: ", lineno); name = PyObject_GetAttrString(category, "__name__"); if (name == NULL) /* XXX Can an object lack a '__name__' attribute? */ - return; + return; f_stderr = PySys_GetObject("stderr"); if (f_stderr == NULL) { @@ -272,8 +272,8 @@ show_warning(PyObject *filename, int lineno, PyObject *text, PyObject /* Print " source_line\n" */ if (sourceline) { char *source_line_str = _PyUnicode_AsString(sourceline); - if (source_line_str == NULL) - return; + if (source_line_str == NULL) + return; while (*source_line_str == ' ' || *source_line_str == '\t' || *source_line_str == '\014') source_line_str++; @@ -284,12 +284,12 @@ show_warning(PyObject *filename, int lineno, PyObject *text, PyObject else if (_Py_DisplaySourceLine(f_stderr, _PyUnicode_AsString(filename), lineno, 2) < 0) - return; + return; PyErr_Clear(); } static PyObject * -warn_explicit(PyObject *category, PyObject *message, +warn_explicit(PyObject *category, PyObject *message, PyObject *filename, int lineno, PyObject *module, PyObject *registry, PyObject *sourceline) { @@ -297,7 +297,7 @@ warn_explicit(PyObject *category, PyObject *message, PyObject *item = Py_None; const char *action; int rc; - + if (registry && !PyDict_Check(registry) && (registry != Py_None)) { PyErr_SetString(PyExc_TypeError, "'registry' must be a dict"); return NULL; @@ -344,7 +344,7 @@ warn_explicit(PyObject *category, PyObject *message, rc = already_warned(registry, key, 0); if (rc == -1) goto cleanup; - else if (rc == 1) + else if (rc == 1) goto return_none; /* Else this warning hasn't been generated before. */ } @@ -374,12 +374,12 @@ warn_explicit(PyObject *category, PyObject *message, goto cleanup; } /* _once_registry[(text, category)] = 1 */ - rc = update_registry(registry, text, category, 0); + rc = update_registry(registry, text, category, 0); } else if (strcmp(action, "module") == 0) { /* registry[(text, category, 0)] = 1 */ if (registry != NULL && registry != Py_None) - rc = update_registry(registry, text, category, 0); + rc = update_registry(registry, text, category, 0); } else if (strcmp(action, "default") != 0) { PyObject *to_str = PyObject_Str(item); @@ -387,9 +387,9 @@ warn_explicit(PyObject *category, PyObject *message, if (to_str != NULL) { err_str = _PyUnicode_AsString(to_str); - if (err_str == NULL) - goto cleanup; - } + if (err_str == NULL) + goto cleanup; + } PyErr_Format(PyExc_RuntimeError, "Unrecognized action (%s) in warnings.filters:\n %s", action, err_str); @@ -500,7 +500,7 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, if (*filename != NULL) { Py_ssize_t len = PyUnicode_GetSize(*filename); const char *file_str = _PyUnicode_AsString(*filename); - if (file_str == NULL || (len < 0 && PyErr_Occurred())) + if (file_str == NULL || (len < 0 && PyErr_Occurred())) goto handle_error; /* if filename.lower().endswith((".pyc", ".pyo")): */ @@ -512,16 +512,16 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, tolower(file_str[len-1]) == 'o')) { *filename = PyUnicode_FromStringAndSize(file_str, len-1); - if (*filename == NULL) - goto handle_error; - } - else + if (*filename == NULL) + goto handle_error; + } + else Py_INCREF(*filename); } else { const char *module_str = _PyUnicode_AsString(*module); - if (module_str == NULL) - goto handle_error; + if (module_str == NULL) + goto handle_error; if (strcmp(module_str, "__main__") == 0) { PyObject *argv = PySys_GetObject("argv"); if (argv != NULL && PyList_Size(argv) > 0) { @@ -544,8 +544,8 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, else { /* embedded interpreters don't have sys.argv, see bug #839151 */ *filename = PyUnicode_FromString("__main__"); - if (*filename == NULL) - goto handle_error; + if (*filename == NULL) + goto handle_error; } } if (*filename == NULL) { @@ -616,7 +616,7 @@ warnings_warn(PyObject *self, PyObject *args, PyObject *kwds) PyObject *message, *category = NULL; Py_ssize_t stack_level = 1; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|On:warn", kw_list, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|On:warn", kw_list, &message, &category, &stack_level)) return NULL; @@ -794,7 +794,7 @@ static PyMethodDef warnings_functions[] = { METH_VARARGS | METH_KEYWORDS, warn_explicit_doc}, /* XXX(brett.cannon): add showwarning? */ /* XXX(brett.cannon): Reasonable to add formatwarning? */ - {NULL, NULL} /* sentinel */ + {NULL, NULL} /* sentinel */ }; @@ -875,15 +875,15 @@ init_filters(void) } static struct PyModuleDef warningsmodule = { - PyModuleDef_HEAD_INIT, - MODULE_NAME, - warnings__doc__, - 0, - warnings_functions, - NULL, - NULL, - NULL, - NULL + PyModuleDef_HEAD_INIT, + MODULE_NAME, + warnings__doc__, + 0, + warnings_functions, + NULL, + NULL, + NULL, + NULL }; diff --git a/Python/asdl.c b/Python/asdl.c index 1105d3aa57..c30d7d2059 100644 --- a/Python/asdl.c +++ b/Python/asdl.c @@ -4,61 +4,61 @@ asdl_seq * asdl_seq_new(int size, PyArena *arena) { - asdl_seq *seq = NULL; - size_t n = (size ? (sizeof(void *) * (size - 1)) : 0); + asdl_seq *seq = NULL; + size_t n = (size ? (sizeof(void *) * (size - 1)) : 0); - /* check size is sane */ - if (size < 0 || size == INT_MIN || - (size && ((size - 1) > (PY_SIZE_MAX / sizeof(void *))))) { - PyErr_NoMemory(); - return NULL; - } + /* check size is sane */ + if (size < 0 || size == INT_MIN || + (size && ((size - 1) > (PY_SIZE_MAX / sizeof(void *))))) { + PyErr_NoMemory(); + return NULL; + } - /* check if size can be added safely */ - if (n > PY_SIZE_MAX - sizeof(asdl_seq)) { - PyErr_NoMemory(); - return NULL; - } + /* check if size can be added safely */ + if (n > PY_SIZE_MAX - sizeof(asdl_seq)) { + PyErr_NoMemory(); + return NULL; + } - n += sizeof(asdl_seq); + n += sizeof(asdl_seq); - seq = (asdl_seq *)PyArena_Malloc(arena, n); - if (!seq) { - PyErr_NoMemory(); - return NULL; - } - memset(seq, 0, n); - seq->size = size; - return seq; + seq = (asdl_seq *)PyArena_Malloc(arena, n); + if (!seq) { + PyErr_NoMemory(); + return NULL; + } + memset(seq, 0, n); + seq->size = size; + return seq; } asdl_int_seq * asdl_int_seq_new(int size, PyArena *arena) { - asdl_int_seq *seq = NULL; - size_t n = (size ? (sizeof(void *) * (size - 1)) : 0); + asdl_int_seq *seq = NULL; + size_t n = (size ? (sizeof(void *) * (size - 1)) : 0); - /* check size is sane */ - if (size < 0 || size == INT_MIN || - (size && ((size - 1) > (PY_SIZE_MAX / sizeof(void *))))) { - PyErr_NoMemory(); - return NULL; - } + /* check size is sane */ + if (size < 0 || size == INT_MIN || + (size && ((size - 1) > (PY_SIZE_MAX / sizeof(void *))))) { + PyErr_NoMemory(); + return NULL; + } - /* check if size can be added safely */ - if (n > PY_SIZE_MAX - sizeof(asdl_seq)) { - PyErr_NoMemory(); - return NULL; - } + /* check if size can be added safely */ + if (n > PY_SIZE_MAX - sizeof(asdl_seq)) { + PyErr_NoMemory(); + return NULL; + } - n += sizeof(asdl_seq); + n += sizeof(asdl_seq); - seq = (asdl_int_seq *)PyArena_Malloc(arena, n); - if (!seq) { - PyErr_NoMemory(); - return NULL; - } - memset(seq, 0, n); - seq->size = size; - return seq; + seq = (asdl_int_seq *)PyArena_Malloc(arena, n); + if (!seq) { + PyErr_NoMemory(); + return NULL; + } + memset(seq, 0, n); + seq->size = size; + return seq; } diff --git a/Python/ast.c b/Python/ast.c index c6a6417efe..0703abc9a7 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -58,19 +58,19 @@ new_identifier(const char* n, PyArena *arena) /* Check whether there are non-ASCII characters in the identifier; if so, normalize to NFKC. */ for (; *u; u++) { - if (*u >= 128) { - PyObject *m = PyImport_ImportModuleNoBlock("unicodedata"); - PyObject *id2; - if (!m) - return NULL; - id2 = PyObject_CallMethod(m, "normalize", "sO", "NFKC", id); - Py_DECREF(m); - if (!id2) - return NULL; - Py_DECREF(id); - id = id2; - break; - } + if (*u >= 128) { + PyObject *m = PyImport_ImportModuleNoBlock("unicodedata"); + PyObject *id2; + if (!m) + return NULL; + id2 = PyObject_CallMethod(m, "normalize", "sO", "NFKC", id); + Py_DECREF(m); + if (!id2) + return NULL; + Py_DECREF(id); + id = id2; + break; + } } PyUnicode_InternInPlace(&id); PyArena_AddPyObject(arena, id); @@ -226,7 +226,7 @@ PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename, c.c_encoding = STR(n); n = CHILD(n, 0); } else { - /* PEP 3120 */ + /* PEP 3120 */ c.c_encoding = "utf-8"; } c.c_arena = arena; @@ -481,8 +481,8 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n) expr_name = "conditional expression"; break; default: - PyErr_Format(PyExc_SystemError, - "unexpected expression in assignment %d (line %d)", + PyErr_Format(PyExc_SystemError, + "unexpected expression in assignment %d (line %d)", e->kind, e->lineno); return 0; } @@ -497,7 +497,7 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n) } /* If the LHS is a list or tuple, we need to set the assignment - context for all the contained elements. + context for all the contained elements. */ if (s) { int i; @@ -603,7 +603,7 @@ ast_for_comp_op(struct compiling *c, const node *n) static asdl_seq * seq_for_testlist(struct compiling *c, const node *n) { - /* testlist: test (',' test)* [','] + /* testlist: test (',' test)* [','] testlist_star_expr: test|star_expr (',' test|star_expr)* [','] */ asdl_seq *seq; @@ -616,7 +616,7 @@ seq_for_testlist(struct compiling *c, const node *n) return NULL; for (i = 0; i < NCH(n); i += 2) { - const node *ch = CHILD(n, i); + const node *ch = CHILD(n, i); assert(TYPE(ch) == test || TYPE(ch) == test_nocond || TYPE(ch) == star_expr); expression = ast_for_expr(c, ch); @@ -726,7 +726,7 @@ handle_keywordonly_args(struct compiling *c, const node *n, int start, } return i; error: - return -1; + return -1; } /* Create AST for argument list. */ @@ -739,12 +739,12 @@ ast_for_arguments(struct compiling *c, const node *n) parameters: '(' [typedargslist] ')' typedargslist: ((tfpdef ['=' test] ',')* - ('*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] + ('*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef) | tfpdef ['=' test] (',' tfpdef ['=' test])* [',']) tfpdef: NAME [':' test] varargslist: ((vfpdef ['=' test] ',')* - ('*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] + ('*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef) | vfpdef ['=' test] (',' vfpdef ['=' test])* [',']) vfpdef: NAME @@ -785,7 +785,7 @@ ast_for_arguments(struct compiling *c, const node *n) if (TYPE(ch) == vfpdef || TYPE(ch) == tfpdef) nposargs++; if (TYPE(ch) == EQUAL) nposdefaults++; } - /* count the number of keyword only args & + /* count the number of keyword only args & defaults for keyword only args */ for ( ; i < NCH(n); ++i) { ch = CHILD(n, i); @@ -799,11 +799,11 @@ ast_for_arguments(struct compiling *c, const node *n) asdl_seq_new(nkwonlyargs, c->c_arena) : NULL); if (!kwonlyargs && nkwonlyargs) goto error; - posdefaults = (nposdefaults ? + posdefaults = (nposdefaults ? asdl_seq_new(nposdefaults, c->c_arena) : NULL); if (!posdefaults && nposdefaults) goto error; - /* The length of kwonlyargs and kwdefaults are same + /* The length of kwonlyargs and kwdefaults are same since we set NULL as default for keyword only argument w/o default - we have sequence data structure, but no dictionary */ kwdefaults = (nkwonlyargs ? @@ -840,7 +840,7 @@ ast_for_arguments(struct compiling *c, const node *n) found_default = 1; } else if (found_default) { - ast_error(n, + ast_error(n, "non-default argument follows default argument"); goto error; } @@ -852,7 +852,7 @@ ast_for_arguments(struct compiling *c, const node *n) break; case STAR: if (i+1 >= NCH(n)) { - ast_error(CHILD(n, i), + ast_error(CHILD(n, i), "named arguments must follow bare *"); goto error; } @@ -953,15 +953,15 @@ ast_for_decorator(struct compiling *c, const node *n) /* decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE */ expr_ty d = NULL; expr_ty name_expr; - + REQ(n, decorator); REQ(CHILD(n, 0), AT); REQ(RCHILD(n, -1), NEWLINE); - + name_expr = ast_for_dotted_name(c, CHILD(n, 1)); if (!name_expr) return NULL; - + if (NCH(n) == 3) { /* No arguments */ d = name_expr; name_expr = NULL; @@ -989,12 +989,12 @@ ast_for_decorators(struct compiling *c, const node *n) asdl_seq* decorator_seq; expr_ty d; int i; - + REQ(n, decorators); decorator_seq = asdl_seq_new(NCH(n), c->c_arena); if (!decorator_seq) return NULL; - + for (i = 0; i < NCH(n); i++) { d = ast_for_decorator(c, CHILD(n, i)); if (!d) @@ -1052,7 +1052,7 @@ ast_for_decorated(struct compiling *c, const node *n) return NULL; assert(TYPE(CHILD(n, 1)) == funcdef || - TYPE(CHILD(n, 1)) == classdef); + TYPE(CHILD(n, 1)) == classdef); if (TYPE(CHILD(n, 1)) == funcdef) { thing = ast_for_funcdef(c, CHILD(n, 1), decorator_seq); @@ -1100,7 +1100,7 @@ ast_for_lambdef(struct compiling *c, const node *n) static expr_ty ast_for_ifexpr(struct compiling *c, const node *n) { - /* test: or_test 'if' or_test 'else' test */ + /* test: or_test 'if' or_test 'else' test */ expr_ty expression, body, orelse; assert(NCH(n) == 5); @@ -1197,9 +1197,9 @@ ast_for_comprehension(struct compiling *c, const node *n) asdl_seq *t; expr_ty expression, first; node *for_ch; - + REQ(n, comp_for); - + for_ch = CHILD(n, 1); t = ast_for_exprlist(c, for_ch, Store); if (!t) @@ -1223,7 +1223,7 @@ ast_for_comprehension(struct compiling *c, const node *n) if (NCH(n) == 5) { int j, n_ifs; asdl_seq *ifs; - + n = CHILD(n, 4); n_ifs = count_comp_ifs(c, n); if (n_ifs == -1) @@ -1237,7 +1237,7 @@ ast_for_comprehension(struct compiling *c, const node *n) REQ(n, comp_iter); n = CHILD(n, 0); REQ(n, comp_if); - + expression = ast_for_expr(c, CHILD(n, 1)); if (!expression) return NULL; @@ -1262,13 +1262,13 @@ ast_for_itercomp(struct compiling *c, const node *n, int type) argument: [test '='] test [comp_for] # Really [keyword '='] test */ expr_ty elt; asdl_seq *comps; - + assert(NCH(n) > 1); - + elt = ast_for_expr(c, CHILD(n, 0)); if (!elt) return NULL; - + comps = ast_for_comprehension(c, CHILD(n, 1)); if (!comps) return NULL; @@ -1289,21 +1289,21 @@ ast_for_dictcomp(struct compiling *c, const node *n) { expr_ty key, value; asdl_seq *comps; - + assert(NCH(n) > 3); REQ(CHILD(n, 1), COLON); - + key = ast_for_expr(c, CHILD(n, 0)); if (!key) return NULL; value = ast_for_expr(c, CHILD(n, 2)); if (!value) return NULL; - + comps = ast_for_comprehension(c, CHILD(n, 3)); if (!comps) return NULL; - + return DictComp(key, value, comps, LINENO(n), n->n_col_offset, c->c_arena); } @@ -1338,7 +1338,7 @@ ast_for_atom(struct compiling *c, const node *n) */ node *ch = CHILD(n, 0); int bytesmode = 0; - + switch (TYPE(ch)) { case NAME: { /* All names start in Load context, but may later be @@ -1389,24 +1389,24 @@ ast_for_atom(struct compiling *c, const node *n) return Ellipsis(LINENO(n), n->n_col_offset, c->c_arena); case LPAR: /* some parenthesized expressions */ ch = CHILD(n, 1); - + if (TYPE(ch) == RPAR) return Tuple(NULL, Load, LINENO(n), n->n_col_offset, c->c_arena); - + if (TYPE(ch) == yield_expr) return ast_for_expr(c, ch); - /* testlist_comp: test ( comp_for | (',' test)* [','] ) */ + /* testlist_comp: test ( comp_for | (',' test)* [','] ) */ if ((NCH(ch) > 1) && (TYPE(CHILD(ch, 1)) == comp_for)) return ast_for_genexp(c, ch); return ast_for_testlist(c, ch); case LSQB: /* list (or list comprehension) */ ch = CHILD(n, 1); - + if (TYPE(ch) == RSQB) return List(NULL, Load, LINENO(n), n->n_col_offset, c->c_arena); - + REQ(ch, testlist_comp); if (NCH(ch) == 1 || TYPE(CHILD(ch, 1)) == COMMA) { asdl_seq *elts = seq_for_testlist(c, ch); @@ -1453,14 +1453,14 @@ ast_for_atom(struct compiling *c, const node *n) keys = asdl_seq_new(size, c->c_arena); if (!keys) return NULL; - + values = asdl_seq_new(size, c->c_arena); if (!values) return NULL; - + for (i = 0; i < NCH(ch); i += 4) { expr_ty expression; - + expression = ast_for_expr(c, CHILD(ch, i)); if (!expression) return NULL; @@ -1498,10 +1498,10 @@ ast_for_slice(struct compiling *c, const node *n) if (NCH(n) == 1 && TYPE(ch) == test) { /* 'step' variable hold no significance in terms of being used over other vars */ - step = ast_for_expr(c, ch); + step = ast_for_expr(c, ch); if (!step) return NULL; - + return Index(step, c->c_arena); } @@ -1551,7 +1551,7 @@ static expr_ty ast_for_binop(struct compiling *c, const node *n) { /* Must account for a sequence of expressions. - How should A op B op C by represented? + How should A op B op C by represented? BinOp(BinOp(A, op, B), op, C). */ @@ -1589,10 +1589,10 @@ ast_for_binop(struct compiling *c, const node *n) if (!tmp) return NULL; - tmp_result = BinOp(result, newoperator, tmp, + tmp_result = BinOp(result, newoperator, tmp, LINENO(next_oper), next_oper->n_col_offset, c->c_arena); - if (!tmp_result) + if (!tmp_result) return NULL; result = tmp_result; } @@ -1602,7 +1602,7 @@ ast_for_binop(struct compiling *c, const node *n) static expr_ty ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr) { - /* trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME + /* trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME subscriptlist: subscript (',' subscript)* [','] subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop] */ @@ -1633,7 +1633,7 @@ ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr) c->c_arena); } else { - /* The grammar is ambiguous here. The ambiguity is resolved + /* The grammar is ambiguous here. The ambiguity is resolved by treating the sequence as a tuple literal if there are no slice features. */ @@ -1786,7 +1786,7 @@ ast_for_expr(struct compiling *c, const node *n) /* handle the full range of simple expressions test: or_test ['if' or_test 'else' test] | lambdef test_nocond: or_test | lambdef_nocond - or_test: and_test ('or' and_test)* + or_test: and_test ('or' and_test)* and_test: not_test ('and' not_test)* not_test: 'not' not_test | comparison comparison: expr (comp_op expr)* @@ -1874,7 +1874,7 @@ ast_for_expr(struct compiling *c, const node *n) if (!expression) { return NULL; } - + asdl_seq_SET(ops, i / 2, newoperator); asdl_seq_SET(cmps, i / 2, expression); } @@ -1882,14 +1882,14 @@ ast_for_expr(struct compiling *c, const node *n) if (!expression) { return NULL; } - + return Compare(expression, ops, cmps, LINENO(n), n->n_col_offset, c->c_arena); } break; case star_expr: - return ast_for_starred(c, n); + return ast_for_starred(c, n); /* The next five cases all handle BinOps. The main body of code is the same in each case, but the switch turned inside out to reuse the code for each type of operator. @@ -1998,7 +1998,7 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func) if (!e) return NULL; asdl_seq_SET(args, nargs++, e); - } + } else if (TYPE(CHILD(ch, 1)) == comp_for) { e = ast_for_genexp(c, ch); if (!e) @@ -2010,7 +2010,7 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func) identifier key, tmp; int k; - /* CHILD(ch, 0) is test, but must be an identifier? */ + /* CHILD(ch, 0) is test, but must be an identifier? */ e = ast_for_expr(c, CHILD(ch, 0)); if (!e) return NULL; @@ -2026,8 +2026,8 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func) ast_error(CHILD(ch, 0), "keyword can't be an expression"); return NULL; } else if (forbidden_name(e->v.Name.id, ch, 1)) { - return NULL; - } + return NULL; + } key = e->v.Name.id; for (k = 0; k < nkeywords; k++) { tmp = ((keyword_ty)asdl_seq_GET(keywords, k))->arg; @@ -2090,7 +2090,7 @@ static stmt_ty ast_for_expr_stmt(struct compiling *c, const node *n) { REQ(n, expr_stmt); - /* expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) + /* expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) | ('=' (yield_expr|testlist))*) testlist_star_expr: (test|star_expr) (',' test|star_expr)* [','] augassign: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' @@ -2164,7 +2164,7 @@ ast_for_expr_stmt(struct compiling *c, const node *n) e = ast_for_testlist(c, ch); /* set context to assign */ - if (!e) + if (!e) return NULL; if (!set_context(c, e, Store, CHILD(n, i))) @@ -2211,7 +2211,7 @@ static stmt_ty ast_for_del_stmt(struct compiling *c, const node *n) { asdl_seq *expr_list; - + /* del_stmt: 'del' exprlist */ REQ(n, del_stmt); @@ -2349,7 +2349,7 @@ alias_for_import_name(struct compiling *c, const node *n, int store) int i; size_t len; char *s; - PyObject *uni; + PyObject *uni; len = 0; for (i = 0; i < NCH(n); i += 2) @@ -2370,13 +2370,13 @@ alias_for_import_name(struct compiling *c, const node *n, int store) } --s; *s = '\0'; - uni = PyUnicode_DecodeUTF8(PyBytes_AS_STRING(str), - PyBytes_GET_SIZE(str), - NULL); - Py_DECREF(str); - if (!uni) - return NULL; - str = uni; + uni = PyUnicode_DecodeUTF8(PyBytes_AS_STRING(str), + PyBytes_GET_SIZE(str), + NULL); + Py_DECREF(str); + if (!uni) + return NULL; + str = uni; PyUnicode_InternInPlace(&str); PyArena_AddPyObject(c->c_arena, str); return alias(str, NULL, c->c_arena); @@ -2433,7 +2433,7 @@ ast_for_import_stmt(struct compiling *c, const node *n) int idx, ndots = 0; alias_ty mod = NULL; identifier modname = NULL; - + /* Count the number of dots (for relative imports) and check for the optional module name */ for (idx = 1; idx < NCH(n); idx++) { @@ -2444,7 +2444,7 @@ ast_for_import_stmt(struct compiling *c, const node *n) idx++; break; } else if (TYPE(CHILD(n, idx)) == ELLIPSIS) { - /* three consecutive dots are tokenized as one ELLIPSIS */ + /* three consecutive dots are tokenized as one ELLIPSIS */ ndots += 3; continue; } else if (TYPE(CHILD(n, idx)) != DOT) { @@ -2571,7 +2571,7 @@ ast_for_assert_stmt(struct compiling *c, const node *n) expr2 = ast_for_expr(c, CHILD(n, 3)); if (!expr2) return NULL; - + return Assert(expr1, expr2, LINENO(n), n->n_col_offset, c->c_arena); } PyErr_Format(PyExc_SystemError, @@ -2598,7 +2598,7 @@ ast_for_suite(struct compiling *c, const node *n) if (TYPE(CHILD(n, 0)) == simple_stmt) { n = CHILD(n, 0); /* simple_stmt always ends with a NEWLINE, - and may have a trailing SEMI + and may have a trailing SEMI */ end = NCH(n) - 1; if (TYPE(CHILD(n, end - 1)) == SEMI) @@ -2663,10 +2663,10 @@ ast_for_if_stmt(struct compiling *c, const node *n) expression = ast_for_expr(c, CHILD(n, 1)); if (!expression) return NULL; - suite_seq = ast_for_suite(c, CHILD(n, 3)); + suite_seq = ast_for_suite(c, CHILD(n, 3)); if (!suite_seq) return NULL; - + return If(expression, suite_seq, NULL, LINENO(n), n->n_col_offset, c->c_arena); } @@ -2724,8 +2724,8 @@ ast_for_if_stmt(struct compiling *c, const node *n) if (!suite_seq2) return NULL; - asdl_seq_SET(orelse, 0, - If(expression, suite_seq, suite_seq2, + asdl_seq_SET(orelse, 0, + If(expression, suite_seq, suite_seq2, LINENO(CHILD(n, NCH(n) - 6)), CHILD(n, NCH(n) - 6)->n_col_offset, c->c_arena)); @@ -2746,7 +2746,7 @@ ast_for_if_stmt(struct compiling *c, const node *n) return NULL; asdl_seq_SET(newobj, 0, - If(expression, suite_seq, orelse, + If(expression, suite_seq, orelse, LINENO(CHILD(n, off)), CHILD(n, off)->n_col_offset, c->c_arena)); orelse = newobj; @@ -2943,7 +2943,7 @@ ast_for_try_stmt(struct compiling *c, const node *n) ast_error(n, "malformed 'try' statement"); return NULL; } - + if (n_except > 0) { int i; stmt_ty except_st; @@ -3160,8 +3160,8 @@ ast_for_stmt(struct compiling *c, const node *n) return ast_for_funcdef(c, ch, NULL); case classdef: return ast_for_classdef(c, ch, NULL); - case decorated: - return ast_for_decorated(c, ch); + case decorated: + return ast_for_decorated(c, ch); default: PyErr_Format(PyExc_SystemError, "unhandled small_stmt: TYPE=%d NCH=%d\n", @@ -3317,7 +3317,7 @@ parsestr(struct compiling *c, const node *n, int *bytesmode) if (quote == 'b' || quote == 'B') { quote = *++s; *bytesmode = 1; - } + } if (quote == 'r' || quote == 'R') { quote = *++s; rawmode = 1; @@ -3330,7 +3330,7 @@ parsestr(struct compiling *c, const node *n, int *bytesmode) s++; len = strlen(s); if (len > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, + PyErr_SetString(PyExc_OverflowError, "string to parse is too long"); return NULL; } @@ -3374,7 +3374,7 @@ parsestr(struct compiling *c, const node *n, int *bytesmode) return PyBytes_FromStringAndSize(s, len); } else if (strcmp(c->c_encoding, "utf-8") == 0) { return PyUnicode_FromStringAndSize(s, len); - } else { + } else { return PyUnicode_DecodeLatin1(s, len, NULL); } } diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 6b8600b0bd..97f7b96126 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -29,138 +29,138 @@ int Py_HasFileSystemDefaultEncoding = 0; int _Py_SetFileSystemEncoding(PyObject *s) { - PyObject *defenc, *codec; - if (!PyUnicode_Check(s)) { - PyErr_BadInternalCall(); - return -1; - } - defenc = _PyUnicode_AsDefaultEncodedString(s, NULL); - if (!defenc) - return -1; - codec = _PyCodec_Lookup(PyBytes_AsString(defenc)); - if (codec == NULL) - return -1; - Py_DECREF(codec); - if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) - /* A file system encoding was set at run-time */ - free((char*)Py_FileSystemDefaultEncoding); - Py_FileSystemDefaultEncoding = strdup(PyBytes_AsString(defenc)); - Py_HasFileSystemDefaultEncoding = 0; - return 0; + PyObject *defenc, *codec; + if (!PyUnicode_Check(s)) { + PyErr_BadInternalCall(); + return -1; + } + defenc = _PyUnicode_AsDefaultEncodedString(s, NULL); + if (!defenc) + return -1; + codec = _PyCodec_Lookup(PyBytes_AsString(defenc)); + if (codec == NULL) + return -1; + Py_DECREF(codec); + if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) + /* A file system encoding was set at run-time */ + free((char*)Py_FileSystemDefaultEncoding); + Py_FileSystemDefaultEncoding = strdup(PyBytes_AsString(defenc)); + Py_HasFileSystemDefaultEncoding = 0; + return 0; } static PyObject * builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) { - PyObject *func, *name, *bases, *mkw, *meta, *prep, *ns, *cell; - PyObject *cls = NULL; - Py_ssize_t nargs, nbases; - - assert(args != NULL); - if (!PyTuple_Check(args)) { - PyErr_SetString(PyExc_TypeError, - "__build_class__: args is not a tuple"); - return NULL; - } - nargs = PyTuple_GET_SIZE(args); - if (nargs < 2) { - PyErr_SetString(PyExc_TypeError, - "__build_class__: not enough arguments"); - return NULL; - } - func = PyTuple_GET_ITEM(args, 0); /* Better be callable */ - name = PyTuple_GET_ITEM(args, 1); - if (!PyUnicode_Check(name)) { - PyErr_SetString(PyExc_TypeError, - "__build_class__: name is not a string"); - return NULL; - } - bases = PyTuple_GetSlice(args, 2, nargs); - if (bases == NULL) - return NULL; - nbases = nargs - 2; - - if (kwds == NULL) { - meta = NULL; - mkw = NULL; + PyObject *func, *name, *bases, *mkw, *meta, *prep, *ns, *cell; + PyObject *cls = NULL; + Py_ssize_t nargs, nbases; + + assert(args != NULL); + if (!PyTuple_Check(args)) { + PyErr_SetString(PyExc_TypeError, + "__build_class__: args is not a tuple"); + return NULL; + } + nargs = PyTuple_GET_SIZE(args); + if (nargs < 2) { + PyErr_SetString(PyExc_TypeError, + "__build_class__: not enough arguments"); + return NULL; + } + func = PyTuple_GET_ITEM(args, 0); /* Better be callable */ + name = PyTuple_GET_ITEM(args, 1); + if (!PyUnicode_Check(name)) { + PyErr_SetString(PyExc_TypeError, + "__build_class__: name is not a string"); + return NULL; + } + bases = PyTuple_GetSlice(args, 2, nargs); + if (bases == NULL) + return NULL; + nbases = nargs - 2; + + if (kwds == NULL) { + meta = NULL; + mkw = NULL; + } + else { + mkw = PyDict_Copy(kwds); /* Don't modify kwds passed in! */ + if (mkw == NULL) { + Py_DECREF(bases); + return NULL; + } + meta = PyDict_GetItemString(mkw, "metaclass"); + if (meta != NULL) { + Py_INCREF(meta); + if (PyDict_DelItemString(mkw, "metaclass") < 0) { + Py_DECREF(meta); + Py_DECREF(mkw); + Py_DECREF(bases); + return NULL; + } + } + } + if (meta == NULL) { + if (PyTuple_GET_SIZE(bases) == 0) + meta = (PyObject *) (&PyType_Type); + else { + PyObject *base0 = PyTuple_GET_ITEM(bases, 0); + meta = (PyObject *) (base0->ob_type); + } + Py_INCREF(meta); + } + prep = PyObject_GetAttrString(meta, "__prepare__"); + if (prep == NULL) { + if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + ns = PyDict_New(); } - else { - mkw = PyDict_Copy(kwds); /* Don't modify kwds passed in! */ - if (mkw == NULL) { - Py_DECREF(bases); - return NULL; - } - meta = PyDict_GetItemString(mkw, "metaclass"); - if (meta != NULL) { - Py_INCREF(meta); - if (PyDict_DelItemString(mkw, "metaclass") < 0) { - Py_DECREF(meta); - Py_DECREF(mkw); - Py_DECREF(bases); - return NULL; - } - } - } - if (meta == NULL) { - if (PyTuple_GET_SIZE(bases) == 0) - meta = (PyObject *) (&PyType_Type); - else { - PyObject *base0 = PyTuple_GET_ITEM(bases, 0); - meta = (PyObject *) (base0->ob_type); - } - Py_INCREF(meta); - } - prep = PyObject_GetAttrString(meta, "__prepare__"); - if (prep == NULL) { - if (PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Clear(); - ns = PyDict_New(); - } - else { - Py_DECREF(meta); - Py_XDECREF(mkw); - Py_DECREF(bases); - return NULL; - } - } - else { - PyObject *pargs = PyTuple_Pack(2, name, bases); - if (pargs == NULL) { - Py_DECREF(prep); - Py_DECREF(meta); - Py_XDECREF(mkw); - Py_DECREF(bases); - return NULL; - } - ns = PyEval_CallObjectWithKeywords(prep, pargs, mkw); - Py_DECREF(pargs); - Py_DECREF(prep); - } - if (ns == NULL) { - Py_DECREF(meta); - Py_XDECREF(mkw); - Py_DECREF(bases); - return NULL; - } - cell = PyObject_CallFunctionObjArgs(func, ns, NULL); - if (cell != NULL) { - PyObject *margs; - margs = PyTuple_Pack(3, name, bases, ns); - if (margs != NULL) { - cls = PyEval_CallObjectWithKeywords(meta, margs, mkw); - Py_DECREF(margs); - } - if (cls != NULL && PyCell_Check(cell)) { - Py_INCREF(cls); - PyCell_SET(cell, cls); - } - Py_DECREF(cell); - } - Py_DECREF(ns); - Py_DECREF(meta); - Py_XDECREF(mkw); - Py_DECREF(bases); - return cls; + else { + Py_DECREF(meta); + Py_XDECREF(mkw); + Py_DECREF(bases); + return NULL; + } + } + else { + PyObject *pargs = PyTuple_Pack(2, name, bases); + if (pargs == NULL) { + Py_DECREF(prep); + Py_DECREF(meta); + Py_XDECREF(mkw); + Py_DECREF(bases); + return NULL; + } + ns = PyEval_CallObjectWithKeywords(prep, pargs, mkw); + Py_DECREF(pargs); + Py_DECREF(prep); + } + if (ns == NULL) { + Py_DECREF(meta); + Py_XDECREF(mkw); + Py_DECREF(bases); + return NULL; + } + cell = PyObject_CallFunctionObjArgs(func, ns, NULL); + if (cell != NULL) { + PyObject *margs; + margs = PyTuple_Pack(3, name, bases, ns); + if (margs != NULL) { + cls = PyEval_CallObjectWithKeywords(meta, margs, mkw); + Py_DECREF(margs); + } + if (cls != NULL && PyCell_Check(cell)) { + Py_INCREF(cls); + PyCell_SET(cell, cls); + } + Py_DECREF(cell); + } + Py_DECREF(ns); + Py_DECREF(meta); + Py_XDECREF(mkw); + Py_DECREF(bases); + return cls; } PyDoc_STRVAR(build_class_doc, @@ -171,19 +171,19 @@ Internal helper function used by the class statement."); 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); + 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, @@ -204,7 +204,7 @@ 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); + return PyNumber_Absolute(v); } PyDoc_STRVAR(abs_doc, @@ -215,38 +215,38 @@ Return the absolute value of the argument."); static PyObject * builtin_all(PyObject *self, PyObject *v) { - PyObject *it, *item; - PyObject *(*iternext)(PyObject *); - int cmp; - - it = PyObject_GetIter(v); - if (it == NULL) - return NULL; - iternext = *Py_TYPE(it)->tp_iternext; - - for (;;) { - item = iternext(it); - if (item == NULL) - break; - 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()) { - if (PyErr_ExceptionMatches(PyExc_StopIteration)) - PyErr_Clear(); - else - return NULL; - } - Py_RETURN_TRUE; + PyObject *it, *item; + PyObject *(*iternext)(PyObject *); + int cmp; + + it = PyObject_GetIter(v); + if (it == NULL) + return NULL; + iternext = *Py_TYPE(it)->tp_iternext; + + for (;;) { + item = iternext(it); + if (item == NULL) + break; + 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()) { + if (PyErr_ExceptionMatches(PyExc_StopIteration)) + PyErr_Clear(); + else + return NULL; + } + Py_RETURN_TRUE; } PyDoc_STRVAR(all_doc, @@ -257,38 +257,38 @@ 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; - PyObject *(*iternext)(PyObject *); - int cmp; - - it = PyObject_GetIter(v); - if (it == NULL) - return NULL; - iternext = *Py_TYPE(it)->tp_iternext; - - for (;;) { - item = iternext(it); - if (item == NULL) - break; - 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()) { - if (PyErr_ExceptionMatches(PyExc_StopIteration)) - PyErr_Clear(); - else - return NULL; - } - Py_RETURN_FALSE; + PyObject *it, *item; + PyObject *(*iternext)(PyObject *); + int cmp; + + it = PyObject_GetIter(v); + if (it == NULL) + return NULL; + iternext = *Py_TYPE(it)->tp_iternext; + + for (;;) { + item = iternext(it); + if (item == NULL) + break; + 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()) { + if (PyErr_ExceptionMatches(PyExc_StopIteration)) + PyErr_Clear(); + else + return NULL; + } + Py_RETURN_FALSE; } PyDoc_STRVAR(any_doc, @@ -299,7 +299,7 @@ Return True if bool(x) is True for any x in the iterable."); static PyObject * builtin_ascii(PyObject *self, PyObject *v) { - return PyObject_ASCII(v); + return PyObject_ASCII(v); } PyDoc_STRVAR(ascii_doc, @@ -314,7 +314,7 @@ to that returned by repr() in Python 2."); static PyObject * builtin_bin(PyObject *self, PyObject *v) { - return PyNumber_ToBase(v, 2); + return PyNumber_ToBase(v, 2); } PyDoc_STRVAR(bin_doc, @@ -324,90 +324,90 @@ Return the binary representation of an integer or long integer."); typedef struct { - PyObject_HEAD - PyObject *func; - PyObject *it; + PyObject_HEAD + PyObject *func; + PyObject *it; } filterobject; static PyObject * filter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - PyObject *func, *seq; - PyObject *it; - filterobject *lz; - - if (type == &PyFilter_Type && !_PyArg_NoKeywords("filter()", kwds)) - return NULL; - - if (!PyArg_UnpackTuple(args, "filter", 2, 2, &func, &seq)) - return NULL; - - /* Get iterator. */ - it = PyObject_GetIter(seq); - if (it == NULL) - return NULL; - - /* create filterobject structure */ - lz = (filterobject *)type->tp_alloc(type, 0); - if (lz == NULL) { - Py_DECREF(it); - return NULL; - } - Py_INCREF(func); - lz->func = func; - lz->it = it; - - return (PyObject *)lz; + PyObject *func, *seq; + PyObject *it; + filterobject *lz; + + if (type == &PyFilter_Type && !_PyArg_NoKeywords("filter()", kwds)) + return NULL; + + if (!PyArg_UnpackTuple(args, "filter", 2, 2, &func, &seq)) + return NULL; + + /* Get iterator. */ + it = PyObject_GetIter(seq); + if (it == NULL) + return NULL; + + /* create filterobject structure */ + lz = (filterobject *)type->tp_alloc(type, 0); + if (lz == NULL) { + Py_DECREF(it); + return NULL; + } + Py_INCREF(func); + lz->func = func; + lz->it = it; + + return (PyObject *)lz; } static void filter_dealloc(filterobject *lz) { - PyObject_GC_UnTrack(lz); - Py_XDECREF(lz->func); - Py_XDECREF(lz->it); - Py_TYPE(lz)->tp_free(lz); + PyObject_GC_UnTrack(lz); + Py_XDECREF(lz->func); + Py_XDECREF(lz->it); + Py_TYPE(lz)->tp_free(lz); } static int filter_traverse(filterobject *lz, visitproc visit, void *arg) { - Py_VISIT(lz->it); - Py_VISIT(lz->func); - return 0; + Py_VISIT(lz->it); + Py_VISIT(lz->func); + return 0; } static PyObject * filter_next(filterobject *lz) { - PyObject *item; - PyObject *it = lz->it; - long ok; - PyObject *(*iternext)(PyObject *); - - iternext = *Py_TYPE(it)->tp_iternext; - for (;;) { - item = iternext(it); - if (item == NULL) - return NULL; - - if (lz->func == Py_None || lz->func == (PyObject *)&PyBool_Type) { - ok = PyObject_IsTrue(item); - } else { - PyObject *good; - good = PyObject_CallFunctionObjArgs(lz->func, - item, NULL); - if (good == NULL) { - Py_DECREF(item); - return NULL; - } - ok = PyObject_IsTrue(good); - Py_DECREF(good); - } - if (ok) - return item; - Py_DECREF(item); - } + PyObject *item; + PyObject *it = lz->it; + long ok; + PyObject *(*iternext)(PyObject *); + + iternext = *Py_TYPE(it)->tp_iternext; + for (;;) { + item = iternext(it); + if (item == NULL) + return NULL; + + if (lz->func == Py_None || lz->func == (PyObject *)&PyBool_Type) { + ok = PyObject_IsTrue(item); + } else { + PyObject *good; + good = PyObject_CallFunctionObjArgs(lz->func, + item, NULL); + if (good == NULL) { + Py_DECREF(item); + return NULL; + } + ok = PyObject_IsTrue(good); + Py_DECREF(good); + } + if (ok) + return item; + Py_DECREF(item); + } } PyDoc_STRVAR(filter_doc, @@ -417,47 +417,47 @@ Return an iterator yielding those items of iterable for which function(item)\n\ is true. If function is None, return the items that are true."); PyTypeObject PyFilter_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "filter", /* tp_name */ - sizeof(filterobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)filter_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - filter_doc, /* tp_doc */ - (traverseproc)filter_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)filter_next, /* tp_iternext */ - 0, /* 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 */ - 0, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - filter_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "filter", /* tp_name */ + sizeof(filterobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)filter_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_BASETYPE, /* tp_flags */ + filter_doc, /* tp_doc */ + (traverseproc)filter_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)filter_next, /* tp_iternext */ + 0, /* 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 */ + 0, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + filter_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ }; @@ -468,7 +468,7 @@ builtin_format(PyObject *self, PyObject *args) PyObject *format_spec = NULL; if (!PyArg_ParseTuple(args, "O|U:format", &value, &format_spec)) - return NULL; + return NULL; return PyObject_Format(value, format_spec); } @@ -482,12 +482,12 @@ format_spec defaults to \"\""); static PyObject * builtin_chr(PyObject *self, PyObject *args) { - int x; + int x; - if (!PyArg_ParseTuple(args, "i:chr", &x)) - return NULL; + if (!PyArg_ParseTuple(args, "i:chr", &x)) + return NULL; - return PyUnicode_FromOrdinal(x); + return PyUnicode_FromOrdinal(x); } PyDoc_VAR(chr_doc) = PyDoc_STR( @@ -506,111 +506,111 @@ PyDoc_STR( static char * source_as_string(PyObject *cmd, char *funcname, char *what, PyCompilerFlags *cf) { - char *str; - Py_ssize_t size; - - if (PyUnicode_Check(cmd)) { - cf->cf_flags |= PyCF_IGNORE_COOKIE; - cmd = _PyUnicode_AsDefaultEncodedString(cmd, NULL); - if (cmd == NULL) - return NULL; - } - else if (!PyObject_CheckReadBuffer(cmd)) { - PyErr_Format(PyExc_TypeError, - "%s() arg 1 must be a %s object", - funcname, what); - return NULL; - } - if (PyObject_AsReadBuffer(cmd, (const void **)&str, &size) < 0) { - return NULL; - } - if (strlen(str) != size) { - PyErr_SetString(PyExc_TypeError, - "source code string cannot contain null bytes"); - return NULL; - } - return str; + char *str; + Py_ssize_t size; + + if (PyUnicode_Check(cmd)) { + cf->cf_flags |= PyCF_IGNORE_COOKIE; + cmd = _PyUnicode_AsDefaultEncodedString(cmd, NULL); + if (cmd == NULL) + return NULL; + } + else if (!PyObject_CheckReadBuffer(cmd)) { + PyErr_Format(PyExc_TypeError, + "%s() arg 1 must be a %s object", + funcname, what); + return NULL; + } + if (PyObject_AsReadBuffer(cmd, (const void **)&str, &size) < 0) { + return NULL; + } + if (strlen(str) != size) { + PyErr_SetString(PyExc_TypeError, + "source code string cannot contain null bytes"); + return NULL; + } + return str; } static PyObject * builtin_compile(PyObject *self, PyObject *args, PyObject *kwds) { - char *str; - char *filename; - char *startstr; - int mode = -1; - int dont_inherit = 0; - int supplied_flags = 0; - int is_ast; - PyCompilerFlags cf; - PyObject *cmd; - static char *kwlist[] = {"source", "filename", "mode", "flags", - "dont_inherit", NULL}; - int start[] = {Py_file_input, Py_eval_input, Py_single_input}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oss|ii:compile", - kwlist, &cmd, &filename, &startstr, - &supplied_flags, &dont_inherit)) - return NULL; - - cf.cf_flags = supplied_flags | PyCF_SOURCE_IS_UTF8; - - if (supplied_flags & - ~(PyCF_MASK | PyCF_MASK_OBSOLETE | PyCF_DONT_IMPLY_DEDENT | PyCF_ONLY_AST)) - { - PyErr_SetString(PyExc_ValueError, - "compile(): unrecognised flags"); - return NULL; - } - /* XXX Warn if (supplied_flags & PyCF_MASK_OBSOLETE) != 0? */ - - if (!dont_inherit) { - PyEval_MergeCompilerFlags(&cf); - } - - if (strcmp(startstr, "exec") == 0) - mode = 0; - else if (strcmp(startstr, "eval") == 0) - mode = 1; - else if (strcmp(startstr, "single") == 0) - mode = 2; - else { - PyErr_SetString(PyExc_ValueError, - "compile() arg 3 must be 'exec', 'eval' or 'single'"); - return NULL; - } - - is_ast = PyAST_Check(cmd); - if (is_ast == -1) - return NULL; - if (is_ast) { - PyObject *result; - if (supplied_flags & PyCF_ONLY_AST) { - Py_INCREF(cmd); - result = cmd; - } - else { - PyArena *arena; - mod_ty mod; - - arena = PyArena_New(); - mod = PyAST_obj2mod(cmd, arena, mode); - if (mod == NULL) { - PyArena_Free(arena); - return NULL; - } - result = (PyObject*)PyAST_Compile(mod, filename, - &cf, arena); - PyArena_Free(arena); - } - return result; - } - - str = source_as_string(cmd, "compile", "string, bytes, AST or code", &cf); - if (str == NULL) - return NULL; - - return Py_CompileStringFlags(str, filename, start[mode], &cf); + char *str; + char *filename; + char *startstr; + int mode = -1; + int dont_inherit = 0; + int supplied_flags = 0; + int is_ast; + PyCompilerFlags cf; + PyObject *cmd; + static char *kwlist[] = {"source", "filename", "mode", "flags", + "dont_inherit", NULL}; + int start[] = {Py_file_input, Py_eval_input, Py_single_input}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oss|ii:compile", + kwlist, &cmd, &filename, &startstr, + &supplied_flags, &dont_inherit)) + return NULL; + + cf.cf_flags = supplied_flags | PyCF_SOURCE_IS_UTF8; + + if (supplied_flags & + ~(PyCF_MASK | PyCF_MASK_OBSOLETE | PyCF_DONT_IMPLY_DEDENT | PyCF_ONLY_AST)) + { + PyErr_SetString(PyExc_ValueError, + "compile(): unrecognised flags"); + return NULL; + } + /* XXX Warn if (supplied_flags & PyCF_MASK_OBSOLETE) != 0? */ + + if (!dont_inherit) { + PyEval_MergeCompilerFlags(&cf); + } + + if (strcmp(startstr, "exec") == 0) + mode = 0; + else if (strcmp(startstr, "eval") == 0) + mode = 1; + else if (strcmp(startstr, "single") == 0) + mode = 2; + else { + PyErr_SetString(PyExc_ValueError, + "compile() arg 3 must be 'exec', 'eval' or 'single'"); + return NULL; + } + + is_ast = PyAST_Check(cmd); + if (is_ast == -1) + return NULL; + if (is_ast) { + PyObject *result; + if (supplied_flags & PyCF_ONLY_AST) { + Py_INCREF(cmd); + result = cmd; + } + else { + PyArena *arena; + mod_ty mod; + + arena = PyArena_New(); + mod = PyAST_obj2mod(cmd, arena, mode); + if (mod == NULL) { + PyArena_Free(arena); + return NULL; + } + result = (PyObject*)PyAST_Compile(mod, filename, + &cf, arena); + PyArena_Free(arena); + } + return result; + } + + str = source_as_string(cmd, "compile", "string, bytes, AST or code", &cf); + if (str == NULL) + return NULL; + + return Py_CompileStringFlags(str, filename, start[mode], &cf); } PyDoc_STRVAR(compile_doc, @@ -631,11 +631,11 @@ in addition to any features explicitly specified."); static PyObject * builtin_dir(PyObject *self, PyObject *args) { - PyObject *arg = NULL; + PyObject *arg = NULL; - if (!PyArg_UnpackTuple(args, "dir", 0, 1, &arg)) - return NULL; - return PyObject_Dir(arg); + if (!PyArg_UnpackTuple(args, "dir", 0, 1, &arg)) + return NULL; + return PyObject_Dir(arg); } PyDoc_STRVAR(dir_doc, @@ -655,11 +655,11 @@ PyDoc_STRVAR(dir_doc, static PyObject * builtin_divmod(PyObject *self, PyObject *args) { - PyObject *v, *w; + PyObject *v, *w; - if (!PyArg_UnpackTuple(args, "divmod", 2, 2, &v, &w)) - return NULL; - return PyNumber_Divmod(v, w); + if (!PyArg_UnpackTuple(args, "divmod", 2, 2, &v, &w)) + return NULL; + return PyNumber_Divmod(v, w); } PyDoc_STRVAR(divmod_doc, @@ -671,65 +671,65 @@ 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); - } - - cf.cf_flags = PyCF_SOURCE_IS_UTF8; - str = source_as_string(cmd, "eval", "string, bytes or code", &cf); - if (str == NULL) - 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; + 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); + } + + cf.cf_flags = PyCF_SOURCE_IS_UTF8; + str = source_as_string(cmd, "eval", "string, bytes or code", &cf); + if (str == NULL) + 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, @@ -745,72 +745,72 @@ If only globals is given, locals defaults to it.\n"); static PyObject * builtin_exec(PyObject *self, PyObject *args) { - PyObject *v; - PyObject *prog, *globals = Py_None, *locals = Py_None; - int plain = 0; - - if (!PyArg_UnpackTuple(args, "exec", 1, 3, &prog, &globals, &locals)) - return NULL; - - 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 NULL; - } - } - else if (locals == Py_None) - locals = globals; - - if (!PyDict_Check(globals)) { - PyErr_Format(PyExc_TypeError, "exec() arg 2 must be a dict, not %.100s", - globals->ob_type->tp_name); - return NULL; - } - if (!PyMapping_Check(locals)) { - PyErr_Format(PyExc_TypeError, - "arg 3 must be a mapping or None, not %.100s", - locals->ob_type->tp_name); - return NULL; - } - if (PyDict_GetItemString(globals, "__builtins__") == NULL) { - if (PyDict_SetItemString(globals, "__builtins__", - PyEval_GetBuiltins()) != 0) - return NULL; - } - - 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 NULL; - } - v = PyEval_EvalCode((PyCodeObject *) prog, globals, locals); - } - else { - char *str; - PyCompilerFlags cf; - cf.cf_flags = PyCF_SOURCE_IS_UTF8; - str = source_as_string(prog, "exec", - "string, bytes or code", &cf); - if (str == NULL) - return NULL; - if (PyEval_MergeCompilerFlags(&cf)) - v = PyRun_StringFlags(str, Py_file_input, globals, - locals, &cf); - else - v = PyRun_String(str, Py_file_input, globals, locals); - } - if (v == NULL) - return NULL; - Py_DECREF(v); - Py_RETURN_NONE; + PyObject *v; + PyObject *prog, *globals = Py_None, *locals = Py_None; + int plain = 0; + + if (!PyArg_UnpackTuple(args, "exec", 1, 3, &prog, &globals, &locals)) + return NULL; + + 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 NULL; + } + } + else if (locals == Py_None) + locals = globals; + + if (!PyDict_Check(globals)) { + PyErr_Format(PyExc_TypeError, "exec() arg 2 must be a dict, not %.100s", + globals->ob_type->tp_name); + return NULL; + } + if (!PyMapping_Check(locals)) { + PyErr_Format(PyExc_TypeError, + "arg 3 must be a mapping or None, not %.100s", + locals->ob_type->tp_name); + return NULL; + } + if (PyDict_GetItemString(globals, "__builtins__") == NULL) { + if (PyDict_SetItemString(globals, "__builtins__", + PyEval_GetBuiltins()) != 0) + return NULL; + } + + 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 NULL; + } + v = PyEval_EvalCode((PyCodeObject *) prog, globals, locals); + } + else { + char *str; + PyCompilerFlags cf; + cf.cf_flags = PyCF_SOURCE_IS_UTF8; + str = source_as_string(prog, "exec", + "string, bytes or code", &cf); + if (str == NULL) + return NULL; + if (PyEval_MergeCompilerFlags(&cf)) + v = PyRun_StringFlags(str, Py_file_input, globals, + locals, &cf); + else + v = PyRun_String(str, Py_file_input, globals, locals); + } + if (v == NULL) + return NULL; + Py_DECREF(v); + Py_RETURN_NONE; } PyDoc_STRVAR(exec_doc, @@ -825,26 +825,26 @@ 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; - - if (!PyUnicode_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; + PyObject *v, *result, *dflt = NULL; + PyObject *name; + + if (!PyArg_UnpackTuple(args, "getattr", 2, 3, &v, &name, &dflt)) + return NULL; + + if (!PyUnicode_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, @@ -858,11 +858,11 @@ exist; without it, an exception is raised in that case."); static PyObject * builtin_globals(PyObject *self) { - PyObject *d; + PyObject *d; - d = PyEval_GetGlobals(); - Py_XINCREF(d); - return d; + d = PyEval_GetGlobals(); + Py_XINCREF(d); + return d; } PyDoc_STRVAR(globals_doc, @@ -874,29 +874,29 @@ 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; - if (!PyUnicode_Check(name)) { - PyErr_SetString(PyExc_TypeError, - "hasattr(): attribute name must be string"); - return NULL; - } - v = PyObject_GetAttr(v, name); - if (v == NULL) { - if (!PyErr_ExceptionMatches(PyExc_Exception)) - return NULL; - else { - PyErr_Clear(); - Py_INCREF(Py_False); - return Py_False; - } - } - Py_DECREF(v); - Py_INCREF(Py_True); - return Py_True; + PyObject *v; + PyObject *name; + + if (!PyArg_UnpackTuple(args, "hasattr", 2, 2, &v, &name)) + return NULL; + if (!PyUnicode_Check(name)) { + PyErr_SetString(PyExc_TypeError, + "hasattr(): attribute name must be string"); + return NULL; + } + v = PyObject_GetAttr(v, name); + if (v == NULL) { + if (!PyErr_ExceptionMatches(PyExc_Exception)) + return NULL; + else { + PyErr_Clear(); + Py_INCREF(Py_False); + return Py_False; + } + } + Py_DECREF(v); + Py_INCREF(Py_True); + return Py_True; } PyDoc_STRVAR(hasattr_doc, @@ -909,7 +909,7 @@ Return whether the object has an attribute with the given name.\n\ static PyObject * builtin_id(PyObject *self, PyObject *v) { - return PyLong_FromVoidPtr(v); + return PyLong_FromVoidPtr(v); } PyDoc_STRVAR(id_doc, @@ -922,181 +922,181 @@ simultaneously existing objects. (Hint: it's the object's memory address.)"); /* map object ************************************************************/ typedef struct { - PyObject_HEAD - PyObject *iters; - PyObject *func; + PyObject_HEAD + PyObject *iters; + PyObject *func; } mapobject; static PyObject * map_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - PyObject *it, *iters, *func; - mapobject *lz; - Py_ssize_t numargs, i; - - if (type == &PyMap_Type && !_PyArg_NoKeywords("map()", kwds)) - return NULL; - - numargs = PyTuple_Size(args); - if (numargs < 2) { - PyErr_SetString(PyExc_TypeError, - "map() must have at least two arguments."); - return NULL; - } - - iters = PyTuple_New(numargs-1); - if (iters == NULL) - return NULL; - - for (i=1 ; itp_alloc(type, 0); - if (lz == NULL) { - Py_DECREF(iters); - return NULL; - } - lz->iters = iters; - func = PyTuple_GET_ITEM(args, 0); - Py_INCREF(func); - lz->func = func; - - return (PyObject *)lz; + PyObject *it, *iters, *func; + mapobject *lz; + Py_ssize_t numargs, i; + + if (type == &PyMap_Type && !_PyArg_NoKeywords("map()", kwds)) + return NULL; + + numargs = PyTuple_Size(args); + if (numargs < 2) { + PyErr_SetString(PyExc_TypeError, + "map() must have at least two arguments."); + return NULL; + } + + iters = PyTuple_New(numargs-1); + if (iters == NULL) + return NULL; + + for (i=1 ; itp_alloc(type, 0); + if (lz == NULL) { + Py_DECREF(iters); + return NULL; + } + lz->iters = iters; + func = PyTuple_GET_ITEM(args, 0); + Py_INCREF(func); + lz->func = func; + + return (PyObject *)lz; } static void map_dealloc(mapobject *lz) { - PyObject_GC_UnTrack(lz); - Py_XDECREF(lz->iters); - Py_XDECREF(lz->func); - Py_TYPE(lz)->tp_free(lz); + PyObject_GC_UnTrack(lz); + Py_XDECREF(lz->iters); + Py_XDECREF(lz->func); + Py_TYPE(lz)->tp_free(lz); } static int map_traverse(mapobject *lz, visitproc visit, void *arg) { - Py_VISIT(lz->iters); - Py_VISIT(lz->func); - return 0; + Py_VISIT(lz->iters); + Py_VISIT(lz->func); + return 0; } static PyObject * map_next(mapobject *lz) { - PyObject *val; - PyObject *argtuple; - PyObject *result; - Py_ssize_t numargs, i; - - numargs = PyTuple_Size(lz->iters); - argtuple = PyTuple_New(numargs); - if (argtuple == NULL) - return NULL; - - for (i=0 ; iiters, i)); - if (val == NULL) { - Py_DECREF(argtuple); - return NULL; - } - PyTuple_SET_ITEM(argtuple, i, val); - } - result = PyObject_Call(lz->func, argtuple, NULL); - Py_DECREF(argtuple); - return result; + PyObject *val; + PyObject *argtuple; + PyObject *result; + Py_ssize_t numargs, i; + + numargs = PyTuple_Size(lz->iters); + argtuple = PyTuple_New(numargs); + if (argtuple == NULL) + return NULL; + + for (i=0 ; iiters, i)); + if (val == NULL) { + Py_DECREF(argtuple); + return NULL; + } + PyTuple_SET_ITEM(argtuple, i, val); + } + result = PyObject_Call(lz->func, argtuple, NULL); + Py_DECREF(argtuple); + return result; } PyDoc_STRVAR(map_doc, "map(func, *iterables) --> map object\n\ \n\ Make an iterator that computes the function using arguments from\n\ -each of the iterables. Stops when the shortest iterable is exhausted."); +each of the iterables. Stops when the shortest iterable is exhausted."); PyTypeObject PyMap_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "map", /* tp_name */ - sizeof(mapobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)map_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - map_doc, /* tp_doc */ - (traverseproc)map_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)map_next, /* tp_iternext */ - 0, /* 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 */ - 0, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - map_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "map", /* tp_name */ + sizeof(mapobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)map_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_BASETYPE, /* tp_flags */ + map_doc, /* tp_doc */ + (traverseproc)map_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)map_next, /* tp_iternext */ + 0, /* 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 */ + 0, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + map_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ }; static PyObject * builtin_next(PyObject *self, PyObject *args) { - PyObject *it, *res; - PyObject *def = NULL; - - if (!PyArg_UnpackTuple(args, "next", 1, 2, &it, &def)) - return NULL; - if (!PyIter_Check(it)) { - PyErr_Format(PyExc_TypeError, - "%.200s object is not an iterator", - it->ob_type->tp_name); - return NULL; - } - - res = (*it->ob_type->tp_iternext)(it); - if (res != NULL) { - return res; - } else if (def != NULL) { - if (PyErr_Occurred()) { - if(!PyErr_ExceptionMatches(PyExc_StopIteration)) - return NULL; - PyErr_Clear(); - } - Py_INCREF(def); - return def; - } else if (PyErr_Occurred()) { - return NULL; - } else { - PyErr_SetNone(PyExc_StopIteration); - return NULL; - } + PyObject *it, *res; + PyObject *def = NULL; + + if (!PyArg_UnpackTuple(args, "next", 1, 2, &it, &def)) + return NULL; + if (!PyIter_Check(it)) { + PyErr_Format(PyExc_TypeError, + "%.200s object is not an iterator", + it->ob_type->tp_name); + return NULL; + } + + res = (*it->ob_type->tp_iternext)(it); + if (res != NULL) { + return res; + } else if (def != NULL) { + if (PyErr_Occurred()) { + if(!PyErr_ExceptionMatches(PyExc_StopIteration)) + return NULL; + PyErr_Clear(); + } + Py_INCREF(def); + return def; + } else if (PyErr_Occurred()) { + return NULL; + } else { + PyErr_SetNone(PyExc_StopIteration); + return NULL; + } } PyDoc_STRVAR(next_doc, @@ -1109,16 +1109,16 @@ is exhausted, it is returned instead of raising StopIteration."); 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; + 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, @@ -1131,15 +1131,15 @@ Set a named attribute on an object; setattr(x, 'y', v) is equivalent to\n\ 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; + 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, @@ -1152,12 +1152,12 @@ Delete a named attribute on an object; delattr(x, 'y') is equivalent to\n\ static PyObject * builtin_hash(PyObject *self, PyObject *v) { - long x; + long x; - x = PyObject_Hash(v); - if (x == -1) - return NULL; - return PyLong_FromLong(x); + x = PyObject_Hash(v); + if (x == -1) + return NULL; + return PyLong_FromLong(x); } PyDoc_STRVAR(hash_doc, @@ -1170,7 +1170,7 @@ the same hash value. The reverse is not necessarily true, but likely."); static PyObject * builtin_hex(PyObject *self, PyObject *v) { - return PyNumber_ToBase(v, 16); + return PyNumber_ToBase(v, 16); } PyDoc_STRVAR(hex_doc, @@ -1182,18 +1182,18 @@ Return the hexadecimal representation of an integer or long integer."); 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); + 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, @@ -1208,12 +1208,12 @@ 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; + Py_ssize_t res; - res = PyObject_Size(v); - if (res < 0 && PyErr_Occurred()) - return NULL; - return PyLong_FromSsize_t(res); + res = PyObject_Size(v); + if (res < 0 && PyErr_Occurred()) + return NULL; + return PyLong_FromSsize_t(res); } PyDoc_STRVAR(len_doc, @@ -1225,11 +1225,11 @@ Return the number of items of a sequence or mapping."); static PyObject * builtin_locals(PyObject *self) { - PyObject *d; + PyObject *d; - d = PyEval_GetLocals(); - Py_XINCREF(d); - return d; + d = PyEval_GetLocals(); + Py_XINCREF(d); + return d; } PyDoc_STRVAR(locals_doc, @@ -1241,96 +1241,96 @@ 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; - } - Py_INCREF(keyfunc); - } - - it = PyObject_GetIter(v); - if (it == NULL) { - Py_XDECREF(keyfunc); - 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); - Py_XDECREF(keyfunc); - return maxitem; + 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; + } + Py_INCREF(keyfunc); + } + + it = PyObject_GetIter(v); + if (it == NULL) { + Py_XDECREF(keyfunc); + 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); + Py_XDECREF(keyfunc); + return maxitem; Fail_it_item_and_val: - Py_DECREF(val); + Py_DECREF(val); Fail_it_item: - Py_DECREF(item); + Py_DECREF(item); Fail_it: - Py_XDECREF(maxval); - Py_XDECREF(maxitem); - Py_DECREF(it); - Py_XDECREF(keyfunc); - return NULL; + Py_XDECREF(maxval); + Py_XDECREF(maxitem); + Py_DECREF(it); + Py_XDECREF(keyfunc); + return NULL; } static PyObject * builtin_min(PyObject *self, PyObject *args, PyObject *kwds) { - return min_max(args, kwds, Py_LT); + return min_max(args, kwds, Py_LT); } PyDoc_STRVAR(min_doc, @@ -1344,7 +1344,7 @@ 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); + return min_max(args, kwds, Py_GT); } PyDoc_STRVAR(max_doc, @@ -1358,7 +1358,7 @@ With two or more arguments, return the largest argument."); static PyObject * builtin_oct(PyObject *self, PyObject *v) { - return PyNumber_ToBase(v, 8); + return PyNumber_ToBase(v, 8); } PyDoc_STRVAR(oct_doc, @@ -1370,56 +1370,56 @@ Return the octal representation of an integer or long integer."); static PyObject * builtin_ord(PyObject *self, PyObject* obj) { - long ord; - Py_ssize_t size; - - if (PyBytes_Check(obj)) { - size = PyBytes_GET_SIZE(obj); - if (size == 1) { - ord = (long)((unsigned char)*PyBytes_AS_STRING(obj)); - return PyLong_FromLong(ord); - } - } - else if (PyUnicode_Check(obj)) { - size = PyUnicode_GET_SIZE(obj); - if (size == 1) { - ord = (long)*PyUnicode_AS_UNICODE(obj); - return PyLong_FromLong(ord); - } + long ord; + Py_ssize_t size; + + if (PyBytes_Check(obj)) { + size = PyBytes_GET_SIZE(obj); + if (size == 1) { + ord = (long)((unsigned char)*PyBytes_AS_STRING(obj)); + return PyLong_FromLong(ord); + } + } + else if (PyUnicode_Check(obj)) { + size = PyUnicode_GET_SIZE(obj); + if (size == 1) { + ord = (long)*PyUnicode_AS_UNICODE(obj); + return PyLong_FromLong(ord); + } #ifndef Py_UNICODE_WIDE - if (size == 2) { - /* Decode a valid surrogate pair */ - int c0 = PyUnicode_AS_UNICODE(obj)[0]; - int c1 = PyUnicode_AS_UNICODE(obj)[1]; - if (0xD800 <= c0 && c0 <= 0xDBFF && - 0xDC00 <= c1 && c1 <= 0xDFFF) { - ord = ((((c0 & 0x03FF) << 10) | (c1 & 0x03FF)) + - 0x00010000); - return PyLong_FromLong(ord); - } - } + if (size == 2) { + /* Decode a valid surrogate pair */ + int c0 = PyUnicode_AS_UNICODE(obj)[0]; + int c1 = PyUnicode_AS_UNICODE(obj)[1]; + if (0xD800 <= c0 && c0 <= 0xDBFF && + 0xDC00 <= c1 && c1 <= 0xDFFF) { + ord = ((((c0 & 0x03FF) << 10) | (c1 & 0x03FF)) + + 0x00010000); + return PyLong_FromLong(ord); + } + } #endif - } - else if (PyByteArray_Check(obj)) { - /* XXX Hopefully this is temporary */ - size = PyByteArray_GET_SIZE(obj); - if (size == 1) { - ord = (long)((unsigned char)*PyByteArray_AS_STRING(obj)); - return PyLong_FromLong(ord); - } - } - 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; + } + else if (PyByteArray_Check(obj)) { + /* XXX Hopefully this is temporary */ + size = PyByteArray_GET_SIZE(obj); + if (size == 1) { + ord = (long)((unsigned char)*PyByteArray_AS_STRING(obj)); + return PyLong_FromLong(ord); + } + } + 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_VAR(ord_doc) = PyDoc_STR( @@ -1438,11 +1438,11 @@ PyDoc_STR( static PyObject * builtin_pow(PyObject *self, PyObject *args) { - PyObject *v, *w, *z = Py_None; + PyObject *v, *w, *z = Py_None; - if (!PyArg_UnpackTuple(args, "pow", 2, 3, &v, &w, &z)) - return NULL; - return PyNumber_Power(v, w, z); + if (!PyArg_UnpackTuple(args, "pow", 2, 3, &v, &w, &z)) + return NULL; + return PyNumber_Power(v, w, z); } PyDoc_STRVAR(pow_doc, @@ -1456,68 +1456,68 @@ equivalent to (x**y) % z, but may be more efficient (e.g. for longs)."); static PyObject * builtin_print(PyObject *self, PyObject *args, PyObject *kwds) { - static char *kwlist[] = {"sep", "end", "file", 0}; - static PyObject *dummy_args; - PyObject *sep = NULL, *end = NULL, *file = NULL; - int i, err; - - if (dummy_args == NULL) { - if (!(dummy_args = PyTuple_New(0))) - return NULL; - } - if (!PyArg_ParseTupleAndKeywords(dummy_args, kwds, "|OOO:print", - kwlist, &sep, &end, &file)) - return NULL; - if (file == NULL || file == Py_None) { - file = PySys_GetObject("stdout"); - /* sys.stdout may be None when FILE* stdout isn't connected */ - if (file == Py_None) - Py_RETURN_NONE; - } - - if (sep == Py_None) { - sep = NULL; - } - else if (sep && !PyUnicode_Check(sep)) { - PyErr_Format(PyExc_TypeError, - "sep must be None or a string, not %.200s", - sep->ob_type->tp_name); - return NULL; - } - if (end == Py_None) { - end = NULL; - } - else if (end && !PyUnicode_Check(end)) { - PyErr_Format(PyExc_TypeError, - "end must be None or a string, not %.200s", - end->ob_type->tp_name); - return NULL; - } - - for (i = 0; i < PyTuple_Size(args); i++) { - if (i > 0) { - if (sep == NULL) - err = PyFile_WriteString(" ", file); - else - err = PyFile_WriteObject(sep, file, - Py_PRINT_RAW); - if (err) - return NULL; - } - err = PyFile_WriteObject(PyTuple_GetItem(args, i), file, - Py_PRINT_RAW); - if (err) - return NULL; - } - - if (end == NULL) - err = PyFile_WriteString("\n", file); - else - err = PyFile_WriteObject(end, file, Py_PRINT_RAW); - if (err) - return NULL; - - Py_RETURN_NONE; + static char *kwlist[] = {"sep", "end", "file", 0}; + static PyObject *dummy_args; + PyObject *sep = NULL, *end = NULL, *file = NULL; + int i, err; + + if (dummy_args == NULL) { + if (!(dummy_args = PyTuple_New(0))) + return NULL; + } + if (!PyArg_ParseTupleAndKeywords(dummy_args, kwds, "|OOO:print", + kwlist, &sep, &end, &file)) + return NULL; + if (file == NULL || file == Py_None) { + file = PySys_GetObject("stdout"); + /* sys.stdout may be None when FILE* stdout isn't connected */ + if (file == Py_None) + Py_RETURN_NONE; + } + + if (sep == Py_None) { + sep = NULL; + } + else if (sep && !PyUnicode_Check(sep)) { + PyErr_Format(PyExc_TypeError, + "sep must be None or a string, not %.200s", + sep->ob_type->tp_name); + return NULL; + } + if (end == Py_None) { + end = NULL; + } + else if (end && !PyUnicode_Check(end)) { + PyErr_Format(PyExc_TypeError, + "end must be None or a string, not %.200s", + end->ob_type->tp_name); + return NULL; + } + + for (i = 0; i < PyTuple_Size(args); i++) { + if (i > 0) { + if (sep == NULL) + err = PyFile_WriteString(" ", file); + else + err = PyFile_WriteObject(sep, file, + Py_PRINT_RAW); + if (err) + return NULL; + } + err = PyFile_WriteObject(PyTuple_GetItem(args, i), file, + Py_PRINT_RAW); + if (err) + return NULL; + } + + if (end == NULL) + err = PyFile_WriteString("\n", file); + else + err = PyFile_WriteObject(end, file, Py_PRINT_RAW); + if (err) + return NULL; + + Py_RETURN_NONE; } PyDoc_STRVAR(print_doc, @@ -1533,164 +1533,164 @@ end: string appended after the last value, default a newline."); static PyObject * builtin_input(PyObject *self, PyObject *args) { - PyObject *promptarg = NULL; - PyObject *fin = PySys_GetObject("stdin"); - PyObject *fout = PySys_GetObject("stdout"); - PyObject *ferr = PySys_GetObject("stderr"); - PyObject *tmp; - long fd; - int tty; - - /* Parse arguments */ - if (!PyArg_UnpackTuple(args, "input", 0, 1, &promptarg)) - return NULL; - - /* Check that stdin/out/err are intact */ - if (fin == NULL || fin == Py_None) { - PyErr_SetString(PyExc_RuntimeError, - "input(): lost sys.stdin"); - return NULL; - } - if (fout == NULL || fout == Py_None) { - PyErr_SetString(PyExc_RuntimeError, - "input(): lost sys.stdout"); - return NULL; - } - if (ferr == NULL || ferr == Py_None) { - PyErr_SetString(PyExc_RuntimeError, - "input(): lost sys.stderr"); - return NULL; - } - - /* First of all, flush stderr */ - tmp = PyObject_CallMethod(ferr, "flush", ""); - if (tmp == NULL) - PyErr_Clear(); - else - Py_DECREF(tmp); - - /* We should only use (GNU) readline if Python's sys.stdin and - sys.stdout are the same as C's stdin and stdout, because we - need to pass it those. */ - tmp = PyObject_CallMethod(fin, "fileno", ""); - if (tmp == NULL) { - PyErr_Clear(); - tty = 0; - } - else { - fd = PyLong_AsLong(tmp); - Py_DECREF(tmp); - if (fd < 0 && PyErr_Occurred()) - return NULL; - tty = fd == fileno(stdin) && isatty(fd); - } - if (tty) { - tmp = PyObject_CallMethod(fout, "fileno", ""); - if (tmp == NULL) - PyErr_Clear(); - else { - fd = PyLong_AsLong(tmp); - Py_DECREF(tmp); - if (fd < 0 && PyErr_Occurred()) - return NULL; - tty = fd == fileno(stdout) && isatty(fd); - } - } - - /* If we're interactive, use (GNU) readline */ - if (tty) { - PyObject *po; - char *prompt; - char *s; - PyObject *stdin_encoding; - PyObject *result; - - stdin_encoding = PyObject_GetAttrString(fin, "encoding"); - if (!stdin_encoding) - /* stdin is a text stream, so it must have an - encoding. */ - return NULL; - tmp = PyObject_CallMethod(fout, "flush", ""); - if (tmp == NULL) - PyErr_Clear(); - else - Py_DECREF(tmp); - if (promptarg != NULL) { - PyObject *stringpo; - PyObject *stdout_encoding; - stdout_encoding = PyObject_GetAttrString(fout, - "encoding"); - if (stdout_encoding == NULL) { - Py_DECREF(stdin_encoding); - return NULL; - } - stringpo = PyObject_Str(promptarg); - if (stringpo == NULL) { - Py_DECREF(stdin_encoding); - Py_DECREF(stdout_encoding); - return NULL; - } - po = PyUnicode_AsEncodedString(stringpo, - _PyUnicode_AsString(stdout_encoding), NULL); - Py_DECREF(stdout_encoding); - Py_DECREF(stringpo); - if (po == NULL) { - Py_DECREF(stdin_encoding); - return NULL; - } - prompt = PyBytes_AsString(po); - if (prompt == NULL) { - Py_DECREF(stdin_encoding); - Py_DECREF(po); - return NULL; - } - } - else { - po = NULL; - prompt = ""; - } - s = PyOS_Readline(stdin, stdout, prompt); - Py_XDECREF(po); - if (s == NULL) { - if (!PyErr_Occurred()) - PyErr_SetNone(PyExc_KeyboardInterrupt); - Py_DECREF(stdin_encoding); - 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, - "input: input too long"); - result = NULL; - } - else { - result = PyUnicode_Decode - (s, len-1, - _PyUnicode_AsString(stdin_encoding), - NULL); - } - } - Py_DECREF(stdin_encoding); - PyMem_FREE(s); - return result; - } - - /* Fallback if we're not interactive */ - if (promptarg != NULL) { - if (PyFile_WriteObject(promptarg, fout, Py_PRINT_RAW) != 0) - return NULL; - } - tmp = PyObject_CallMethod(fout, "flush", ""); - if (tmp == NULL) - PyErr_Clear(); - else - Py_DECREF(tmp); - return PyFile_GetLine(fin, -1); + PyObject *promptarg = NULL; + PyObject *fin = PySys_GetObject("stdin"); + PyObject *fout = PySys_GetObject("stdout"); + PyObject *ferr = PySys_GetObject("stderr"); + PyObject *tmp; + long fd; + int tty; + + /* Parse arguments */ + if (!PyArg_UnpackTuple(args, "input", 0, 1, &promptarg)) + return NULL; + + /* Check that stdin/out/err are intact */ + if (fin == NULL || fin == Py_None) { + PyErr_SetString(PyExc_RuntimeError, + "input(): lost sys.stdin"); + return NULL; + } + if (fout == NULL || fout == Py_None) { + PyErr_SetString(PyExc_RuntimeError, + "input(): lost sys.stdout"); + return NULL; + } + if (ferr == NULL || ferr == Py_None) { + PyErr_SetString(PyExc_RuntimeError, + "input(): lost sys.stderr"); + return NULL; + } + + /* First of all, flush stderr */ + tmp = PyObject_CallMethod(ferr, "flush", ""); + if (tmp == NULL) + PyErr_Clear(); + else + Py_DECREF(tmp); + + /* We should only use (GNU) readline if Python's sys.stdin and + sys.stdout are the same as C's stdin and stdout, because we + need to pass it those. */ + tmp = PyObject_CallMethod(fin, "fileno", ""); + if (tmp == NULL) { + PyErr_Clear(); + tty = 0; + } + else { + fd = PyLong_AsLong(tmp); + Py_DECREF(tmp); + if (fd < 0 && PyErr_Occurred()) + return NULL; + tty = fd == fileno(stdin) && isatty(fd); + } + if (tty) { + tmp = PyObject_CallMethod(fout, "fileno", ""); + if (tmp == NULL) + PyErr_Clear(); + else { + fd = PyLong_AsLong(tmp); + Py_DECREF(tmp); + if (fd < 0 && PyErr_Occurred()) + return NULL; + tty = fd == fileno(stdout) && isatty(fd); + } + } + + /* If we're interactive, use (GNU) readline */ + if (tty) { + PyObject *po; + char *prompt; + char *s; + PyObject *stdin_encoding; + PyObject *result; + + stdin_encoding = PyObject_GetAttrString(fin, "encoding"); + if (!stdin_encoding) + /* stdin is a text stream, so it must have an + encoding. */ + return NULL; + tmp = PyObject_CallMethod(fout, "flush", ""); + if (tmp == NULL) + PyErr_Clear(); + else + Py_DECREF(tmp); + if (promptarg != NULL) { + PyObject *stringpo; + PyObject *stdout_encoding; + stdout_encoding = PyObject_GetAttrString(fout, + "encoding"); + if (stdout_encoding == NULL) { + Py_DECREF(stdin_encoding); + return NULL; + } + stringpo = PyObject_Str(promptarg); + if (stringpo == NULL) { + Py_DECREF(stdin_encoding); + Py_DECREF(stdout_encoding); + return NULL; + } + po = PyUnicode_AsEncodedString(stringpo, + _PyUnicode_AsString(stdout_encoding), NULL); + Py_DECREF(stdout_encoding); + Py_DECREF(stringpo); + if (po == NULL) { + Py_DECREF(stdin_encoding); + return NULL; + } + prompt = PyBytes_AsString(po); + if (prompt == NULL) { + Py_DECREF(stdin_encoding); + Py_DECREF(po); + return NULL; + } + } + else { + po = NULL; + prompt = ""; + } + s = PyOS_Readline(stdin, stdout, prompt); + Py_XDECREF(po); + if (s == NULL) { + if (!PyErr_Occurred()) + PyErr_SetNone(PyExc_KeyboardInterrupt); + Py_DECREF(stdin_encoding); + 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, + "input: input too long"); + result = NULL; + } + else { + result = PyUnicode_Decode + (s, len-1, + _PyUnicode_AsString(stdin_encoding), + NULL); + } + } + Py_DECREF(stdin_encoding); + PyMem_FREE(s); + return result; + } + + /* Fallback if we're not interactive */ + if (promptarg != NULL) { + if (PyFile_WriteObject(promptarg, fout, Py_PRINT_RAW) != 0) + return NULL; + } + tmp = PyObject_CallMethod(fout, "flush", ""); + if (tmp == NULL) + PyErr_Clear(); + else + Py_DECREF(tmp); + return PyFile_GetLine(fin, -1); } PyDoc_STRVAR(input_doc, @@ -1705,7 +1705,7 @@ is printed without a trailing newline before reading."); static PyObject * builtin_repr(PyObject *self, PyObject *v) { - return PyObject_Repr(v); + return PyObject_Repr(v); } PyDoc_STRVAR(repr_doc, @@ -1718,38 +1718,38 @@ For most object types, eval(repr(object)) == object."); static PyObject * builtin_round(PyObject *self, PyObject *args, PyObject *kwds) { - static PyObject *round_str = NULL; - PyObject *ndigits = NULL; - static char *kwlist[] = {"number", "ndigits", 0}; - PyObject *number, *round; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:round", - kwlist, &number, &ndigits)) - return NULL; - - if (Py_TYPE(number)->tp_dict == NULL) { - if (PyType_Ready(Py_TYPE(number)) < 0) - return NULL; - } - - if (round_str == NULL) { - round_str = PyUnicode_InternFromString("__round__"); - if (round_str == NULL) - return NULL; - } - - round = _PyType_Lookup(Py_TYPE(number), round_str); - if (round == NULL) { - PyErr_Format(PyExc_TypeError, - "type %.100s doesn't define __round__ method", - Py_TYPE(number)->tp_name); - return NULL; - } - - if (ndigits == NULL) - return PyObject_CallFunction(round, "O", number); - else - return PyObject_CallFunction(round, "OO", number, ndigits); + static PyObject *round_str = NULL; + PyObject *ndigits = NULL; + static char *kwlist[] = {"number", "ndigits", 0}; + PyObject *number, *round; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:round", + kwlist, &number, &ndigits)) + return NULL; + + if (Py_TYPE(number)->tp_dict == NULL) { + if (PyType_Ready(Py_TYPE(number)) < 0) + return NULL; + } + + if (round_str == NULL) { + round_str = PyUnicode_InternFromString("__round__"); + if (round_str == NULL) + return NULL; + } + + round = _PyType_Lookup(Py_TYPE(number), round_str); + if (round == NULL) { + PyErr_Format(PyExc_TypeError, + "type %.100s doesn't define __round__ method", + Py_TYPE(number)->tp_name); + return NULL; + } + + if (ndigits == NULL) + return PyObject_CallFunction(round, "O", number); + else + return PyObject_CallFunction(round, "OO", number, ndigits); } PyDoc_STRVAR(round_doc, @@ -1763,42 +1763,42 @@ same type as the number. ndigits may be negative."); static PyObject * builtin_sorted(PyObject *self, PyObject *args, PyObject *kwds) { - PyObject *newlist, *v, *seq, *keyfunc=NULL, *newargs; - PyObject *callable; - static char *kwlist[] = {"iterable", "key", "reverse", 0}; - int reverse; - - /* args 1-3 should match listsort in Objects/listobject.c */ - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Oi:sorted", - kwlist, &seq, &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; + PyObject *newlist, *v, *seq, *keyfunc=NULL, *newargs; + PyObject *callable; + static char *kwlist[] = {"iterable", "key", "reverse", 0}; + int reverse; + + /* args 1-3 should match listsort in Objects/listobject.c */ + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Oi:sorted", + kwlist, &seq, &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, @@ -1807,30 +1807,30 @@ PyDoc_STRVAR(sorted_doc, 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; + 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, @@ -1842,156 +1842,156 @@ 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 = PyLong_FromLong(0); - if (result == NULL) { - Py_DECREF(iter); - return NULL; - } - } else { - /* reject string values for 'start' parameter */ - if (PyUnicode_Check(result)) { - PyErr_SetString(PyExc_TypeError, - "sum() can't sum strings [use ''.join(seq) instead]"); - Py_DECREF(iter); - return NULL; - } - if (PyByteArray_Check(result)) { - PyErr_SetString(PyExc_TypeError, - "sum() can't sum bytes [use b''.join(seq) instead]"); - Py_DECREF(iter); - return NULL; - } - - Py_INCREF(result); - } + 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 = PyLong_FromLong(0); + if (result == NULL) { + Py_DECREF(iter); + return NULL; + } + } else { + /* reject string values for 'start' parameter */ + if (PyUnicode_Check(result)) { + PyErr_SetString(PyExc_TypeError, + "sum() can't sum strings [use ''.join(seq) instead]"); + Py_DECREF(iter); + return NULL; + } + if (PyByteArray_Check(result)) { + PyErr_SetString(PyExc_TypeError, + "sum() can't sum bytes [use b''.join(seq) instead]"); + Py_DECREF(iter); + return NULL; + } + + Py_INCREF(result); + } #ifndef SLOW_SUM - /* Fast addition by keeping temporary sums in C instead of new Python objects. - Assumes all inputs are the same type. If the assumption fails, default - to the more general routine. - */ - if (PyLong_CheckExact(result)) { - int overflow; - long i_result = PyLong_AsLongAndOverflow(result, &overflow); - /* If this already overflowed, don't even enter the loop. */ - if (overflow == 0) { - Py_DECREF(result); - result = NULL; - } - while(result == NULL) { - item = PyIter_Next(iter); - if (item == NULL) { - Py_DECREF(iter); - if (PyErr_Occurred()) - return NULL; - return PyLong_FromLong(i_result); - } - if (PyLong_CheckExact(item)) { - long b = PyLong_AsLongAndOverflow(item, &overflow); - long x = i_result + b; - if (overflow == 0 && ((x^i_result) >= 0 || (x^b) >= 0)) { - i_result = x; - Py_DECREF(item); - continue; - } - } - /* Either overflowed or is not an int. Restore real objects and process normally */ - result = PyLong_FromLong(i_result); - temp = PyNumber_Add(result, item); - Py_DECREF(result); - Py_DECREF(item); - result = temp; - if (result == NULL) { - Py_DECREF(iter); - return NULL; - } - } - } - - if (PyFloat_CheckExact(result)) { - double f_result = PyFloat_AS_DOUBLE(result); - Py_DECREF(result); - result = NULL; - while(result == NULL) { - item = PyIter_Next(iter); - if (item == NULL) { - Py_DECREF(iter); - if (PyErr_Occurred()) - return NULL; - return PyFloat_FromDouble(f_result); - } - if (PyFloat_CheckExact(item)) { - PyFPE_START_PROTECT("add", Py_DECREF(item); Py_DECREF(iter); return 0) - f_result += PyFloat_AS_DOUBLE(item); - PyFPE_END_PROTECT(f_result) - Py_DECREF(item); - continue; - } - if (PyLong_CheckExact(item)) { - long value; - int overflow; - value = PyLong_AsLongAndOverflow(item, &overflow); - if (!overflow) { - PyFPE_START_PROTECT("add", Py_DECREF(item); Py_DECREF(iter); return 0) - f_result += (double)value; - PyFPE_END_PROTECT(f_result) - Py_DECREF(item); - continue; - } - } - result = PyFloat_FromDouble(f_result); - temp = PyNumber_Add(result, item); - Py_DECREF(result); - Py_DECREF(item); - result = temp; - if (result == NULL) { - Py_DECREF(iter); - return NULL; - } - } - } + /* Fast addition by keeping temporary sums in C instead of new Python objects. + Assumes all inputs are the same type. If the assumption fails, default + to the more general routine. + */ + if (PyLong_CheckExact(result)) { + int overflow; + long i_result = PyLong_AsLongAndOverflow(result, &overflow); + /* If this already overflowed, don't even enter the loop. */ + if (overflow == 0) { + Py_DECREF(result); + result = NULL; + } + while(result == NULL) { + item = PyIter_Next(iter); + if (item == NULL) { + Py_DECREF(iter); + if (PyErr_Occurred()) + return NULL; + return PyLong_FromLong(i_result); + } + if (PyLong_CheckExact(item)) { + long b = PyLong_AsLongAndOverflow(item, &overflow); + long x = i_result + b; + if (overflow == 0 && ((x^i_result) >= 0 || (x^b) >= 0)) { + i_result = x; + Py_DECREF(item); + continue; + } + } + /* Either overflowed or is not an int. Restore real objects and process normally */ + result = PyLong_FromLong(i_result); + temp = PyNumber_Add(result, item); + Py_DECREF(result); + Py_DECREF(item); + result = temp; + if (result == NULL) { + Py_DECREF(iter); + return NULL; + } + } + } + + if (PyFloat_CheckExact(result)) { + double f_result = PyFloat_AS_DOUBLE(result); + Py_DECREF(result); + result = NULL; + while(result == NULL) { + item = PyIter_Next(iter); + if (item == NULL) { + Py_DECREF(iter); + if (PyErr_Occurred()) + return NULL; + return PyFloat_FromDouble(f_result); + } + if (PyFloat_CheckExact(item)) { + PyFPE_START_PROTECT("add", Py_DECREF(item); Py_DECREF(iter); return 0) + f_result += PyFloat_AS_DOUBLE(item); + PyFPE_END_PROTECT(f_result) + Py_DECREF(item); + continue; + } + if (PyLong_CheckExact(item)) { + long value; + int overflow; + value = PyLong_AsLongAndOverflow(item, &overflow); + if (!overflow) { + PyFPE_START_PROTECT("add", Py_DECREF(item); Py_DECREF(iter); return 0) + f_result += (double)value; + PyFPE_END_PROTECT(f_result) + Py_DECREF(item); + continue; + } + } + result = PyFloat_FromDouble(f_result); + temp = PyNumber_Add(result, item); + Py_DECREF(result); + Py_DECREF(item); + result = temp; + if (result == NULL) { + Py_DECREF(iter); + return NULL; + } + } + } #endif - for(;;) { - item = PyIter_Next(iter); - if (item == NULL) { - /* error, or end-of-sequence */ - if (PyErr_Occurred()) { - Py_DECREF(result); - result = NULL; - } - break; - } - /* It's tempting to use PyNumber_InPlaceAdd instead of - PyNumber_Add here, to avoid quadratic running time - when doing 'sum(list_of_lists, [])'. However, this - would produce a change in behaviour: a snippet like - - empty = [] - sum([[x] for x in range(10)], empty) - - would change the value of empty. */ - temp = PyNumber_Add(result, item); - Py_DECREF(result); - Py_DECREF(item); - result = temp; - if (result == NULL) - break; - } - Py_DECREF(iter); - return result; + for(;;) { + item = PyIter_Next(iter); + if (item == NULL) { + /* error, or end-of-sequence */ + if (PyErr_Occurred()) { + Py_DECREF(result); + result = NULL; + } + break; + } + /* It's tempting to use PyNumber_InPlaceAdd instead of + PyNumber_Add here, to avoid quadratic running time + when doing 'sum(list_of_lists, [])'. However, this + would produce a change in behaviour: a snippet like + + empty = [] + sum([[x] for x in range(10)], empty) + + would change the value of empty. */ + 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, @@ -2005,17 +2005,17 @@ empty, returns start."); static PyObject * builtin_isinstance(PyObject *self, PyObject *args) { - PyObject *inst; - PyObject *cls; - int retval; + PyObject *inst; + PyObject *cls; + int retval; - if (!PyArg_UnpackTuple(args, "isinstance", 2, 2, &inst, &cls)) - return NULL; + 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); + retval = PyObject_IsInstance(inst, cls); + if (retval < 0) + return NULL; + return PyBool_FromLong(retval); } PyDoc_STRVAR(isinstance_doc, @@ -2030,17 +2030,17 @@ isinstance(x, A) or isinstance(x, B) or ... (etc.)."); static PyObject * builtin_issubclass(PyObject *self, PyObject *args) { - PyObject *derived; - PyObject *cls; - int retval; + PyObject *derived; + PyObject *cls; + int retval; - if (!PyArg_UnpackTuple(args, "issubclass", 2, 2, &derived, &cls)) - return NULL; + 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); + retval = PyObject_IsSubclass(derived, cls); + if (retval < 0) + return NULL; + return PyBool_FromLong(retval); } PyDoc_STRVAR(issubclass_doc, @@ -2052,127 +2052,127 @@ is a shortcut for issubclass(X, A) or issubclass(X, B) or ... (etc.)."); typedef struct { - PyObject_HEAD - Py_ssize_t tuplesize; - PyObject *ittuple; /* tuple of iterators */ - PyObject *result; + PyObject_HEAD + Py_ssize_t tuplesize; + PyObject *ittuple; /* tuple of iterators */ + PyObject *result; } zipobject; static PyObject * zip_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - zipobject *lz; - Py_ssize_t i; - PyObject *ittuple; /* tuple of iterators */ - PyObject *result; - Py_ssize_t tuplesize = PySequence_Length(args); - - if (type == &PyZip_Type && !_PyArg_NoKeywords("zip()", kwds)) - return NULL; - - /* args must be a tuple */ - assert(PyTuple_Check(args)); - - /* obtain iterators */ - ittuple = PyTuple_New(tuplesize); - if (ittuple == NULL) - return NULL; - for (i=0; i < tuplesize; ++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); - Py_DECREF(ittuple); - return NULL; - } - PyTuple_SET_ITEM(ittuple, i, it); - } - - /* create a result holder */ - result = PyTuple_New(tuplesize); - if (result == NULL) { - Py_DECREF(ittuple); - return NULL; - } - for (i=0 ; i < tuplesize ; i++) { - Py_INCREF(Py_None); - PyTuple_SET_ITEM(result, i, Py_None); - } - - /* create zipobject structure */ - lz = (zipobject *)type->tp_alloc(type, 0); - if (lz == NULL) { - Py_DECREF(ittuple); - Py_DECREF(result); - return NULL; - } - lz->ittuple = ittuple; - lz->tuplesize = tuplesize; - lz->result = result; - - return (PyObject *)lz; + zipobject *lz; + Py_ssize_t i; + PyObject *ittuple; /* tuple of iterators */ + PyObject *result; + Py_ssize_t tuplesize = PySequence_Length(args); + + if (type == &PyZip_Type && !_PyArg_NoKeywords("zip()", kwds)) + return NULL; + + /* args must be a tuple */ + assert(PyTuple_Check(args)); + + /* obtain iterators */ + ittuple = PyTuple_New(tuplesize); + if (ittuple == NULL) + return NULL; + for (i=0; i < tuplesize; ++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); + Py_DECREF(ittuple); + return NULL; + } + PyTuple_SET_ITEM(ittuple, i, it); + } + + /* create a result holder */ + result = PyTuple_New(tuplesize); + if (result == NULL) { + Py_DECREF(ittuple); + return NULL; + } + for (i=0 ; i < tuplesize ; i++) { + Py_INCREF(Py_None); + PyTuple_SET_ITEM(result, i, Py_None); + } + + /* create zipobject structure */ + lz = (zipobject *)type->tp_alloc(type, 0); + if (lz == NULL) { + Py_DECREF(ittuple); + Py_DECREF(result); + return NULL; + } + lz->ittuple = ittuple; + lz->tuplesize = tuplesize; + lz->result = result; + + return (PyObject *)lz; } static void zip_dealloc(zipobject *lz) { - PyObject_GC_UnTrack(lz); - Py_XDECREF(lz->ittuple); - Py_XDECREF(lz->result); - Py_TYPE(lz)->tp_free(lz); + PyObject_GC_UnTrack(lz); + Py_XDECREF(lz->ittuple); + Py_XDECREF(lz->result); + Py_TYPE(lz)->tp_free(lz); } static int zip_traverse(zipobject *lz, visitproc visit, void *arg) { - Py_VISIT(lz->ittuple); - Py_VISIT(lz->result); - return 0; + Py_VISIT(lz->ittuple); + Py_VISIT(lz->result); + return 0; } static PyObject * zip_next(zipobject *lz) { - Py_ssize_t i; - Py_ssize_t tuplesize = lz->tuplesize; - PyObject *result = lz->result; - PyObject *it; - PyObject *item; - PyObject *olditem; - - if (tuplesize == 0) - return NULL; - if (Py_REFCNT(result) == 1) { - Py_INCREF(result); - for (i=0 ; i < tuplesize ; i++) { - it = PyTuple_GET_ITEM(lz->ittuple, i); - item = (*Py_TYPE(it)->tp_iternext)(it); - if (item == NULL) { - Py_DECREF(result); - return NULL; - } - olditem = PyTuple_GET_ITEM(result, i); - PyTuple_SET_ITEM(result, i, item); - Py_DECREF(olditem); - } - } else { - result = PyTuple_New(tuplesize); - if (result == NULL) - return NULL; - for (i=0 ; i < tuplesize ; i++) { - it = PyTuple_GET_ITEM(lz->ittuple, i); - item = (*Py_TYPE(it)->tp_iternext)(it); - if (item == NULL) { - Py_DECREF(result); - return NULL; - } - PyTuple_SET_ITEM(result, i, item); - } - } - return result; + Py_ssize_t i; + Py_ssize_t tuplesize = lz->tuplesize; + PyObject *result = lz->result; + PyObject *it; + PyObject *item; + PyObject *olditem; + + if (tuplesize == 0) + return NULL; + if (Py_REFCNT(result) == 1) { + Py_INCREF(result); + for (i=0 ; i < tuplesize ; i++) { + it = PyTuple_GET_ITEM(lz->ittuple, i); + item = (*Py_TYPE(it)->tp_iternext)(it); + if (item == NULL) { + Py_DECREF(result); + return NULL; + } + olditem = PyTuple_GET_ITEM(result, i); + PyTuple_SET_ITEM(result, i, item); + Py_DECREF(olditem); + } + } else { + result = PyTuple_New(tuplesize); + if (result == NULL) + return NULL; + for (i=0 ; i < tuplesize ; i++) { + it = PyTuple_GET_ITEM(lz->ittuple, i); + item = (*Py_TYPE(it)->tp_iternext)(it); + if (item == NULL) { + Py_DECREF(result); + return NULL; + } + PyTuple_SET_ITEM(result, i, item); + } + } + return result; } PyDoc_STRVAR(zip_doc, @@ -2184,93 +2184,93 @@ method continues until the shortest iterable in the argument sequence\n\ is exhausted and then it raises StopIteration."); PyTypeObject PyZip_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "zip", /* tp_name */ - sizeof(zipobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)zip_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - zip_doc, /* tp_doc */ - (traverseproc)zip_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)zip_next, /* tp_iternext */ - 0, /* 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 */ - 0, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - zip_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "zip", /* tp_name */ + sizeof(zipobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)zip_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_BASETYPE, /* tp_flags */ + zip_doc, /* tp_doc */ + (traverseproc)zip_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)zip_next, /* tp_iternext */ + 0, /* 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 */ + 0, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + zip_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ }; static PyMethodDef builtin_methods[] = { - {"__build_class__", (PyCFunction)builtin___build_class__, - METH_VARARGS | METH_KEYWORDS, build_class_doc}, - {"__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}, - {"ascii", builtin_ascii, METH_O, ascii_doc}, - {"bin", builtin_bin, METH_O, bin_doc}, - {"chr", builtin_chr, METH_VARARGS, chr_doc}, - {"compile", (PyCFunction)builtin_compile, METH_VARARGS | METH_KEYWORDS, 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}, - {"exec", builtin_exec, METH_VARARGS, exec_doc}, - {"format", builtin_format, METH_VARARGS, format_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}, - {"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}, - {"max", (PyCFunction)builtin_max, METH_VARARGS | METH_KEYWORDS, max_doc}, - {"min", (PyCFunction)builtin_min, METH_VARARGS | METH_KEYWORDS, min_doc}, - {"next", (PyCFunction)builtin_next, METH_VARARGS, next_doc}, - {"oct", builtin_oct, METH_O, oct_doc}, - {"ord", builtin_ord, METH_O, ord_doc}, - {"pow", builtin_pow, METH_VARARGS, pow_doc}, - {"print", (PyCFunction)builtin_print, METH_VARARGS | METH_KEYWORDS, print_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}, - {"vars", builtin_vars, METH_VARARGS, vars_doc}, - {NULL, NULL}, + {"__build_class__", (PyCFunction)builtin___build_class__, + METH_VARARGS | METH_KEYWORDS, build_class_doc}, + {"__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}, + {"ascii", builtin_ascii, METH_O, ascii_doc}, + {"bin", builtin_bin, METH_O, bin_doc}, + {"chr", builtin_chr, METH_VARARGS, chr_doc}, + {"compile", (PyCFunction)builtin_compile, METH_VARARGS | METH_KEYWORDS, 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}, + {"exec", builtin_exec, METH_VARARGS, exec_doc}, + {"format", builtin_format, METH_VARARGS, format_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}, + {"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}, + {"max", (PyCFunction)builtin_max, METH_VARARGS | METH_KEYWORDS, max_doc}, + {"min", (PyCFunction)builtin_min, METH_VARARGS | METH_KEYWORDS, min_doc}, + {"next", (PyCFunction)builtin_next, METH_VARARGS, next_doc}, + {"oct", builtin_oct, METH_O, oct_doc}, + {"ord", builtin_ord, METH_O, ord_doc}, + {"pow", builtin_pow, METH_VARARGS, pow_doc}, + {"print", (PyCFunction)builtin_print, METH_VARARGS | METH_KEYWORDS, print_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}, + {"vars", builtin_vars, METH_VARARGS, vars_doc}, + {NULL, NULL}, }; PyDoc_STRVAR(builtin_doc, @@ -2279,83 +2279,83 @@ PyDoc_STRVAR(builtin_doc, Noteworthy: None is the `nil' object; Ellipsis represents `...' in slices."); static struct PyModuleDef builtinsmodule = { - PyModuleDef_HEAD_INIT, - "builtins", - builtin_doc, - -1, /* multiple "initialization" just copies the module dict. */ - builtin_methods, - NULL, - NULL, - NULL, - NULL + PyModuleDef_HEAD_INIT, + "builtins", + builtin_doc, + -1, /* multiple "initialization" just copies the module dict. */ + builtin_methods, + NULL, + NULL, + NULL, + NULL }; PyObject * _PyBuiltin_Init(void) { - PyObject *mod, *dict, *debug; - mod = PyModule_Create(&builtinsmodule); - if (mod == NULL) - return NULL; - dict = PyModule_GetDict(mod); + PyObject *mod, *dict, *debug; + mod = PyModule_Create(&builtinsmodule); + if (mod == NULL) + return NULL; + dict = PyModule_GetDict(mod); #ifdef Py_TRACE_REFS - /* "builtins" 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). - */ + /* "builtins" 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("bool", &PyBool_Type); - SETBUILTIN("memoryview", &PyMemoryView_Type); - SETBUILTIN("bytearray", &PyByteArray_Type); - SETBUILTIN("bytes", &PyBytes_Type); - SETBUILTIN("classmethod", &PyClassMethod_Type); - SETBUILTIN("complex", &PyComplex_Type); - SETBUILTIN("dict", &PyDict_Type); - SETBUILTIN("enumerate", &PyEnum_Type); - SETBUILTIN("filter", &PyFilter_Type); - SETBUILTIN("float", &PyFloat_Type); - SETBUILTIN("frozenset", &PyFrozenSet_Type); - SETBUILTIN("property", &PyProperty_Type); - SETBUILTIN("int", &PyLong_Type); - SETBUILTIN("list", &PyList_Type); - SETBUILTIN("map", &PyMap_Type); - SETBUILTIN("object", &PyBaseObject_Type); - SETBUILTIN("range", &PyRange_Type); - SETBUILTIN("reversed", &PyReversed_Type); - SETBUILTIN("set", &PySet_Type); - SETBUILTIN("slice", &PySlice_Type); - SETBUILTIN("staticmethod", &PyStaticMethod_Type); - SETBUILTIN("str", &PyUnicode_Type); - SETBUILTIN("super", &PySuper_Type); - SETBUILTIN("tuple", &PyTuple_Type); - SETBUILTIN("type", &PyType_Type); - SETBUILTIN("zip", &PyZip_Type); - debug = PyBool_FromLong(Py_OptimizeFlag == 0); - if (PyDict_SetItemString(dict, "__debug__", debug) < 0) { - Py_XDECREF(debug); - return NULL; - } - Py_XDECREF(debug); - - return mod; + 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("bool", &PyBool_Type); + SETBUILTIN("memoryview", &PyMemoryView_Type); + SETBUILTIN("bytearray", &PyByteArray_Type); + SETBUILTIN("bytes", &PyBytes_Type); + SETBUILTIN("classmethod", &PyClassMethod_Type); + SETBUILTIN("complex", &PyComplex_Type); + SETBUILTIN("dict", &PyDict_Type); + SETBUILTIN("enumerate", &PyEnum_Type); + SETBUILTIN("filter", &PyFilter_Type); + SETBUILTIN("float", &PyFloat_Type); + SETBUILTIN("frozenset", &PyFrozenSet_Type); + SETBUILTIN("property", &PyProperty_Type); + SETBUILTIN("int", &PyLong_Type); + SETBUILTIN("list", &PyList_Type); + SETBUILTIN("map", &PyMap_Type); + SETBUILTIN("object", &PyBaseObject_Type); + SETBUILTIN("range", &PyRange_Type); + SETBUILTIN("reversed", &PyReversed_Type); + SETBUILTIN("set", &PySet_Type); + SETBUILTIN("slice", &PySlice_Type); + SETBUILTIN("staticmethod", &PyStaticMethod_Type); + SETBUILTIN("str", &PyUnicode_Type); + SETBUILTIN("super", &PySuper_Type); + SETBUILTIN("tuple", &PyTuple_Type); + SETBUILTIN("type", &PyType_Type); + SETBUILTIN("zip", &PyZip_Type); + 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 } diff --git a/Python/ceval.c b/Python/ceval.c index 3bd0ce62ac..297b44973b 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -28,27 +28,27 @@ 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 :-) */ + 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; + 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; + 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; } #elif defined(__i386__) @@ -77,17 +77,17 @@ ppc_getcounter(uint64 *v) #endif void dump_tsc(int opcode, int ticked, uint64 inst0, uint64 inst1, - uint64 loop0, uint64 loop1, uint64 intr0, uint64 intr1) + 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); + 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 @@ -97,8 +97,8 @@ void dump_tsc(int opcode, int ticked, uint64 inst0, uint64 inst1, #ifdef Py_DEBUG /* For debugging the interpreter: */ -#define LLTRACE 1 /* Low-level trace feature */ -#define CHECKEXC 1 /* Double-check exception checking */ +#define LLTRACE 1 /* Low-level trace feature */ +#define CHECKEXC 1 /* Double-check exception checking */ #endif typedef PyObject *(*callproc)(PyObject *, PyObject *, PyObject *); @@ -113,7 +113,7 @@ 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 *); + PyObject *); static PyObject * update_star_args(int, int, PyObject *, PyObject ***); static PyObject * load_args(PyObject ***, int); #define CALL_FLAG_VAR 1 @@ -124,12 +124,12 @@ static int lltrace; static int prtrace(PyObject *, char *); #endif static int call_trace(Py_tracefunc, PyObject *, PyFrameObject *, - int, PyObject *); + int, PyObject *); static int call_trace_protected(Py_tracefunc, PyObject *, - PyFrameObject *, int, 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 *); + PyFrameObject *, int *, int *, int *); static PyObject * cmp_outcome(int, PyObject *, PyObject *); static PyObject * import_from(PyObject *, PyObject *); @@ -140,14 +140,14 @@ static PyObject * unicode_concatenate(PyObject *, PyObject *, static PyObject * special_lookup(PyObject *, char *, PyObject **); #define NAME_ERROR_MSG \ - "name '%.200s' is not defined" + "name '%.200s' is not defined" #define GLOBAL_NAME_ERROR_MSG \ - "global name '%.200s' is not defined" + "global name '%.200s' is not defined" #define UNBOUNDLOCAL_ERROR_MSG \ - "local variable '%.200s' referenced before assignment" + "local variable '%.200s' referenced before assignment" #define UNBOUNDFREE_ERROR_MSG \ - "free variable '%.200s' referenced before assignment" \ - " in enclosing scope" + "free variable '%.200s' referenced before assignment" \ + " in enclosing scope" /* Dynamic execution profile */ #ifdef DYNAMIC_EXECUTION_PROFILE @@ -199,10 +199,10 @@ static int pcall[PCALL_NUM]; 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]); + 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) @@ -210,8 +210,8 @@ PyEval_GetCallStats(PyObject *self) PyObject * PyEval_GetCallStats(PyObject *self) { - Py_INCREF(Py_None); - return Py_None; + Py_INCREF(Py_None); + return Py_None; } #endif @@ -220,45 +220,45 @@ PyEval_GetCallStats(PyObject *self) 1. We believe this is all right because the eval loop will release the GIL eventually anyway. */ #define COMPUTE_EVAL_BREAKER() \ - _Py_atomic_store_relaxed( \ - &eval_breaker, \ - _Py_atomic_load_relaxed(&gil_drop_request) | \ - _Py_atomic_load_relaxed(&pendingcalls_to_do) | \ - pending_async_exc) + _Py_atomic_store_relaxed( \ + &eval_breaker, \ + _Py_atomic_load_relaxed(&gil_drop_request) | \ + _Py_atomic_load_relaxed(&pendingcalls_to_do) | \ + pending_async_exc) #define SET_GIL_DROP_REQUEST() \ - do { \ - _Py_atomic_store_relaxed(&gil_drop_request, 1); \ - _Py_atomic_store_relaxed(&eval_breaker, 1); \ - } while (0) + do { \ + _Py_atomic_store_relaxed(&gil_drop_request, 1); \ + _Py_atomic_store_relaxed(&eval_breaker, 1); \ + } while (0) #define RESET_GIL_DROP_REQUEST() \ - do { \ - _Py_atomic_store_relaxed(&gil_drop_request, 0); \ - COMPUTE_EVAL_BREAKER(); \ - } while (0) + do { \ + _Py_atomic_store_relaxed(&gil_drop_request, 0); \ + COMPUTE_EVAL_BREAKER(); \ + } while (0) /* Pending calls are only modified under pending_lock */ #define SIGNAL_PENDING_CALLS() \ - do { \ - _Py_atomic_store_relaxed(&pendingcalls_to_do, 1); \ - _Py_atomic_store_relaxed(&eval_breaker, 1); \ - } while (0) + do { \ + _Py_atomic_store_relaxed(&pendingcalls_to_do, 1); \ + _Py_atomic_store_relaxed(&eval_breaker, 1); \ + } while (0) #define UNSIGNAL_PENDING_CALLS() \ - do { \ - _Py_atomic_store_relaxed(&pendingcalls_to_do, 0); \ - COMPUTE_EVAL_BREAKER(); \ - } while (0) + do { \ + _Py_atomic_store_relaxed(&pendingcalls_to_do, 0); \ + COMPUTE_EVAL_BREAKER(); \ + } while (0) #define SIGNAL_ASYNC_EXC() \ - do { \ - pending_async_exc = 1; \ - _Py_atomic_store_relaxed(&eval_breaker, 1); \ - } while (0) + do { \ + pending_async_exc = 1; \ + _Py_atomic_store_relaxed(&eval_breaker, 1); \ + } while (0) #define UNSIGNAL_ASYNC_EXC() \ - do { pending_async_exc = 0; COMPUTE_EVAL_BREAKER(); } while (0) + do { pending_async_exc = 0; COMPUTE_EVAL_BREAKER(); } while (0) #ifdef WITH_THREAD @@ -286,62 +286,62 @@ static int pending_async_exc = 0; int PyEval_ThreadsInitialized(void) { - return gil_created(); + return gil_created(); } void PyEval_InitThreads(void) { - if (gil_created()) - return; - create_gil(); - take_gil(PyThreadState_GET()); - main_thread = PyThread_get_thread_ident(); - if (!pending_lock) - pending_lock = PyThread_allocate_lock(); + if (gil_created()) + return; + create_gil(); + take_gil(PyThreadState_GET()); + main_thread = PyThread_get_thread_ident(); + if (!pending_lock) + pending_lock = PyThread_allocate_lock(); } void PyEval_AcquireLock(void) { - PyThreadState *tstate = PyThreadState_GET(); - if (tstate == NULL) - Py_FatalError("PyEval_AcquireLock: current thread state is NULL"); - take_gil(tstate); + PyThreadState *tstate = PyThreadState_GET(); + if (tstate == NULL) + Py_FatalError("PyEval_AcquireLock: current thread state is NULL"); + take_gil(tstate); } void PyEval_ReleaseLock(void) { - /* This function must succeed when the current thread state is NULL. - We therefore avoid PyThreadState_GET() which dumps a fatal error - in debug mode. - */ - drop_gil((PyThreadState*)_Py_atomic_load_relaxed( - &_PyThreadState_Current)); + /* This function must succeed when the current thread state is NULL. + We therefore avoid PyThreadState_GET() which dumps a fatal error + in debug mode. + */ + drop_gil((PyThreadState*)_Py_atomic_load_relaxed( + &_PyThreadState_Current)); } 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(gil_created()); - take_gil(tstate); - if (PyThreadState_Swap(tstate) != NULL) - Py_FatalError( - "PyEval_AcquireThread: non-NULL old thread state"); + if (tstate == NULL) + Py_FatalError("PyEval_AcquireThread: NULL new thread state"); + /* Check someone has called PyEval_InitThreads() to create the lock */ + assert(gil_created()); + take_gil(tstate); + 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"); - drop_gil(tstate); + if (tstate == NULL) + Py_FatalError("PyEval_ReleaseThread: NULL thread state"); + if (PyThreadState_Swap(NULL) != tstate) + Py_FatalError("PyEval_ReleaseThread: wrong thread state"); + drop_gil(tstate); } /* This function is called from PyOS_AfterFork to ensure that newly @@ -352,36 +352,36 @@ PyEval_ReleaseThread(PyThreadState *tstate) void PyEval_ReInitThreads(void) { - PyObject *threading, *result; - PyThreadState *tstate = PyThreadState_GET(); - - if (!gil_created()) - 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 */ - recreate_gil(); - pending_lock = PyThread_allocate_lock(); - take_gil(tstate); - main_thread = PyThread_get_thread_ident(); - - /* Update the threading module with the new state. - */ - tstate = PyThreadState_GET(); - threading = PyMapping_GetItemString(tstate->interp->modules, - "threading"); - if (threading == NULL) { - /* threading not imported */ - PyErr_Clear(); - return; - } - result = PyObject_CallMethod(threading, "_after_fork", NULL); - if (result == NULL) - PyErr_WriteUnraisable(threading); - else - Py_DECREF(result); - Py_DECREF(threading); + PyObject *threading, *result; + PyThreadState *tstate = PyThreadState_GET(); + + if (!gil_created()) + 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 */ + recreate_gil(); + pending_lock = PyThread_allocate_lock(); + take_gil(tstate); + main_thread = PyThread_get_thread_ident(); + + /* Update the threading module with the new state. + */ + tstate = PyThreadState_GET(); + threading = PyMapping_GetItemString(tstate->interp->modules, + "threading"); + if (threading == NULL) { + /* threading not imported */ + PyErr_Clear(); + return; + } + result = PyObject_CallMethod(threading, "_after_fork", NULL); + if (result == NULL) + PyErr_WriteUnraisable(threading); + else + Py_DECREF(result); + Py_DECREF(threading); } #else @@ -396,7 +396,7 @@ static int pending_async_exc = 0; void _PyEval_SignalAsyncExc(void) { - SIGNAL_ASYNC_EXC(); + SIGNAL_ASYNC_EXC(); } /* Functions save_thread and restore_thread are always defined so @@ -406,29 +406,29 @@ _PyEval_SignalAsyncExc(void) PyThreadState * PyEval_SaveThread(void) { - PyThreadState *tstate = PyThreadState_Swap(NULL); - if (tstate == NULL) - Py_FatalError("PyEval_SaveThread: NULL tstate"); + PyThreadState *tstate = PyThreadState_Swap(NULL); + if (tstate == NULL) + Py_FatalError("PyEval_SaveThread: NULL tstate"); #ifdef WITH_THREAD - if (gil_created()) - drop_gil(tstate); + if (gil_created()) + drop_gil(tstate); #endif - return tstate; + return tstate; } void PyEval_RestoreThread(PyThreadState *tstate) { - if (tstate == NULL) - Py_FatalError("PyEval_RestoreThread: NULL tstate"); + if (tstate == NULL) + Py_FatalError("PyEval_RestoreThread: NULL tstate"); #ifdef WITH_THREAD - if (gil_created()) { - int err = errno; - take_gil(tstate); - errno = err; - } + if (gil_created()) { + int err = errno; + take_gil(tstate); + errno = err; + } #endif - PyThreadState_Swap(tstate); + PyThreadState_Swap(tstate); } @@ -465,8 +465,8 @@ PyEval_RestoreThread(PyThreadState *tstate) #define NPENDINGCALLS 32 static struct { - int (*func)(void *); - void *arg; + int (*func)(void *); + void *arg; } pendingcalls[NPENDINGCALLS]; static int pendingfirst = 0; static int pendinglast = 0; @@ -475,95 +475,95 @@ static char pendingbusy = 0; int Py_AddPendingCall(int (*func)(void *), void *arg) { - int i, j, result=0; - PyThread_type_lock lock = pending_lock; - - /* try a few times for the lock. Since this mechanism is used - * for signal handling (on the main thread), there is a (slim) - * chance that a signal is delivered on the same thread while we - * hold the lock during the Py_MakePendingCalls() function. - * This avoids a deadlock in that case. - * Note that signals can be delivered on any thread. In particular, - * on Windows, a SIGINT is delivered on a system-created worker - * thread. - * We also check for lock being NULL, in the unlikely case that - * this function is called before any bytecode evaluation takes place. - */ - if (lock != NULL) { - for (i = 0; i<100; i++) { - if (PyThread_acquire_lock(lock, NOWAIT_LOCK)) - break; - } - if (i == 100) - return -1; - } - - i = pendinglast; - j = (i + 1) % NPENDINGCALLS; - if (j == pendingfirst) { - result = -1; /* Queue full */ - } else { - pendingcalls[i].func = func; - pendingcalls[i].arg = arg; - pendinglast = j; - } - /* signal main loop */ - SIGNAL_PENDING_CALLS(); - if (lock != NULL) - PyThread_release_lock(lock); - return result; + int i, j, result=0; + PyThread_type_lock lock = pending_lock; + + /* try a few times for the lock. Since this mechanism is used + * for signal handling (on the main thread), there is a (slim) + * chance that a signal is delivered on the same thread while we + * hold the lock during the Py_MakePendingCalls() function. + * This avoids a deadlock in that case. + * Note that signals can be delivered on any thread. In particular, + * on Windows, a SIGINT is delivered on a system-created worker + * thread. + * We also check for lock being NULL, in the unlikely case that + * this function is called before any bytecode evaluation takes place. + */ + if (lock != NULL) { + for (i = 0; i<100; i++) { + if (PyThread_acquire_lock(lock, NOWAIT_LOCK)) + break; + } + if (i == 100) + return -1; + } + + i = pendinglast; + j = (i + 1) % NPENDINGCALLS; + if (j == pendingfirst) { + result = -1; /* Queue full */ + } else { + pendingcalls[i].func = func; + pendingcalls[i].arg = arg; + pendinglast = j; + } + /* signal main loop */ + SIGNAL_PENDING_CALLS(); + if (lock != NULL) + PyThread_release_lock(lock); + return result; } int Py_MakePendingCalls(void) { - int i; - int r = 0; - - if (!pending_lock) { - /* initial allocation of the lock */ - pending_lock = PyThread_allocate_lock(); - if (pending_lock == NULL) - return -1; - } - - /* only service pending calls on main thread */ - if (main_thread && PyThread_get_thread_ident() != main_thread) - return 0; - /* don't perform recursive pending calls */ - if (pendingbusy) - return 0; - pendingbusy = 1; - /* perform a bounded number of calls, in case of recursion */ - for (i=0; irecursion_depth; - PyErr_SetString(PyExc_MemoryError, "Stack overflow"); - return -1; - } + if (PyOS_CheckStack()) { + --tstate->recursion_depth; + PyErr_SetString(PyExc_MemoryError, "Stack overflow"); + return -1; + } #endif - _Py_CheckRecursionLimit = recursion_limit; - if (tstate->recursion_critical) - /* Somebody asked that we don't check for recursion. */ - return 0; - if (tstate->overflowed) { - if (tstate->recursion_depth > recursion_limit + 50) { - /* Overflowing while handling an overflow. Give up. */ - Py_FatalError("Cannot recover from stack overflow."); - } - return 0; - } - if (tstate->recursion_depth > recursion_limit) { - --tstate->recursion_depth; - tstate->overflowed = 1; - PyErr_Format(PyExc_RuntimeError, - "maximum recursion depth exceeded%s", - where); - return -1; - } - return 0; + _Py_CheckRecursionLimit = recursion_limit; + if (tstate->recursion_critical) + /* Somebody asked that we don't check for recursion. */ + return 0; + if (tstate->overflowed) { + if (tstate->recursion_depth > recursion_limit + 50) { + /* Overflowing while handling an overflow. Give up. */ + Py_FatalError("Cannot recover from stack overflow."); + } + return 0; + } + if (tstate->recursion_depth > recursion_limit) { + --tstate->recursion_depth; + tstate->overflowed = 1; + PyErr_Format(PyExc_RuntimeError, + "maximum recursion depth exceeded%s", + where); + return -1; + } + 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 */ - WHY_SILENCED = 0x0080 /* Exception silenced by 'with' */ + 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 */ + WHY_SILENCED = 0x0080 /* Exception silenced by 'with' */ }; static enum why_code do_raise(PyObject *, PyObject *); @@ -743,12 +743,12 @@ static int _Py_TracingPossible = 0; PyObject * PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals) { - return PyEval_EvalCodeEx(co, - globals, locals, - (PyObject **)NULL, 0, - (PyObject **)NULL, 0, - (PyObject **)NULL, 0, - NULL, NULL); + return PyEval_EvalCodeEx(co, + globals, locals, + (PyObject **)NULL, 0, + (PyObject **)NULL, 0, + (PyObject **)NULL, 0, + NULL, NULL); } @@ -756,49 +756,49 @@ PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals) 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); + /* 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; + 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 **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; + 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 **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; + /* Make it easier to find out where we are with a debugger */ + char *filename; #endif /* Computed GOTOs, or @@ -807,7 +807,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) (http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html). The traditional bytecode evaluation loop uses a "switch" statement, which - decent compilers will optimize as a single indirect branch instruction + decent compilers will optimize as a single indirect branch instruction combined with a lookup table of jump addresses. However, since the indirect jump instruction is shared by all opcodes, the CPU will have a hard time making the right prediction for where to jump next (actually, @@ -822,7 +822,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) a much better chance to turn out valid, especially in small bytecode loops. A mispredicted branch on a modern CPU flushes the whole pipeline and - can cost several CPU cycles (depending on the pipeline depth), + can cost several CPU cycles (depending on the pipeline depth), and potentially many more instructions (depending on the pipeline width). A correctly predicted branch, however, is nearly free. @@ -851,56 +851,56 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) /* This macro is used when several opcodes defer to the same implementation (e.g. SETUP_LOOP, SETUP_FINALLY) */ #define TARGET_WITH_IMPL(op, impl) \ - TARGET_##op: \ - opcode = op; \ - if (HAS_ARG(op)) \ - oparg = NEXTARG(); \ - case op: \ - goto impl; \ + TARGET_##op: \ + opcode = op; \ + if (HAS_ARG(op)) \ + oparg = NEXTARG(); \ + case op: \ + goto impl; \ #define TARGET(op) \ - TARGET_##op: \ - opcode = op; \ - if (HAS_ARG(op)) \ - oparg = NEXTARG(); \ - case op: + TARGET_##op: \ + opcode = op; \ + if (HAS_ARG(op)) \ + oparg = NEXTARG(); \ + case op: #define DISPATCH() \ - { \ - if (!_Py_atomic_load_relaxed(&eval_breaker)) { \ - FAST_DISPATCH(); \ - } \ - continue; \ - } + { \ + if (!_Py_atomic_load_relaxed(&eval_breaker)) { \ + FAST_DISPATCH(); \ + } \ + continue; \ + } #ifdef LLTRACE #define FAST_DISPATCH() \ - { \ - if (!lltrace && !_Py_TracingPossible) { \ - f->f_lasti = INSTR_OFFSET(); \ - goto *opcode_targets[*next_instr++]; \ - } \ - goto fast_next_opcode; \ - } + { \ + if (!lltrace && !_Py_TracingPossible) { \ + f->f_lasti = INSTR_OFFSET(); \ + goto *opcode_targets[*next_instr++]; \ + } \ + goto fast_next_opcode; \ + } #else #define FAST_DISPATCH() \ - { \ - if (!_Py_TracingPossible) { \ - f->f_lasti = INSTR_OFFSET(); \ - goto *opcode_targets[*next_instr++]; \ - } \ - goto fast_next_opcode; \ - } + { \ + if (!_Py_TracingPossible) { \ + f->f_lasti = INSTR_OFFSET(); \ + goto *opcode_targets[*next_instr++]; \ + } \ + goto fast_next_opcode; \ + } #endif #else #define TARGET(op) \ - case op: + case op: #define TARGET_WITH_IMPL(op, impl) \ - /* silence compiler warnings about `impl` unused */ \ - if (0) goto impl; \ - case op: + /* silence compiler warnings about `impl` unused */ \ + if (0) goto impl; \ + case op: #define DISPATCH() continue #define FAST_DISPATCH() goto fast_next_opcode #endif @@ -942,62 +942,62 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) CALL_FUNCTION (and friends) */ - uint64 inst0, inst1, loop0, loop1, intr0 = 0, intr1 = 0; - int ticked = 0; + uint64 inst0, inst1, loop0, loop1, intr0 = 0, intr1 = 0; + int ticked = 0; - READ_TIMESTAMP(inst0); - READ_TIMESTAMP(inst1); - READ_TIMESTAMP(loop0); - READ_TIMESTAMP(loop1); + READ_TIMESTAMP(inst0); + READ_TIMESTAMP(inst1); + READ_TIMESTAMP(loop0); + READ_TIMESTAMP(loop1); - /* shut up the compiler */ - opcode = 0; + /* 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)) +#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 a register - variable against a constant. If the pairing was good, then the - processor's own internal branch predication has a high likelihood of - success, resulting 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 HAS_ARG test and the - switch-case. Combined with the processor's internal branch prediction, - a successful PREDICT has the effect of making the two opcodes run as if - they were a single new opcode with the bodies combined. + 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 a register + variable against a constant. If the pairing was good, then the + processor's own internal branch predication has a high likelihood of + success, resulting 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 HAS_ARG test and the + switch-case. Combined with the processor's internal branch prediction, + a successful PREDICT has the effect of making the two opcodes run as if + they were a single new opcode with the bodies combined. If collecting opcode statistics, your choices are to either keep the - predictions turned-on and interpret the results as if some opcodes - had been combined or turn-off predictions so that the opcode frequency - counter updates for both opcodes. + predictions turned-on and interpret the results as if some opcodes + had been combined or turn-off predictions so that the opcode frequency + counter updates for both opcodes. Opcode prediction is disabled with threaded code, since the latter allows - the CPU to record separate branch prediction information for each - opcode. + the CPU to record separate branch prediction information for each + opcode. */ #if defined(DYNAMIC_EXECUTION_PROFILE) || defined(USE_COMPUTED_GOTOS) -#define PREDICT(op) if (0) goto PRED_##op -#define PREDICTED(op) PRED_##op: -#define PREDICTED_WITH_ARG(op) PRED_##op: +#define PREDICT(op) if (0) goto PRED_##op +#define PREDICTED(op) PRED_##op: +#define PREDICTED_WITH_ARG(op) PRED_##op: #else -#define PREDICT(op) if (*next_instr == op) goto PRED_##op -#define PREDICTED(op) PRED_##op: next_instr++ -#define PREDICTED_WITH_ARG(op) PRED_##op: oparg = PEEKARG(); next_instr += 3 +#define PREDICT(op) if (*next_instr == op) goto PRED_##op +#define PREDICTED(op) PRED_##op: next_instr++ +#define PREDICTED_WITH_ARG(op) PRED_##op: oparg = PEEKARG(); next_instr += 3 #endif @@ -1005,44 +1005,44 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) /* 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 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 PEEK(n) (stack_pointer[-(n)]) -#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 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 SET_VALUE(n, v) (stack_pointer[-(n)] = (v)) -#define BASIC_STACKADJ(n) (stack_pointer += n) -#define BASIC_PUSH(v) (*stack_pointer++ = (v)) -#define BASIC_POP() (*--stack_pointer) +#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 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) ((void)(lltrace && \ - prtrace((STACK_POINTER)[-1], "ext_pop")), \ - *--(STACK_POINTER)) + prtrace((STACK_POINTER)[-1], "ext_pop")), \ + *--(STACK_POINTER)) #else -#define PUSH(v) BASIC_PUSH(v) -#define POP() BASIC_POP() -#define STACKADJ(n) BASIC_STACKADJ(n) +#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]) +#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 @@ -1050,2006 +1050,2006 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) 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) +#define SETLOCAL(i, value) do { PyObject *tmp = GETLOCAL(i); \ + GETLOCAL(i) = value; \ + Py_XDECREF(tmp); } while (0) #define UNWIND_BLOCK(b) \ - while (STACK_LEVEL() > (b)->b_level) { \ - PyObject *v = POP(); \ - Py_XDECREF(v); \ - } + while (STACK_LEVEL() > (b)->b_level) { \ + PyObject *v = POP(); \ + Py_XDECREF(v); \ + } #define UNWIND_EXCEPT_HANDLER(b) \ - { \ - PyObject *type, *value, *traceback; \ - assert(STACK_LEVEL() >= (b)->b_level + 3); \ - while (STACK_LEVEL() > (b)->b_level + 3) { \ - value = POP(); \ - Py_XDECREF(value); \ - } \ - type = tstate->exc_type; \ - value = tstate->exc_value; \ - traceback = tstate->exc_traceback; \ - tstate->exc_type = POP(); \ - tstate->exc_value = POP(); \ - tstate->exc_traceback = POP(); \ - Py_XDECREF(type); \ - Py_XDECREF(value); \ - Py_XDECREF(traceback); \ - } + { \ + PyObject *type, *value, *traceback; \ + assert(STACK_LEVEL() >= (b)->b_level + 3); \ + while (STACK_LEVEL() > (b)->b_level + 3) { \ + value = POP(); \ + Py_XDECREF(value); \ + } \ + type = tstate->exc_type; \ + value = tstate->exc_value; \ + traceback = tstate->exc_traceback; \ + tstate->exc_type = POP(); \ + tstate->exc_value = POP(); \ + tstate->exc_traceback = POP(); \ + Py_XDECREF(type); \ + Py_XDECREF(value); \ + Py_XDECREF(traceback); \ + } #define SAVE_EXC_STATE() \ - { \ - PyObject *type, *value, *traceback; \ - Py_XINCREF(tstate->exc_type); \ - Py_XINCREF(tstate->exc_value); \ - Py_XINCREF(tstate->exc_traceback); \ - type = f->f_exc_type; \ - value = f->f_exc_value; \ - traceback = f->f_exc_traceback; \ - f->f_exc_type = tstate->exc_type; \ - f->f_exc_value = tstate->exc_value; \ - f->f_exc_traceback = tstate->exc_traceback; \ - Py_XDECREF(type); \ - Py_XDECREF(value); \ - Py_XDECREF(traceback); \ - } + { \ + PyObject *type, *value, *traceback; \ + Py_XINCREF(tstate->exc_type); \ + Py_XINCREF(tstate->exc_value); \ + Py_XINCREF(tstate->exc_traceback); \ + type = f->f_exc_type; \ + value = f->f_exc_value; \ + traceback = f->f_exc_traceback; \ + f->f_exc_type = tstate->exc_type; \ + f->f_exc_value = tstate->exc_value; \ + f->f_exc_traceback = tstate->exc_traceback; \ + Py_XDECREF(type); \ + Py_XDECREF(value); \ + Py_XDECREF(traceback); \ + } #define SWAP_EXC_STATE() \ - { \ - PyObject *tmp; \ - tmp = tstate->exc_type; \ - tstate->exc_type = f->f_exc_type; \ - f->f_exc_type = tmp; \ - tmp = tstate->exc_value; \ - tstate->exc_value = f->f_exc_value; \ - f->f_exc_value = tmp; \ - tmp = tstate->exc_traceback; \ - tstate->exc_traceback = f->f_exc_traceback; \ - f->f_exc_traceback = tmp; \ - } + { \ + PyObject *tmp; \ + tmp = tstate->exc_type; \ + tstate->exc_type = f->f_exc_type; \ + f->f_exc_type = tmp; \ + tmp = tstate->exc_value; \ + tstate->exc_value = f->f_exc_value; \ + f->f_exc_value = tmp; \ + tmp = tstate->exc_traceback; \ + tstate->exc_traceback = f->f_exc_traceback; \ + f->f_exc_traceback = tmp; \ + } /* 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_protected(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_protected(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*) PyBytes_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. - - When the PREDICT() macros are enabled, some opcode pairs follow in - direct succession without updating f->f_lasti. A successful - prediction effectively links the two codes together as if they - were a single new opcode; accordingly,f->f_lasti will point to - the first code in the pair (for instance, GET_ITER followed by - FOR_ITER is effectively a single opcode and f->f_lasti will point - at to the beginning of the combined pair.) - */ - 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 */ - - if (co->co_flags & CO_GENERATOR && !throwflag) { - if (f->f_exc_type != NULL && f->f_exc_type != Py_None) { - /* We were in an except handler when we left, - restore the exception state which was put aside - (see YIELD_VALUE). */ - SWAP_EXC_STATE(); - } - else { - SAVE_EXC_STATE(); - } - } + 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_protected(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_protected(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*) PyBytes_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. + + When the PREDICT() macros are enabled, some opcode pairs follow in + direct succession without updating f->f_lasti. A successful + prediction effectively links the two codes together as if they + were a single new opcode; accordingly,f->f_lasti will point to + the first code in the pair (for instance, GET_ITER followed by + FOR_ITER is effectively a single opcode and f->f_lasti will point + at to the beginning of the combined pair.) + */ + 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 */ + + if (co->co_flags & CO_GENERATOR && !throwflag) { + if (f->f_exc_type != NULL && f->f_exc_type != Py_None) { + /* We were in an except handler when we left, + restore the exception state which was put aside + (see YIELD_VALUE). */ + SWAP_EXC_STATE(); + } + else { + SAVE_EXC_STATE(); + } + } #ifdef LLTRACE - lltrace = PyDict_GetItemString(f->f_globals, "__lltrace__") != NULL; + lltrace = PyDict_GetItemString(f->f_globals, "__lltrace__") != NULL; #endif #if defined(Py_DEBUG) || defined(LLTRACE) - filename = _PyUnicode_AsString(co->co_filename); + filename = _PyUnicode_AsString(co->co_filename); #endif - why = WHY_NOT; - err = 0; - x = Py_None; /* Not a reference, just anything non-NULL */ - w = NULL; + 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; - } + if (throwflag) { /* support for generator.throw() */ + why = WHY_EXCEPTION; + goto on_error; + } - for (;;) { + 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); + 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 - ``pendingcalls_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_atomic_load_relaxed(&eval_breaker)) { - if (*next_instr == SETUP_FINALLY) { - /* Make the last opcode before - a try: finally: block uninterruptable. */ - goto fast_next_opcode; - } - tstate->tick_counter++; + 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 + ``pendingcalls_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_atomic_load_relaxed(&eval_breaker)) { + if (*next_instr == SETUP_FINALLY) { + /* Make the last opcode before + a try: finally: block uninterruptable. */ + goto fast_next_opcode; + } + tstate->tick_counter++; #ifdef WITH_TSC - ticked = 1; + ticked = 1; #endif - if (_Py_atomic_load_relaxed(&pendingcalls_to_do)) { - if (Py_MakePendingCalls() < 0) { - why = WHY_EXCEPTION; - goto on_error; - } - } - if (_Py_atomic_load_relaxed(&gil_drop_request)) { + if (_Py_atomic_load_relaxed(&pendingcalls_to_do)) { + if (Py_MakePendingCalls() < 0) { + why = WHY_EXCEPTION; + goto on_error; + } + } + if (_Py_atomic_load_relaxed(&gil_drop_request)) { #ifdef WITH_THREAD - /* Give another thread a chance */ - if (PyThreadState_Swap(NULL) != tstate) - Py_FatalError("ceval: tstate mix-up"); - drop_gil(tstate); - - /* Other threads may run now */ - - take_gil(tstate); - if (PyThreadState_Swap(tstate) != NULL) - Py_FatalError("ceval: orphan tstate"); + /* Give another thread a chance */ + if (PyThreadState_Swap(NULL) != tstate) + Py_FatalError("ceval: tstate mix-up"); + drop_gil(tstate); + + /* Other threads may run now */ + + take_gil(tstate); + if (PyThreadState_Swap(tstate) != NULL) + Py_FatalError("ceval: orphan tstate"); #endif - } - /* Check for asynchronous exceptions. */ - if (tstate->async_exc != NULL) { - x = tstate->async_exc; - tstate->async_exc = NULL; - UNSIGNAL_ASYNC_EXC(); - PyErr_SetNone(x); - Py_DECREF(x); - why = WHY_EXCEPTION; - goto on_error; - } - } - - fast_next_opcode: - f->f_lasti = INSTR_OFFSET(); - - /* line-by-line tracing support */ - - if (_Py_TracingPossible && - 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: + } + /* Check for asynchronous exceptions. */ + if (tstate->async_exc != NULL) { + x = tstate->async_exc; + tstate->async_exc = NULL; + UNSIGNAL_ASYNC_EXC(); + PyErr_SetNone(x); + Py_DECREF(x); + why = WHY_EXCEPTION; + goto on_error; + } + } + + fast_next_opcode: + f->f_lasti = INSTR_OFFSET(); + + /* line-by-line tracing support */ + + if (_Py_TracingPossible && + 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; + dxpairs[lastopcode][opcode]++; + lastopcode = opcode; #endif - dxp[opcode]++; + 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); - } - } + /* 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! */ - - TARGET(NOP) - FAST_DISPATCH(); - - TARGET(LOAD_FAST) - x = GETLOCAL(oparg); - if (x != NULL) { - Py_INCREF(x); - PUSH(x); - FAST_DISPATCH(); - } - format_exc_check_arg(PyExc_UnboundLocalError, - UNBOUNDLOCAL_ERROR_MSG, - PyTuple_GetItem(co->co_varnames, oparg)); - break; - - TARGET(LOAD_CONST) - x = GETITEM(consts, oparg); - Py_INCREF(x); - PUSH(x); - FAST_DISPATCH(); - - PREDICTED_WITH_ARG(STORE_FAST); - TARGET(STORE_FAST) - v = POP(); - SETLOCAL(oparg, v); - FAST_DISPATCH(); - - TARGET(POP_TOP) - v = POP(); - Py_DECREF(v); - FAST_DISPATCH(); - - TARGET(ROT_TWO) - v = TOP(); - w = SECOND(); - SET_TOP(w); - SET_SECOND(v); - FAST_DISPATCH(); - - TARGET(ROT_THREE) - v = TOP(); - w = SECOND(); - x = THIRD(); - SET_TOP(w); - SET_SECOND(x); - SET_THIRD(v); - FAST_DISPATCH(); - - TARGET(ROT_FOUR) - u = TOP(); - v = SECOND(); - w = THIRD(); - x = FOURTH(); - SET_TOP(v); - SET_SECOND(w); - SET_THIRD(x); - SET_FOURTH(u); - FAST_DISPATCH(); - - TARGET(DUP_TOP) - v = TOP(); - Py_INCREF(v); - PUSH(v); - FAST_DISPATCH(); - - TARGET(DUP_TOPX) - if (oparg == 2) { - x = TOP(); - Py_INCREF(x); - w = SECOND(); - Py_INCREF(w); - STACKADJ(2); - SET_TOP(x); - SET_SECOND(w); - FAST_DISPATCH(); - } 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); - FAST_DISPATCH(); - } - Py_FatalError("invalid argument to DUP_TOPX" - " (bytecode corruption?)"); - /* Never returns, so don't bother to set why. */ - break; - - TARGET(UNARY_POSITIVE) - v = TOP(); - x = PyNumber_Positive(v); - Py_DECREF(v); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(UNARY_NEGATIVE) - v = TOP(); - x = PyNumber_Negative(v); - Py_DECREF(v); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(UNARY_NOT) - v = TOP(); - err = PyObject_IsTrue(v); - Py_DECREF(v); - if (err == 0) { - Py_INCREF(Py_True); - SET_TOP(Py_True); - DISPATCH(); - } - else if (err > 0) { - Py_INCREF(Py_False); - SET_TOP(Py_False); - err = 0; - DISPATCH(); - } - STACKADJ(-1); - break; - - TARGET(UNARY_INVERT) - v = TOP(); - x = PyNumber_Invert(v); - Py_DECREF(v); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(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) DISPATCH(); - break; - - TARGET(BINARY_MULTIPLY) - w = POP(); - v = TOP(); - x = PyNumber_Multiply(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(BINARY_TRUE_DIVIDE) - w = POP(); - v = TOP(); - x = PyNumber_TrueDivide(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(BINARY_FLOOR_DIVIDE) - w = POP(); - v = TOP(); - x = PyNumber_FloorDivide(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(BINARY_MODULO) - w = POP(); - v = TOP(); - if (PyUnicode_CheckExact(v)) - x = PyUnicode_Format(v, w); - else - x = PyNumber_Remainder(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(BINARY_ADD) - w = POP(); - v = TOP(); - if (PyUnicode_CheckExact(v) && - PyUnicode_CheckExact(w)) { - x = unicode_concatenate(v, w, f, next_instr); - /* unicode_concatenate consumed the ref to v */ - goto skip_decref_vx; - } - else { - x = PyNumber_Add(v, w); - } - Py_DECREF(v); - skip_decref_vx: - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(BINARY_SUBTRACT) - w = POP(); - v = TOP(); - x = PyNumber_Subtract(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(BINARY_SUBSCR) - w = POP(); - v = TOP(); - x = PyObject_GetItem(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(BINARY_LSHIFT) - w = POP(); - v = TOP(); - x = PyNumber_Lshift(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(BINARY_RSHIFT) - w = POP(); - v = TOP(); - x = PyNumber_Rshift(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(BINARY_AND) - w = POP(); - v = TOP(); - x = PyNumber_And(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(BINARY_XOR) - w = POP(); - v = TOP(); - x = PyNumber_Xor(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(BINARY_OR) - w = POP(); - v = TOP(); - x = PyNumber_Or(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(LIST_APPEND) - w = POP(); - v = PEEK(oparg); - err = PyList_Append(v, w); - Py_DECREF(w); - if (err == 0) { - PREDICT(JUMP_ABSOLUTE); - DISPATCH(); - } - break; - - TARGET(SET_ADD) - w = POP(); - v = stack_pointer[-oparg]; - err = PySet_Add(v, w); - Py_DECREF(w); - if (err == 0) { - PREDICT(JUMP_ABSOLUTE); - DISPATCH(); - } - break; - - TARGET(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) DISPATCH(); - break; - - TARGET(INPLACE_MULTIPLY) - w = POP(); - v = TOP(); - x = PyNumber_InPlaceMultiply(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(INPLACE_TRUE_DIVIDE) - w = POP(); - v = TOP(); - x = PyNumber_InPlaceTrueDivide(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(INPLACE_FLOOR_DIVIDE) - w = POP(); - v = TOP(); - x = PyNumber_InPlaceFloorDivide(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(INPLACE_MODULO) - w = POP(); - v = TOP(); - x = PyNumber_InPlaceRemainder(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(INPLACE_ADD) - w = POP(); - v = TOP(); - if (PyUnicode_CheckExact(v) && - PyUnicode_CheckExact(w)) { - x = unicode_concatenate(v, w, f, next_instr); - /* unicode_concatenate consumed the ref to v */ - goto skip_decref_v; - } - else { - x = PyNumber_InPlaceAdd(v, w); - } - Py_DECREF(v); - skip_decref_v: - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(INPLACE_SUBTRACT) - w = POP(); - v = TOP(); - x = PyNumber_InPlaceSubtract(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(INPLACE_LSHIFT) - w = POP(); - v = TOP(); - x = PyNumber_InPlaceLshift(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(INPLACE_RSHIFT) - w = POP(); - v = TOP(); - x = PyNumber_InPlaceRshift(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(INPLACE_AND) - w = POP(); - v = TOP(); - x = PyNumber_InPlaceAnd(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(INPLACE_XOR) - w = POP(); - v = TOP(); - x = PyNumber_InPlaceXor(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(INPLACE_OR) - w = POP(); - v = TOP(); - x = PyNumber_InPlaceOr(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(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) DISPATCH(); - break; - - TARGET(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) DISPATCH(); - break; - - TARGET(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; + /* 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! */ + + TARGET(NOP) + FAST_DISPATCH(); + + TARGET(LOAD_FAST) + x = GETLOCAL(oparg); + if (x != NULL) { + Py_INCREF(x); + PUSH(x); + FAST_DISPATCH(); + } + format_exc_check_arg(PyExc_UnboundLocalError, + UNBOUNDLOCAL_ERROR_MSG, + PyTuple_GetItem(co->co_varnames, oparg)); + break; + + TARGET(LOAD_CONST) + x = GETITEM(consts, oparg); + Py_INCREF(x); + PUSH(x); + FAST_DISPATCH(); + + PREDICTED_WITH_ARG(STORE_FAST); + TARGET(STORE_FAST) + v = POP(); + SETLOCAL(oparg, v); + FAST_DISPATCH(); + + TARGET(POP_TOP) + v = POP(); + Py_DECREF(v); + FAST_DISPATCH(); + + TARGET(ROT_TWO) + v = TOP(); + w = SECOND(); + SET_TOP(w); + SET_SECOND(v); + FAST_DISPATCH(); + + TARGET(ROT_THREE) + v = TOP(); + w = SECOND(); + x = THIRD(); + SET_TOP(w); + SET_SECOND(x); + SET_THIRD(v); + FAST_DISPATCH(); + + TARGET(ROT_FOUR) + u = TOP(); + v = SECOND(); + w = THIRD(); + x = FOURTH(); + SET_TOP(v); + SET_SECOND(w); + SET_THIRD(x); + SET_FOURTH(u); + FAST_DISPATCH(); + + TARGET(DUP_TOP) + v = TOP(); + Py_INCREF(v); + PUSH(v); + FAST_DISPATCH(); + + TARGET(DUP_TOPX) + if (oparg == 2) { + x = TOP(); + Py_INCREF(x); + w = SECOND(); + Py_INCREF(w); + STACKADJ(2); + SET_TOP(x); + SET_SECOND(w); + FAST_DISPATCH(); + } 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); + FAST_DISPATCH(); + } + Py_FatalError("invalid argument to DUP_TOPX" + " (bytecode corruption?)"); + /* Never returns, so don't bother to set why. */ + break; + + TARGET(UNARY_POSITIVE) + v = TOP(); + x = PyNumber_Positive(v); + Py_DECREF(v); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(UNARY_NEGATIVE) + v = TOP(); + x = PyNumber_Negative(v); + Py_DECREF(v); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(UNARY_NOT) + v = TOP(); + err = PyObject_IsTrue(v); + Py_DECREF(v); + if (err == 0) { + Py_INCREF(Py_True); + SET_TOP(Py_True); + DISPATCH(); + } + else if (err > 0) { + Py_INCREF(Py_False); + SET_TOP(Py_False); + err = 0; + DISPATCH(); + } + STACKADJ(-1); + break; + + TARGET(UNARY_INVERT) + v = TOP(); + x = PyNumber_Invert(v); + Py_DECREF(v); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(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) DISPATCH(); + break; + + TARGET(BINARY_MULTIPLY) + w = POP(); + v = TOP(); + x = PyNumber_Multiply(v, w); + Py_DECREF(v); + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(BINARY_TRUE_DIVIDE) + w = POP(); + v = TOP(); + x = PyNumber_TrueDivide(v, w); + Py_DECREF(v); + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(BINARY_FLOOR_DIVIDE) + w = POP(); + v = TOP(); + x = PyNumber_FloorDivide(v, w); + Py_DECREF(v); + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(BINARY_MODULO) + w = POP(); + v = TOP(); + if (PyUnicode_CheckExact(v)) + x = PyUnicode_Format(v, w); + else + x = PyNumber_Remainder(v, w); + Py_DECREF(v); + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(BINARY_ADD) + w = POP(); + v = TOP(); + if (PyUnicode_CheckExact(v) && + PyUnicode_CheckExact(w)) { + x = unicode_concatenate(v, w, f, next_instr); + /* unicode_concatenate consumed the ref to v */ + goto skip_decref_vx; + } + else { + x = PyNumber_Add(v, w); + } + Py_DECREF(v); + skip_decref_vx: + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(BINARY_SUBTRACT) + w = POP(); + v = TOP(); + x = PyNumber_Subtract(v, w); + Py_DECREF(v); + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(BINARY_SUBSCR) + w = POP(); + v = TOP(); + x = PyObject_GetItem(v, w); + Py_DECREF(v); + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(BINARY_LSHIFT) + w = POP(); + v = TOP(); + x = PyNumber_Lshift(v, w); + Py_DECREF(v); + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(BINARY_RSHIFT) + w = POP(); + v = TOP(); + x = PyNumber_Rshift(v, w); + Py_DECREF(v); + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(BINARY_AND) + w = POP(); + v = TOP(); + x = PyNumber_And(v, w); + Py_DECREF(v); + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(BINARY_XOR) + w = POP(); + v = TOP(); + x = PyNumber_Xor(v, w); + Py_DECREF(v); + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(BINARY_OR) + w = POP(); + v = TOP(); + x = PyNumber_Or(v, w); + Py_DECREF(v); + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(LIST_APPEND) + w = POP(); + v = PEEK(oparg); + err = PyList_Append(v, w); + Py_DECREF(w); + if (err == 0) { + PREDICT(JUMP_ABSOLUTE); + DISPATCH(); + } + break; + + TARGET(SET_ADD) + w = POP(); + v = stack_pointer[-oparg]; + err = PySet_Add(v, w); + Py_DECREF(w); + if (err == 0) { + PREDICT(JUMP_ABSOLUTE); + DISPATCH(); + } + break; + + TARGET(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) DISPATCH(); + break; + + TARGET(INPLACE_MULTIPLY) + w = POP(); + v = TOP(); + x = PyNumber_InPlaceMultiply(v, w); + Py_DECREF(v); + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(INPLACE_TRUE_DIVIDE) + w = POP(); + v = TOP(); + x = PyNumber_InPlaceTrueDivide(v, w); + Py_DECREF(v); + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(INPLACE_FLOOR_DIVIDE) + w = POP(); + v = TOP(); + x = PyNumber_InPlaceFloorDivide(v, w); + Py_DECREF(v); + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(INPLACE_MODULO) + w = POP(); + v = TOP(); + x = PyNumber_InPlaceRemainder(v, w); + Py_DECREF(v); + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(INPLACE_ADD) + w = POP(); + v = TOP(); + if (PyUnicode_CheckExact(v) && + PyUnicode_CheckExact(w)) { + x = unicode_concatenate(v, w, f, next_instr); + /* unicode_concatenate consumed the ref to v */ + goto skip_decref_v; + } + else { + x = PyNumber_InPlaceAdd(v, w); + } + Py_DECREF(v); + skip_decref_v: + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(INPLACE_SUBTRACT) + w = POP(); + v = TOP(); + x = PyNumber_InPlaceSubtract(v, w); + Py_DECREF(v); + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(INPLACE_LSHIFT) + w = POP(); + v = TOP(); + x = PyNumber_InPlaceLshift(v, w); + Py_DECREF(v); + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(INPLACE_RSHIFT) + w = POP(); + v = TOP(); + x = PyNumber_InPlaceRshift(v, w); + Py_DECREF(v); + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(INPLACE_AND) + w = POP(); + v = TOP(); + x = PyNumber_InPlaceAnd(v, w); + Py_DECREF(v); + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(INPLACE_XOR) + w = POP(); + v = TOP(); + x = PyNumber_InPlaceXor(v, w); + Py_DECREF(v); + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(INPLACE_OR) + w = POP(); + v = TOP(); + x = PyNumber_InPlaceOr(v, w); + Py_DECREF(v); + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(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) DISPATCH(); + break; + + TARGET(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) DISPATCH(); + break; + + TARGET(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; #ifdef CASE_TOO_BIG - default: switch (opcode) { + default: switch (opcode) { #endif - TARGET(RAISE_VARARGS) - v = w = NULL; - switch (oparg) { - case 2: - v = POP(); /* cause */ - case 1: - w = POP(); /* exc */ - case 0: /* Fallthrough */ - why = do_raise(w, v); - break; - default: - PyErr_SetString(PyExc_SystemError, - "bad RAISE_VARARGS oparg"); - why = WHY_EXCEPTION; - break; - } - break; - - TARGET(STORE_LOCALS) - x = POP(); - v = f->f_locals; - Py_XDECREF(v); - f->f_locals = x; - DISPATCH(); - - TARGET(RETURN_VALUE) - retval = POP(); - why = WHY_RETURN; - goto fast_block_end; - - TARGET(YIELD_VALUE) - retval = POP(); - f->f_stacktop = stack_pointer; - why = WHY_YIELD; - /* Put aside the current exception state and restore - that of the calling frame. This only serves when - "yield" is used inside an except handler. */ - SWAP_EXC_STATE(); - goto fast_yield; - - TARGET(POP_EXCEPT) - { - PyTryBlock *b = PyFrame_BlockPop(f); - if (b->b_type != EXCEPT_HANDLER) { - PyErr_SetString(PyExc_SystemError, - "popped block is not an except handler"); - why = WHY_EXCEPTION; - break; - } - UNWIND_EXCEPT_HANDLER(b); - } - DISPATCH(); - - TARGET(POP_BLOCK) - { - PyTryBlock *b = PyFrame_BlockPop(f); - UNWIND_BLOCK(b); - } - DISPATCH(); - - PREDICTED(END_FINALLY); - TARGET(END_FINALLY) - v = POP(); - if (PyLong_Check(v)) { - why = (enum why_code) PyLong_AS_LONG(v); - assert(why != WHY_YIELD); - if (why == WHY_RETURN || - why == WHY_CONTINUE) - retval = POP(); - if (why == WHY_SILENCED) { - /* An exception was silenced by 'with', we must - manually unwind the EXCEPT_HANDLER block which was - created when the exception was caught, otherwise - the stack will be in an inconsistent state. */ - PyTryBlock *b = PyFrame_BlockPop(f); - assert(b->b_type == EXCEPT_HANDLER); - UNWIND_EXCEPT_HANDLER(b); - why = WHY_NOT; - } - } - else if (PyExceptionClass_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; - - TARGET(LOAD_BUILD_CLASS) - x = PyDict_GetItemString(f->f_builtins, - "__build_class__"); - if (x == NULL) { - PyErr_SetString(PyExc_ImportError, - "__build_class__ not found"); - break; - } - Py_INCREF(x); - PUSH(x); - break; - - TARGET(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) DISPATCH(); - break; - } - PyErr_Format(PyExc_SystemError, - "no locals found when storing %R", w); - break; - - TARGET(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 %R", w); - break; - - PREDICTED_WITH_ARG(UNPACK_SEQUENCE); - TARGET(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); - DISPATCH(); - } 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, -1, - stack_pointer + oparg)) { - STACKADJ(oparg); - } else { - /* unpack_iterable() raised an exception */ - why = WHY_EXCEPTION; - } - Py_DECREF(v); - break; - - TARGET(UNPACK_EX) - { - int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8); - v = POP(); - - if (unpack_iterable(v, oparg & 0xFF, oparg >> 8, - stack_pointer + totalargs)) { - stack_pointer += totalargs; - } else { - why = WHY_EXCEPTION; - } - Py_DECREF(v); - break; - } - - TARGET(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) DISPATCH(); - break; - - TARGET(DELETE_ATTR) - w = GETITEM(names, oparg); - v = POP(); - err = PyObject_SetAttr(v, w, (PyObject *)NULL); - /* del v.w */ - Py_DECREF(v); - break; - - TARGET(STORE_GLOBAL) - w = GETITEM(names, oparg); - v = POP(); - err = PyDict_SetItem(f->f_globals, w, v); - Py_DECREF(v); - if (err == 0) DISPATCH(); - break; - - TARGET(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; - - TARGET(LOAD_NAME) - w = GETITEM(names, oparg); - if ((v = f->f_locals) == NULL) { - PyErr_Format(PyExc_SystemError, - "no locals when loading %R", w); - why = WHY_EXCEPTION; - 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); - DISPATCH(); - - TARGET(LOAD_GLOBAL) - w = GETITEM(names, oparg); - if (PyUnicode_CheckExact(w)) { - /* Inline the PyDict_GetItem() calls. - WARNING: this is an extreme speed hack. - Do not try this at home. */ - long hash = ((PyUnicodeObject *)w)->hash; - 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); - DISPATCH(); - } - 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); - DISPATCH(); - } - 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); - DISPATCH(); - - TARGET(DELETE_FAST) - x = GETLOCAL(oparg); - if (x != NULL) { - SETLOCAL(oparg, NULL); - DISPATCH(); - } - format_exc_check_arg( - PyExc_UnboundLocalError, - UNBOUNDLOCAL_ERROR_MSG, - PyTuple_GetItem(co->co_varnames, oparg) - ); - break; - - TARGET(LOAD_CLOSURE) - x = freevars[oparg]; - Py_INCREF(x); - PUSH(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(LOAD_DEREF) - x = freevars[oparg]; - w = PyCell_Get(x); - if (w != NULL) { - PUSH(w); - DISPATCH(); - } - 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; - - TARGET(STORE_DEREF) - w = POP(); - x = freevars[oparg]; - PyCell_Set(x, w); - Py_DECREF(w); - DISPATCH(); - - TARGET(BUILD_TUPLE) - x = PyTuple_New(oparg); - if (x != NULL) { - for (; --oparg >= 0;) { - w = POP(); - PyTuple_SET_ITEM(x, oparg, w); - } - PUSH(x); - DISPATCH(); - } - break; - - TARGET(BUILD_LIST) - x = PyList_New(oparg); - if (x != NULL) { - for (; --oparg >= 0;) { - w = POP(); - PyList_SET_ITEM(x, oparg, w); - } - PUSH(x); - DISPATCH(); - } - break; - - TARGET(BUILD_SET) - x = PySet_New(NULL); - if (x != NULL) { - for (; --oparg >= 0;) { - w = POP(); - if (err == 0) - err = PySet_Add(x, w); - Py_DECREF(w); - } - if (err != 0) { - Py_DECREF(x); - break; - } - PUSH(x); - DISPATCH(); - } - break; - - TARGET(BUILD_MAP) - x = _PyDict_NewPresized((Py_ssize_t)oparg); - PUSH(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(STORE_MAP) - w = TOP(); /* key */ - u = SECOND(); /* value */ - v = THIRD(); /* dict */ - STACKADJ(-2); - assert (PyDict_CheckExact(v)); - err = PyDict_SetItem(v, w, u); /* v[w] = u */ - Py_DECREF(u); - Py_DECREF(w); - if (err == 0) DISPATCH(); - break; - - TARGET(MAP_ADD) - w = TOP(); /* key */ - u = SECOND(); /* value */ - STACKADJ(-2); - v = stack_pointer[-oparg]; /* dict */ - assert (PyDict_CheckExact(v)); - err = PyDict_SetItem(v, w, u); /* v[w] = u */ - Py_DECREF(u); - Py_DECREF(w); - if (err == 0) { - PREDICT(JUMP_ABSOLUTE); - DISPATCH(); - } - break; - - TARGET(LOAD_ATTR) - w = GETITEM(names, oparg); - v = TOP(); - x = PyObject_GetAttr(v, w); - Py_DECREF(v); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(COMPARE_OP) - w = POP(); - v = TOP(); - x = cmp_outcome(oparg, v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x == NULL) break; - PREDICT(POP_JUMP_IF_FALSE); - PREDICT(POP_JUMP_IF_TRUE); - DISPATCH(); - - TARGET(IMPORT_NAME) - w = GETITEM(names, oparg); - x = PyDict_GetItemString(f->f_builtins, "__import__"); - if (x == NULL) { - PyErr_SetString(PyExc_ImportError, - "__import__ not found"); - break; - } - Py_INCREF(x); - v = POP(); - u = TOP(); - if (PyLong_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(); - Py_DECREF(x); - x = NULL; - break; - } - READ_TIMESTAMP(intr0); - v = x; - x = PyEval_CallObject(v, w); - Py_DECREF(v); - READ_TIMESTAMP(intr1); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(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) DISPATCH(); - break; - - TARGET(IMPORT_FROM) - w = GETITEM(names, oparg); - v = TOP(); - READ_TIMESTAMP(intr0); - x = import_from(v, w); - READ_TIMESTAMP(intr1); - PUSH(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(JUMP_FORWARD) - JUMPBY(oparg); - FAST_DISPATCH(); - - PREDICTED_WITH_ARG(POP_JUMP_IF_FALSE); - TARGET(POP_JUMP_IF_FALSE) - w = POP(); - if (w == Py_True) { - Py_DECREF(w); - FAST_DISPATCH(); - } - if (w == Py_False) { - Py_DECREF(w); - JUMPTO(oparg); - FAST_DISPATCH(); - } - err = PyObject_IsTrue(w); - Py_DECREF(w); - if (err > 0) - err = 0; - else if (err == 0) - JUMPTO(oparg); - else - break; - DISPATCH(); - - PREDICTED_WITH_ARG(POP_JUMP_IF_TRUE); - TARGET(POP_JUMP_IF_TRUE) - w = POP(); - if (w == Py_False) { - Py_DECREF(w); - FAST_DISPATCH(); - } - if (w == Py_True) { - Py_DECREF(w); - JUMPTO(oparg); - FAST_DISPATCH(); - } - err = PyObject_IsTrue(w); - Py_DECREF(w); - if (err > 0) { - err = 0; - JUMPTO(oparg); - } - else if (err == 0) - ; - else - break; - DISPATCH(); - - TARGET(JUMP_IF_FALSE_OR_POP) - w = TOP(); - if (w == Py_True) { - STACKADJ(-1); - Py_DECREF(w); - FAST_DISPATCH(); - } - if (w == Py_False) { - JUMPTO(oparg); - FAST_DISPATCH(); - } - err = PyObject_IsTrue(w); - if (err > 0) { - STACKADJ(-1); - Py_DECREF(w); - err = 0; - } - else if (err == 0) - JUMPTO(oparg); - else - break; - DISPATCH(); - - TARGET(JUMP_IF_TRUE_OR_POP) - w = TOP(); - if (w == Py_False) { - STACKADJ(-1); - Py_DECREF(w); - FAST_DISPATCH(); - } - if (w == Py_True) { - JUMPTO(oparg); - FAST_DISPATCH(); - } - err = PyObject_IsTrue(w); - if (err > 0) { - err = 0; - JUMPTO(oparg); - } - else if (err == 0) { - STACKADJ(-1); - Py_DECREF(w); - } - else - break; - DISPATCH(); - - PREDICTED_WITH_ARG(JUMP_ABSOLUTE); - TARGET(JUMP_ABSOLUTE) - JUMPTO(oparg); + TARGET(RAISE_VARARGS) + v = w = NULL; + switch (oparg) { + case 2: + v = POP(); /* cause */ + case 1: + w = POP(); /* exc */ + case 0: /* Fallthrough */ + why = do_raise(w, v); + break; + default: + PyErr_SetString(PyExc_SystemError, + "bad RAISE_VARARGS oparg"); + why = WHY_EXCEPTION; + break; + } + break; + + TARGET(STORE_LOCALS) + x = POP(); + v = f->f_locals; + Py_XDECREF(v); + f->f_locals = x; + DISPATCH(); + + TARGET(RETURN_VALUE) + retval = POP(); + why = WHY_RETURN; + goto fast_block_end; + + TARGET(YIELD_VALUE) + retval = POP(); + f->f_stacktop = stack_pointer; + why = WHY_YIELD; + /* Put aside the current exception state and restore + that of the calling frame. This only serves when + "yield" is used inside an except handler. */ + SWAP_EXC_STATE(); + goto fast_yield; + + TARGET(POP_EXCEPT) + { + PyTryBlock *b = PyFrame_BlockPop(f); + if (b->b_type != EXCEPT_HANDLER) { + PyErr_SetString(PyExc_SystemError, + "popped block is not an except handler"); + why = WHY_EXCEPTION; + break; + } + UNWIND_EXCEPT_HANDLER(b); + } + DISPATCH(); + + TARGET(POP_BLOCK) + { + PyTryBlock *b = PyFrame_BlockPop(f); + UNWIND_BLOCK(b); + } + DISPATCH(); + + PREDICTED(END_FINALLY); + TARGET(END_FINALLY) + v = POP(); + if (PyLong_Check(v)) { + why = (enum why_code) PyLong_AS_LONG(v); + assert(why != WHY_YIELD); + if (why == WHY_RETURN || + why == WHY_CONTINUE) + retval = POP(); + if (why == WHY_SILENCED) { + /* An exception was silenced by 'with', we must + manually unwind the EXCEPT_HANDLER block which was + created when the exception was caught, otherwise + the stack will be in an inconsistent state. */ + PyTryBlock *b = PyFrame_BlockPop(f); + assert(b->b_type == EXCEPT_HANDLER); + UNWIND_EXCEPT_HANDLER(b); + why = WHY_NOT; + } + } + else if (PyExceptionClass_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; + + TARGET(LOAD_BUILD_CLASS) + x = PyDict_GetItemString(f->f_builtins, + "__build_class__"); + if (x == NULL) { + PyErr_SetString(PyExc_ImportError, + "__build_class__ not found"); + break; + } + Py_INCREF(x); + PUSH(x); + break; + + TARGET(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) DISPATCH(); + break; + } + PyErr_Format(PyExc_SystemError, + "no locals found when storing %R", w); + break; + + TARGET(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 %R", w); + break; + + PREDICTED_WITH_ARG(UNPACK_SEQUENCE); + TARGET(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); + DISPATCH(); + } 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, -1, + stack_pointer + oparg)) { + STACKADJ(oparg); + } else { + /* unpack_iterable() raised an exception */ + why = WHY_EXCEPTION; + } + Py_DECREF(v); + break; + + TARGET(UNPACK_EX) + { + int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8); + v = POP(); + + if (unpack_iterable(v, oparg & 0xFF, oparg >> 8, + stack_pointer + totalargs)) { + stack_pointer += totalargs; + } else { + why = WHY_EXCEPTION; + } + Py_DECREF(v); + break; + } + + TARGET(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) DISPATCH(); + break; + + TARGET(DELETE_ATTR) + w = GETITEM(names, oparg); + v = POP(); + err = PyObject_SetAttr(v, w, (PyObject *)NULL); + /* del v.w */ + Py_DECREF(v); + break; + + TARGET(STORE_GLOBAL) + w = GETITEM(names, oparg); + v = POP(); + err = PyDict_SetItem(f->f_globals, w, v); + Py_DECREF(v); + if (err == 0) DISPATCH(); + break; + + TARGET(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; + + TARGET(LOAD_NAME) + w = GETITEM(names, oparg); + if ((v = f->f_locals) == NULL) { + PyErr_Format(PyExc_SystemError, + "no locals when loading %R", w); + why = WHY_EXCEPTION; + 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); + DISPATCH(); + + TARGET(LOAD_GLOBAL) + w = GETITEM(names, oparg); + if (PyUnicode_CheckExact(w)) { + /* Inline the PyDict_GetItem() calls. + WARNING: this is an extreme speed hack. + Do not try this at home. */ + long hash = ((PyUnicodeObject *)w)->hash; + 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); + DISPATCH(); + } + 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); + DISPATCH(); + } + 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); + DISPATCH(); + + TARGET(DELETE_FAST) + x = GETLOCAL(oparg); + if (x != NULL) { + SETLOCAL(oparg, NULL); + DISPATCH(); + } + format_exc_check_arg( + PyExc_UnboundLocalError, + UNBOUNDLOCAL_ERROR_MSG, + PyTuple_GetItem(co->co_varnames, oparg) + ); + break; + + TARGET(LOAD_CLOSURE) + x = freevars[oparg]; + Py_INCREF(x); + PUSH(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(LOAD_DEREF) + x = freevars[oparg]; + w = PyCell_Get(x); + if (w != NULL) { + PUSH(w); + DISPATCH(); + } + 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; + + TARGET(STORE_DEREF) + w = POP(); + x = freevars[oparg]; + PyCell_Set(x, w); + Py_DECREF(w); + DISPATCH(); + + TARGET(BUILD_TUPLE) + x = PyTuple_New(oparg); + if (x != NULL) { + for (; --oparg >= 0;) { + w = POP(); + PyTuple_SET_ITEM(x, oparg, w); + } + PUSH(x); + DISPATCH(); + } + break; + + TARGET(BUILD_LIST) + x = PyList_New(oparg); + if (x != NULL) { + for (; --oparg >= 0;) { + w = POP(); + PyList_SET_ITEM(x, oparg, w); + } + PUSH(x); + DISPATCH(); + } + break; + + TARGET(BUILD_SET) + x = PySet_New(NULL); + if (x != NULL) { + for (; --oparg >= 0;) { + w = POP(); + if (err == 0) + err = PySet_Add(x, w); + Py_DECREF(w); + } + if (err != 0) { + Py_DECREF(x); + break; + } + PUSH(x); + DISPATCH(); + } + break; + + TARGET(BUILD_MAP) + x = _PyDict_NewPresized((Py_ssize_t)oparg); + PUSH(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(STORE_MAP) + w = TOP(); /* key */ + u = SECOND(); /* value */ + v = THIRD(); /* dict */ + STACKADJ(-2); + assert (PyDict_CheckExact(v)); + err = PyDict_SetItem(v, w, u); /* v[w] = u */ + Py_DECREF(u); + Py_DECREF(w); + if (err == 0) DISPATCH(); + break; + + TARGET(MAP_ADD) + w = TOP(); /* key */ + u = SECOND(); /* value */ + STACKADJ(-2); + v = stack_pointer[-oparg]; /* dict */ + assert (PyDict_CheckExact(v)); + err = PyDict_SetItem(v, w, u); /* v[w] = u */ + Py_DECREF(u); + Py_DECREF(w); + if (err == 0) { + PREDICT(JUMP_ABSOLUTE); + DISPATCH(); + } + break; + + TARGET(LOAD_ATTR) + w = GETITEM(names, oparg); + v = TOP(); + x = PyObject_GetAttr(v, w); + Py_DECREF(v); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(COMPARE_OP) + w = POP(); + v = TOP(); + x = cmp_outcome(oparg, v, w); + Py_DECREF(v); + Py_DECREF(w); + SET_TOP(x); + if (x == NULL) break; + PREDICT(POP_JUMP_IF_FALSE); + PREDICT(POP_JUMP_IF_TRUE); + DISPATCH(); + + TARGET(IMPORT_NAME) + w = GETITEM(names, oparg); + x = PyDict_GetItemString(f->f_builtins, "__import__"); + if (x == NULL) { + PyErr_SetString(PyExc_ImportError, + "__import__ not found"); + break; + } + Py_INCREF(x); + v = POP(); + u = TOP(); + if (PyLong_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(); + Py_DECREF(x); + x = NULL; + break; + } + READ_TIMESTAMP(intr0); + v = x; + x = PyEval_CallObject(v, w); + Py_DECREF(v); + READ_TIMESTAMP(intr1); + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(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) DISPATCH(); + break; + + TARGET(IMPORT_FROM) + w = GETITEM(names, oparg); + v = TOP(); + READ_TIMESTAMP(intr0); + x = import_from(v, w); + READ_TIMESTAMP(intr1); + PUSH(x); + if (x != NULL) DISPATCH(); + break; + + TARGET(JUMP_FORWARD) + JUMPBY(oparg); + FAST_DISPATCH(); + + PREDICTED_WITH_ARG(POP_JUMP_IF_FALSE); + TARGET(POP_JUMP_IF_FALSE) + w = POP(); + if (w == Py_True) { + Py_DECREF(w); + FAST_DISPATCH(); + } + if (w == Py_False) { + Py_DECREF(w); + JUMPTO(oparg); + FAST_DISPATCH(); + } + err = PyObject_IsTrue(w); + Py_DECREF(w); + if (err > 0) + err = 0; + else if (err == 0) + JUMPTO(oparg); + else + break; + DISPATCH(); + + PREDICTED_WITH_ARG(POP_JUMP_IF_TRUE); + TARGET(POP_JUMP_IF_TRUE) + w = POP(); + if (w == Py_False) { + Py_DECREF(w); + FAST_DISPATCH(); + } + if (w == Py_True) { + Py_DECREF(w); + JUMPTO(oparg); + FAST_DISPATCH(); + } + err = PyObject_IsTrue(w); + Py_DECREF(w); + if (err > 0) { + err = 0; + JUMPTO(oparg); + } + else if (err == 0) + ; + else + break; + DISPATCH(); + + TARGET(JUMP_IF_FALSE_OR_POP) + w = TOP(); + if (w == Py_True) { + STACKADJ(-1); + Py_DECREF(w); + FAST_DISPATCH(); + } + if (w == Py_False) { + JUMPTO(oparg); + FAST_DISPATCH(); + } + err = PyObject_IsTrue(w); + if (err > 0) { + STACKADJ(-1); + Py_DECREF(w); + err = 0; + } + else if (err == 0) + JUMPTO(oparg); + else + break; + DISPATCH(); + + TARGET(JUMP_IF_TRUE_OR_POP) + w = TOP(); + if (w == Py_False) { + STACKADJ(-1); + Py_DECREF(w); + FAST_DISPATCH(); + } + if (w == Py_True) { + JUMPTO(oparg); + FAST_DISPATCH(); + } + err = PyObject_IsTrue(w); + if (err > 0) { + err = 0; + JUMPTO(oparg); + } + else if (err == 0) { + STACKADJ(-1); + Py_DECREF(w); + } + else + break; + DISPATCH(); + + PREDICTED_WITH_ARG(JUMP_ABSOLUTE); + TARGET(JUMP_ABSOLUTE) + JUMPTO(oparg); #if FAST_LOOPS - /* Enabling this path speeds-up all while and for-loops by bypassing - the per-loop checks for signals. By default, this should be turned-off - because it prevents detection of a control-break in tight loops like - "while 1: pass". Compile with this option turned-on when you need - the speed-up and do not need break checking inside tight loops (ones - that contain only instructions ending with FAST_DISPATCH). - */ - FAST_DISPATCH(); + /* Enabling this path speeds-up all while and for-loops by bypassing + the per-loop checks for signals. By default, this should be turned-off + because it prevents detection of a control-break in tight loops like + "while 1: pass". Compile with this option turned-on when you need + the speed-up and do not need break checking inside tight loops (ones + that contain only instructions ending with FAST_DISPATCH). + */ + FAST_DISPATCH(); #else - DISPATCH(); + DISPATCH(); #endif - TARGET(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); - DISPATCH(); - } - STACKADJ(-1); - break; - - PREDICTED_WITH_ARG(FOR_ITER); - TARGET(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); - DISPATCH(); - } - if (PyErr_Occurred()) { - if (!PyErr_ExceptionMatches( - PyExc_StopIteration)) - break; - PyErr_Clear(); - } - /* iterator ended normally */ - x = v = POP(); - Py_DECREF(v); - JUMPBY(oparg); - DISPATCH(); - - TARGET(BREAK_LOOP) - why = WHY_BREAK; - goto fast_block_end; - - TARGET(CONTINUE_LOOP) - retval = PyLong_FromLong(oparg); - if (!retval) { - x = NULL; - break; - } - why = WHY_CONTINUE; - goto fast_block_end; - - TARGET_WITH_IMPL(SETUP_LOOP, _setup_finally) - TARGET_WITH_IMPL(SETUP_EXCEPT, _setup_finally) - TARGET(SETUP_FINALLY) - _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()); - DISPATCH(); - - TARGET(SETUP_WITH) - { - static PyObject *exit, *enter; - w = TOP(); - x = special_lookup(w, "__exit__", &exit); - if (!x) - break; - SET_TOP(x); - u = special_lookup(w, "__enter__", &enter); - Py_DECREF(w); - if (!u) { - x = NULL; - break; - } - x = PyObject_CallFunctionObjArgs(u, NULL); - Py_DECREF(u); - if (!x) - break; - /* Setup the finally block before pushing the result - of __enter__ on the stack. */ - PyFrame_BlockSetup(f, SETUP_FINALLY, INSTR_OFFSET() + oparg, - STACK_LEVEL()); - - PUSH(x); - DISPATCH(); - } - - TARGET(WITH_CLEANUP) - { - /* At the top of the stack are 1-3 values indicating - how/why we entered the finally clause: - - TOP = None - - (TOP, SECOND) = (WHY_{RETURN,CONTINUE}), retval - - TOP = WHY_*; no retval below it - - (TOP, SECOND, THIRD) = exc_info() - (FOURTH, FITH, SIXTH) = previous exception for EXCEPT_HANDLER - Below them is EXIT, the context.__exit__ bound method. - In the last case, we must call - EXIT(TOP, SECOND, THIRD) - otherwise we must call - EXIT(None, None, None) - - In the first two cases, we remove EXIT from the - stack, leaving the rest in the same order. In the - third case, we shift the bottom 3 values of the - stack down, and replace the empty spot with NULL. - - In addition, if the stack represents an exception, - *and* the function call returns a 'true' value, we - push WHY_SILENCED onto the stack. END_FINALLY will - then not re-raise the exception. (But non-local - gotos should still be resumed.) - */ - - PyObject *exit_func; - u = TOP(); - if (u == Py_None) { - (void)POP(); - exit_func = TOP(); - SET_TOP(u); - v = w = Py_None; - } - else if (PyLong_Check(u)) { - (void)POP(); - switch(PyLong_AsLong(u)) { - case WHY_RETURN: - case WHY_CONTINUE: - /* Retval in TOP. */ - exit_func = SECOND(); - SET_SECOND(TOP()); - SET_TOP(u); - break; - default: - exit_func = TOP(); - SET_TOP(u); - break; - } - u = v = w = Py_None; - } - else { - PyObject *tp, *exc, *tb; - PyTryBlock *block; - v = SECOND(); - w = THIRD(); - tp = FOURTH(); - exc = PEEK(5); - tb = PEEK(6); - exit_func = PEEK(7); - SET_VALUE(7, tb); - SET_VALUE(6, exc); - SET_VALUE(5, tp); - /* UNWIND_EXCEPT_HANDLER will pop this off. */ - SET_FOURTH(NULL); - /* We just shifted the stack down, so we have - to tell the except handler block that the - values are lower than it expects. */ - block = &f->f_blockstack[f->f_iblock - 1]; - assert(block->b_type == EXCEPT_HANDLER); - block->b_level--; - } - /* XXX Not the fastest way to call it... */ - x = PyObject_CallFunctionObjArgs(exit_func, u, v, w, - NULL); - Py_DECREF(exit_func); - if (x == NULL) - break; /* Go to error exit */ - - if (u != Py_None) - err = PyObject_IsTrue(x); - else - err = 0; - Py_DECREF(x); - - if (err < 0) - break; /* Go to error exit */ - else if (err > 0) { - err = 0; - /* There was an exception and a True return */ - PUSH(PyLong_FromLong((long) WHY_SILENCED)); - } - PREDICT(END_FINALLY); - break; - } - - TARGET(CALL_FUNCTION) - { - PyObject **sp; - PCALL(PCALL_ALL); - sp = stack_pointer; + TARGET(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); + DISPATCH(); + } + STACKADJ(-1); + break; + + PREDICTED_WITH_ARG(FOR_ITER); + TARGET(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); + DISPATCH(); + } + if (PyErr_Occurred()) { + if (!PyErr_ExceptionMatches( + PyExc_StopIteration)) + break; + PyErr_Clear(); + } + /* iterator ended normally */ + x = v = POP(); + Py_DECREF(v); + JUMPBY(oparg); + DISPATCH(); + + TARGET(BREAK_LOOP) + why = WHY_BREAK; + goto fast_block_end; + + TARGET(CONTINUE_LOOP) + retval = PyLong_FromLong(oparg); + if (!retval) { + x = NULL; + break; + } + why = WHY_CONTINUE; + goto fast_block_end; + + TARGET_WITH_IMPL(SETUP_LOOP, _setup_finally) + TARGET_WITH_IMPL(SETUP_EXCEPT, _setup_finally) + TARGET(SETUP_FINALLY) + _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()); + DISPATCH(); + + TARGET(SETUP_WITH) + { + static PyObject *exit, *enter; + w = TOP(); + x = special_lookup(w, "__exit__", &exit); + if (!x) + break; + SET_TOP(x); + u = special_lookup(w, "__enter__", &enter); + Py_DECREF(w); + if (!u) { + x = NULL; + break; + } + x = PyObject_CallFunctionObjArgs(u, NULL); + Py_DECREF(u); + if (!x) + break; + /* Setup the finally block before pushing the result + of __enter__ on the stack. */ + PyFrame_BlockSetup(f, SETUP_FINALLY, INSTR_OFFSET() + oparg, + STACK_LEVEL()); + + PUSH(x); + DISPATCH(); + } + + TARGET(WITH_CLEANUP) + { + /* At the top of the stack are 1-3 values indicating + how/why we entered the finally clause: + - TOP = None + - (TOP, SECOND) = (WHY_{RETURN,CONTINUE}), retval + - TOP = WHY_*; no retval below it + - (TOP, SECOND, THIRD) = exc_info() + (FOURTH, FITH, SIXTH) = previous exception for EXCEPT_HANDLER + Below them is EXIT, the context.__exit__ bound method. + In the last case, we must call + EXIT(TOP, SECOND, THIRD) + otherwise we must call + EXIT(None, None, None) + + In the first two cases, we remove EXIT from the + stack, leaving the rest in the same order. In the + third case, we shift the bottom 3 values of the + stack down, and replace the empty spot with NULL. + + In addition, if the stack represents an exception, + *and* the function call returns a 'true' value, we + push WHY_SILENCED onto the stack. END_FINALLY will + then not re-raise the exception. (But non-local + gotos should still be resumed.) + */ + + PyObject *exit_func; + u = TOP(); + if (u == Py_None) { + (void)POP(); + exit_func = TOP(); + SET_TOP(u); + v = w = Py_None; + } + else if (PyLong_Check(u)) { + (void)POP(); + switch(PyLong_AsLong(u)) { + case WHY_RETURN: + case WHY_CONTINUE: + /* Retval in TOP. */ + exit_func = SECOND(); + SET_SECOND(TOP()); + SET_TOP(u); + break; + default: + exit_func = TOP(); + SET_TOP(u); + break; + } + u = v = w = Py_None; + } + else { + PyObject *tp, *exc, *tb; + PyTryBlock *block; + v = SECOND(); + w = THIRD(); + tp = FOURTH(); + exc = PEEK(5); + tb = PEEK(6); + exit_func = PEEK(7); + SET_VALUE(7, tb); + SET_VALUE(6, exc); + SET_VALUE(5, tp); + /* UNWIND_EXCEPT_HANDLER will pop this off. */ + SET_FOURTH(NULL); + /* We just shifted the stack down, so we have + to tell the except handler block that the + values are lower than it expects. */ + block = &f->f_blockstack[f->f_iblock - 1]; + assert(block->b_type == EXCEPT_HANDLER); + block->b_level--; + } + /* XXX Not the fastest way to call it... */ + x = PyObject_CallFunctionObjArgs(exit_func, u, v, w, + NULL); + Py_DECREF(exit_func); + if (x == NULL) + break; /* Go to error exit */ + + if (u != Py_None) + err = PyObject_IsTrue(x); + else + err = 0; + Py_DECREF(x); + + if (err < 0) + break; /* Go to error exit */ + else if (err > 0) { + err = 0; + /* There was an exception and a True return */ + PUSH(PyLong_FromLong((long) WHY_SILENCED)); + } + PREDICT(END_FINALLY); + break; + } + + TARGET(CALL_FUNCTION) + { + PyObject **sp; + PCALL(PCALL_ALL); + sp = stack_pointer; #ifdef WITH_TSC - x = call_function(&sp, oparg, &intr0, &intr1); + x = call_function(&sp, oparg, &intr0, &intr1); #else - x = call_function(&sp, oparg); + x = call_function(&sp, oparg); #endif - stack_pointer = sp; - PUSH(x); - if (x != NULL) - DISPATCH(); - break; - } - - TARGET_WITH_IMPL(CALL_FUNCTION_VAR, _call_function_var_kw) - TARGET_WITH_IMPL(CALL_FUNCTION_KW, _call_function_var_kw) - TARGET(CALL_FUNCTION_VAR_KW) - _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) - DISPATCH(); - break; - } - - TARGET_WITH_IMPL(MAKE_CLOSURE, _make_function) - TARGET(MAKE_FUNCTION) - _make_function: - { - int posdefaults = oparg & 0xff; - int kwdefaults = (oparg>>8) & 0xff; - int num_annotations = (oparg >> 16) & 0x7fff; - - v = POP(); /* code object */ - x = PyFunction_New(v, f->f_globals); - Py_DECREF(v); - - if (x != NULL && opcode == MAKE_CLOSURE) { - v = POP(); - if (PyFunction_SetClosure(x, v) != 0) { - /* Can't happen unless bytecode is corrupt. */ - why = WHY_EXCEPTION; - } - Py_DECREF(v); - } - - if (x != NULL && num_annotations > 0) { - Py_ssize_t name_ix; - u = POP(); /* names of args with annotations */ - v = PyDict_New(); - if (v == NULL) { - Py_DECREF(x); - x = NULL; - break; - } - name_ix = PyTuple_Size(u); - assert(num_annotations == name_ix+1); - while (name_ix > 0) { - --name_ix; - t = PyTuple_GET_ITEM(u, name_ix); - w = POP(); - /* XXX(nnorwitz): check for errors */ - PyDict_SetItem(v, t, w); - Py_DECREF(w); - } - - if (PyFunction_SetAnnotations(x, v) != 0) { - /* Can't happen unless - PyFunction_SetAnnotations changes. */ - why = WHY_EXCEPTION; - } - Py_DECREF(v); - Py_DECREF(u); - } - - /* XXX Maybe this should be a separate opcode? */ - if (x != NULL && posdefaults > 0) { - v = PyTuple_New(posdefaults); - if (v == NULL) { - Py_DECREF(x); - x = NULL; - break; - } - while (--posdefaults >= 0) { - w = POP(); - PyTuple_SET_ITEM(v, posdefaults, w); - } - if (PyFunction_SetDefaults(x, v) != 0) { - /* Can't happen unless - PyFunction_SetDefaults changes. */ - why = WHY_EXCEPTION; - } - Py_DECREF(v); - } - if (x != NULL && kwdefaults > 0) { - v = PyDict_New(); - if (v == NULL) { - Py_DECREF(x); - x = NULL; - break; - } - while (--kwdefaults >= 0) { - w = POP(); /* default value */ - u = POP(); /* kw only arg name */ - /* XXX(nnorwitz): check for errors */ - PyDict_SetItem(v, u, w); - Py_DECREF(w); - Py_DECREF(u); - } - if (PyFunction_SetKwDefaults(x, v) != 0) { - /* Can't happen unless - PyFunction_SetKwDefaults changes. */ - why = WHY_EXCEPTION; - } - Py_DECREF(v); - } - PUSH(x); - break; - } - - TARGET(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) DISPATCH(); - break; - - TARGET(EXTENDED_ARG) - opcode = NEXTOP(); - oparg = oparg<<16 | NEXTARG(); - goto dispatch_opcode; + stack_pointer = sp; + PUSH(x); + if (x != NULL) + DISPATCH(); + break; + } + + TARGET_WITH_IMPL(CALL_FUNCTION_VAR, _call_function_var_kw) + TARGET_WITH_IMPL(CALL_FUNCTION_KW, _call_function_var_kw) + TARGET(CALL_FUNCTION_VAR_KW) + _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) + DISPATCH(); + break; + } + + TARGET_WITH_IMPL(MAKE_CLOSURE, _make_function) + TARGET(MAKE_FUNCTION) + _make_function: + { + int posdefaults = oparg & 0xff; + int kwdefaults = (oparg>>8) & 0xff; + int num_annotations = (oparg >> 16) & 0x7fff; + + v = POP(); /* code object */ + x = PyFunction_New(v, f->f_globals); + Py_DECREF(v); + + if (x != NULL && opcode == MAKE_CLOSURE) { + v = POP(); + if (PyFunction_SetClosure(x, v) != 0) { + /* Can't happen unless bytecode is corrupt. */ + why = WHY_EXCEPTION; + } + Py_DECREF(v); + } + + if (x != NULL && num_annotations > 0) { + Py_ssize_t name_ix; + u = POP(); /* names of args with annotations */ + v = PyDict_New(); + if (v == NULL) { + Py_DECREF(x); + x = NULL; + break; + } + name_ix = PyTuple_Size(u); + assert(num_annotations == name_ix+1); + while (name_ix > 0) { + --name_ix; + t = PyTuple_GET_ITEM(u, name_ix); + w = POP(); + /* XXX(nnorwitz): check for errors */ + PyDict_SetItem(v, t, w); + Py_DECREF(w); + } + + if (PyFunction_SetAnnotations(x, v) != 0) { + /* Can't happen unless + PyFunction_SetAnnotations changes. */ + why = WHY_EXCEPTION; + } + Py_DECREF(v); + Py_DECREF(u); + } + + /* XXX Maybe this should be a separate opcode? */ + if (x != NULL && posdefaults > 0) { + v = PyTuple_New(posdefaults); + if (v == NULL) { + Py_DECREF(x); + x = NULL; + break; + } + while (--posdefaults >= 0) { + w = POP(); + PyTuple_SET_ITEM(v, posdefaults, w); + } + if (PyFunction_SetDefaults(x, v) != 0) { + /* Can't happen unless + PyFunction_SetDefaults changes. */ + why = WHY_EXCEPTION; + } + Py_DECREF(v); + } + if (x != NULL && kwdefaults > 0) { + v = PyDict_New(); + if (v == NULL) { + Py_DECREF(x); + x = NULL; + break; + } + while (--kwdefaults >= 0) { + w = POP(); /* default value */ + u = POP(); /* kw only arg name */ + /* XXX(nnorwitz): check for errors */ + PyDict_SetItem(v, u, w); + Py_DECREF(w); + Py_DECREF(u); + } + if (PyFunction_SetKwDefaults(x, v) != 0) { + /* Can't happen unless + PyFunction_SetKwDefaults changes. */ + why = WHY_EXCEPTION; + } + Py_DECREF(v); + } + PUSH(x); + break; + } + + TARGET(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) DISPATCH(); + break; + + TARGET(EXTENDED_ARG) + opcode = NEXTOP(); + oparg = oparg<<16 | NEXTARG(); + goto dispatch_opcode; #ifdef USE_COMPUTED_GOTOS - _unknown_opcode: + _unknown_opcode: #endif - default: - fprintf(stderr, - "XXX lineno: %d, opcode: %d\n", - PyFrame_GetLineNumber(f), - opcode); - PyErr_SetString(PyExc_SystemError, "unknown opcode"); - why = WHY_EXCEPTION; - break; + default: + fprintf(stderr, + "XXX lineno: %d, opcode: %d\n", + PyFrame_GetLineNumber(f), + opcode); + PyErr_SetString(PyExc_SystemError, "unknown opcode"); + why = WHY_EXCEPTION; + break; #ifdef CASE_TOO_BIG - } + } #endif - } /* switch */ + } /* switch */ - on_error: + on_error: - READ_TIMESTAMP(inst1); + READ_TIMESTAMP(inst1); - /* Quickly continue if no error occurred */ + /* Quickly continue if no error occurred */ - if (why == WHY_NOT) { - if (err == 0 && x != NULL) { + 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 { + /* This check is expensive! */ + if (PyErr_Occurred()) + fprintf(stderr, + "XXX undetected error\n"); + else { #endif - READ_TIMESTAMP(loop1); - continue; /* Normal, fast path */ + 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; - } - } + } + 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[128]; - sprintf(buf, "Stack unwind with exception " - "set and why=%d", why); - Py_FatalError(buf); - } - } + else { + /* This check is expensive! */ + if (PyErr_Occurred()) { + char buf[128]; + sprintf(buf, "Stack unwind with exception " + "set and why=%d", why); + Py_FatalError(buf); + } + } #endif - /* Log traceback info if this is a real exception */ + /* Log traceback info if this is a real exception */ - if (why == WHY_EXCEPTION) { - PyTraceBack_Here(f); + if (why == WHY_EXCEPTION) { + PyTraceBack_Here(f); - if (tstate->c_tracefunc != NULL) - call_exc_trace(tstate->c_tracefunc, - tstate->c_traceobj, 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 */ + /* For the rest, treat WHY_RERAISE as WHY_EXCEPTION */ - if (why == WHY_RERAISE) - why = WHY_EXCEPTION; + if (why == WHY_RERAISE) + why = WHY_EXCEPTION; - /* Unwind stacks if a (pseudo) exception occurred */ + /* Unwind stacks if a (pseudo) exception occurred */ fast_block_end: - while (why != WHY_NOT && f->f_iblock > 0) { - /* Peek at the current block. */ - PyTryBlock *b = &f->f_blockstack[f->f_iblock - 1]; - - assert(why != WHY_YIELD); - if (b->b_type == SETUP_LOOP && why == WHY_CONTINUE) { - why = WHY_NOT; - JUMPTO(PyLong_AS_LONG(retval)); - Py_DECREF(retval); - break; - } - /* Now we have to pop the block. */ - f->f_iblock--; - - if (b->b_type == EXCEPT_HANDLER) { - UNWIND_EXCEPT_HANDLER(b); - continue; - } - UNWIND_BLOCK(b); - if (b->b_type == SETUP_LOOP && why == WHY_BREAK) { - why = WHY_NOT; - JUMPTO(b->b_handler); - break; - } - if (why == WHY_EXCEPTION && (b->b_type == SETUP_EXCEPT - || b->b_type == SETUP_FINALLY)) { - PyObject *exc, *val, *tb; - int handler = b->b_handler; - /* Beware, this invalidates all b->b_* fields */ - PyFrame_BlockSetup(f, EXCEPT_HANDLER, -1, STACK_LEVEL()); - PUSH(tstate->exc_traceback); - PUSH(tstate->exc_value); - if (tstate->exc_type != NULL) { - PUSH(tstate->exc_type); - } - else { - Py_INCREF(Py_None); - PUSH(Py_None); - } - PyErr_Fetch(&exc, &val, &tb); - /* Make the raw exception data - available to the handler, - so a program can emulate the - Python main loop. */ - PyErr_NormalizeException( - &exc, &val, &tb); - PyException_SetTraceback(val, tb); - Py_INCREF(exc); - tstate->exc_type = exc; - Py_INCREF(val); - tstate->exc_value = val; - tstate->exc_traceback = tb; - if (tb == NULL) - tb = Py_None; - Py_INCREF(tb); - PUSH(tb); - PUSH(val); - PUSH(exc); - why = WHY_NOT; - JUMPTO(handler); - break; - } - if (b->b_type == SETUP_FINALLY) { - if (why & (WHY_RETURN | WHY_CONTINUE)) - PUSH(retval); - PUSH(PyLong_FromLong((long)why)); - 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; + while (why != WHY_NOT && f->f_iblock > 0) { + /* Peek at the current block. */ + PyTryBlock *b = &f->f_blockstack[f->f_iblock - 1]; + + assert(why != WHY_YIELD); + if (b->b_type == SETUP_LOOP && why == WHY_CONTINUE) { + why = WHY_NOT; + JUMPTO(PyLong_AS_LONG(retval)); + Py_DECREF(retval); + break; + } + /* Now we have to pop the block. */ + f->f_iblock--; + + if (b->b_type == EXCEPT_HANDLER) { + UNWIND_EXCEPT_HANDLER(b); + continue; + } + UNWIND_BLOCK(b); + if (b->b_type == SETUP_LOOP && why == WHY_BREAK) { + why = WHY_NOT; + JUMPTO(b->b_handler); + break; + } + if (why == WHY_EXCEPTION && (b->b_type == SETUP_EXCEPT + || b->b_type == SETUP_FINALLY)) { + PyObject *exc, *val, *tb; + int handler = b->b_handler; + /* Beware, this invalidates all b->b_* fields */ + PyFrame_BlockSetup(f, EXCEPT_HANDLER, -1, STACK_LEVEL()); + PUSH(tstate->exc_traceback); + PUSH(tstate->exc_value); + if (tstate->exc_type != NULL) { + PUSH(tstate->exc_type); + } + else { + Py_INCREF(Py_None); + PUSH(Py_None); + } + PyErr_Fetch(&exc, &val, &tb); + /* Make the raw exception data + available to the handler, + so a program can emulate the + Python main loop. */ + PyErr_NormalizeException( + &exc, &val, &tb); + PyException_SetTraceback(val, tb); + Py_INCREF(exc); + tstate->exc_type = exc; + Py_INCREF(val); + tstate->exc_value = val; + tstate->exc_traceback = tb; + if (tb == NULL) + tb = Py_None; + Py_INCREF(tb); + PUSH(tb); + PUSH(val); + PUSH(exc); + why = WHY_NOT; + JUMPTO(handler); + break; + } + if (b->b_type == SETUP_FINALLY) { + if (why & (WHY_RETURN | WHY_CONTINUE)) + PUSH(retval); + PUSH(PyLong_FromLong((long)why)); + 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; - } - } - } - - /* pop frame */ + 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; + } + } + } + + /* pop frame */ exit_eval_frame: - Py_LeaveRecursiveCall(); - tstate->frame = f->f_back; + Py_LeaveRecursiveCall(); + tstate->frame = f->f_back; - return retval; + return retval; } /* This is gonna seem *real weird*, but if you put some other code between @@ -3058,279 +3058,279 @@ exit_eval_frame: PyObject * PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, - PyObject **args, int argcount, PyObject **kws, int kwcount, - PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure) + PyObject **args, int argcount, PyObject **kws, int kwcount, + PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure) { - register PyFrameObject *f; - register PyObject *retval = NULL; - register PyObject **fastlocals, **freevars; - PyThreadState *tstate = PyThreadState_GET(); - PyObject *x, *u; - int total_args = co->co_argcount + co->co_kwonlyargcount; - - 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 (total_args || 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 = total_args; - 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, - "%U() takes %s %d " - "argument%s (%d given)", - co->co_name, - defcount ? "at most" : "exactly", - total_args, - total_args == 1 ? "" : "s", - argcount + kwcount); - 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(total_args, 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 **co_varnames; - PyObject *keyword = kws[2*i]; - PyObject *value = kws[2*i + 1]; - int j; - if (keyword == NULL || !PyUnicode_Check(keyword)) { - PyErr_Format(PyExc_TypeError, - "%U() keywords must be strings", - co->co_name); - goto fail; - } - /* Speed hack: do raw pointer compares. As names are - normally interned this should almost always hit. */ - co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item; - for (j = 0; j < total_args; j++) { - PyObject *nm = co_varnames[j]; - if (nm == keyword) - goto kw_found; - } - /* Slow fallback, just in case */ - for (j = 0; j < total_args; j++) { - PyObject *nm = co_varnames[j]; - int cmp = PyObject_RichCompareBool( - keyword, nm, Py_EQ); - if (cmp > 0) - goto kw_found; - else if (cmp < 0) - goto fail; - } - if (j >= total_args && kwdict == NULL) { - PyErr_Format(PyExc_TypeError, - "%U() got an unexpected " - "keyword argument '%S'", - co->co_name, - keyword); - goto fail; - } - PyDict_SetItem(kwdict, keyword, value); - continue; - kw_found: - if (GETLOCAL(j) != NULL) { - PyErr_Format(PyExc_TypeError, - "%U() got multiple " - "values for keyword " - "argument '%S'", - co->co_name, - keyword); - goto fail; - } - Py_INCREF(value); - SETLOCAL(j, value); - } - if (co->co_kwonlyargcount > 0) { - for (i = co->co_argcount; i < total_args; i++) { - PyObject *name; - if (GETLOCAL(i) != NULL) - continue; - name = PyTuple_GET_ITEM(co->co_varnames, i); - if (kwdefs != NULL) { - PyObject *def = PyDict_GetItem(kwdefs, name); - if (def) { - Py_INCREF(def); - SETLOCAL(i, def); - continue; - } - } - PyErr_Format(PyExc_TypeError, - "%U() needs keyword-only argument %S", - co->co_name, name); - goto fail; - } - } - if (argcount < co->co_argcount) { - int m = co->co_argcount - defcount; - for (i = argcount; i < m; i++) { - if (GETLOCAL(i) == NULL) { - int j, given = 0; - for (j = 0; j < co->co_argcount; j++) - if (GETLOCAL(j)) - given++; - PyErr_Format(PyExc_TypeError, - "%U() takes %s %d " - "argument%s " - "(%d given)", - co->co_name, - ((co->co_flags & CO_VARARGS) || - defcount) ? "at least" - : "exactly", - m, m == 1 ? "" : "s", given); - 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, - "%U() takes no arguments (%d given)", - 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; - Py_UNICODE *cellname, *argname; - PyObject *c; - - nargs = total_args; - 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 = PyUnicode_AS_UNICODE( - PyTuple_GET_ITEM(co->co_cellvars, i)); - found = 0; - for (j = 0; j < nargs; j++) { - argname = PyUnicode_AS_UNICODE( - PyTuple_GET_ITEM(co->co_varnames, j)); - if (Py_UNICODE_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); + register PyFrameObject *f; + register PyObject *retval = NULL; + register PyObject **fastlocals, **freevars; + PyThreadState *tstate = PyThreadState_GET(); + PyObject *x, *u; + int total_args = co->co_argcount + co->co_kwonlyargcount; + + 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 (total_args || 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 = total_args; + 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, + "%U() takes %s %d " + "argument%s (%d given)", + co->co_name, + defcount ? "at most" : "exactly", + total_args, + total_args == 1 ? "" : "s", + argcount + kwcount); + 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(total_args, 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 **co_varnames; + PyObject *keyword = kws[2*i]; + PyObject *value = kws[2*i + 1]; + int j; + if (keyword == NULL || !PyUnicode_Check(keyword)) { + PyErr_Format(PyExc_TypeError, + "%U() keywords must be strings", + co->co_name); + goto fail; + } + /* Speed hack: do raw pointer compares. As names are + normally interned this should almost always hit. */ + co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item; + for (j = 0; j < total_args; j++) { + PyObject *nm = co_varnames[j]; + if (nm == keyword) + goto kw_found; + } + /* Slow fallback, just in case */ + for (j = 0; j < total_args; j++) { + PyObject *nm = co_varnames[j]; + int cmp = PyObject_RichCompareBool( + keyword, nm, Py_EQ); + if (cmp > 0) + goto kw_found; + else if (cmp < 0) + goto fail; + } + if (j >= total_args && kwdict == NULL) { + PyErr_Format(PyExc_TypeError, + "%U() got an unexpected " + "keyword argument '%S'", + co->co_name, + keyword); + goto fail; + } + PyDict_SetItem(kwdict, keyword, value); + continue; + kw_found: + if (GETLOCAL(j) != NULL) { + PyErr_Format(PyExc_TypeError, + "%U() got multiple " + "values for keyword " + "argument '%S'", + co->co_name, + keyword); + goto fail; + } + Py_INCREF(value); + SETLOCAL(j, value); + } + if (co->co_kwonlyargcount > 0) { + for (i = co->co_argcount; i < total_args; i++) { + PyObject *name; + if (GETLOCAL(i) != NULL) + continue; + name = PyTuple_GET_ITEM(co->co_varnames, i); + if (kwdefs != NULL) { + PyObject *def = PyDict_GetItem(kwdefs, name); + if (def) { + Py_INCREF(def); + SETLOCAL(i, def); + continue; + } + } + PyErr_Format(PyExc_TypeError, + "%U() needs keyword-only argument %S", + co->co_name, name); + goto fail; + } + } + if (argcount < co->co_argcount) { + int m = co->co_argcount - defcount; + for (i = argcount; i < m; i++) { + if (GETLOCAL(i) == NULL) { + int j, given = 0; + for (j = 0; j < co->co_argcount; j++) + if (GETLOCAL(j)) + given++; + PyErr_Format(PyExc_TypeError, + "%U() takes %s %d " + "argument%s " + "(%d given)", + co->co_name, + ((co->co_flags & CO_VARARGS) || + defcount) ? "at least" + : "exactly", + m, m == 1 ? "" : "s", given); + 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, + "%U() takes no arguments (%d given)", + 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; + Py_UNICODE *cellname, *argname; + PyObject *c; + + nargs = total_args; + 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 = PyUnicode_AS_UNICODE( + PyTuple_GET_ITEM(co->co_cellvars, i)); + found = 0; + for (j = 0; j < nargs; j++) { + argname = PyUnicode_AS_UNICODE( + PyTuple_GET_ITEM(co->co_varnames, j)); + if (Py_UNICODE_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; + /* 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; } static PyObject * special_lookup(PyObject *o, char *meth, PyObject **cache) { - PyObject *res; - res = _PyObject_LookupSpecial(o, meth, cache); - if (res == NULL && !PyErr_Occurred()) { - PyErr_SetObject(PyExc_AttributeError, *cache); - return NULL; - } - return res; + PyObject *res; + res = _PyObject_LookupSpecial(o, meth, cache); + if (res == NULL && !PyErr_Occurred()) { + PyErr_SetObject(PyExc_AttributeError, *cache); + return NULL; + } + return res; } @@ -3339,83 +3339,83 @@ special_lookup(PyObject *o, char *meth, PyObject **cache) static enum why_code do_raise(PyObject *exc, PyObject *cause) { - PyObject *type = NULL, *value = NULL; - - if (exc == NULL) { - /* Reraise */ - PyThreadState *tstate = PyThreadState_GET(); - PyObject *tb; - type = tstate->exc_type; - value = tstate->exc_value; - tb = tstate->exc_traceback; - if (type == Py_None) { - PyErr_SetString(PyExc_RuntimeError, - "No active exception to reraise"); - return WHY_EXCEPTION; - } - Py_XINCREF(type); - Py_XINCREF(value); - Py_XINCREF(tb); - PyErr_Restore(type, value, tb); - return WHY_RERAISE; - } - - /* We support the following forms of raise: - raise + PyObject *type = NULL, *value = NULL; + + if (exc == NULL) { + /* Reraise */ + PyThreadState *tstate = PyThreadState_GET(); + PyObject *tb; + type = tstate->exc_type; + value = tstate->exc_value; + tb = tstate->exc_traceback; + if (type == Py_None) { + PyErr_SetString(PyExc_RuntimeError, + "No active exception to reraise"); + return WHY_EXCEPTION; + } + Py_XINCREF(type); + Py_XINCREF(value); + Py_XINCREF(tb); + PyErr_Restore(type, value, tb); + return WHY_RERAISE; + } + + /* We support the following forms of raise: + raise raise raise */ - if (PyExceptionClass_Check(exc)) { - type = exc; - value = PyObject_CallObject(exc, NULL); - if (value == NULL) - goto raise_error; - } - else if (PyExceptionInstance_Check(exc)) { - value = exc; - type = PyExceptionInstance_Class(exc); - Py_INCREF(type); - } - else { - /* Not something you can raise. You get an exception - anyway, just not what you specified :-) */ - Py_DECREF(exc); - PyErr_SetString(PyExc_TypeError, - "exceptions must derive from BaseException"); - goto raise_error; - } - - if (cause) { - PyObject *fixed_cause; - if (PyExceptionClass_Check(cause)) { - fixed_cause = PyObject_CallObject(cause, NULL); - if (fixed_cause == NULL) - goto raise_error; - Py_DECREF(cause); - } - else if (PyExceptionInstance_Check(cause)) { - fixed_cause = cause; - } - else { - PyErr_SetString(PyExc_TypeError, - "exception causes must derive from " - "BaseException"); - goto raise_error; - } - PyException_SetCause(value, fixed_cause); - } - - PyErr_SetObject(type, value); - /* PyErr_SetObject incref's its arguments */ - Py_XDECREF(value); - Py_XDECREF(type); - return WHY_EXCEPTION; + if (PyExceptionClass_Check(exc)) { + type = exc; + value = PyObject_CallObject(exc, NULL); + if (value == NULL) + goto raise_error; + } + else if (PyExceptionInstance_Check(exc)) { + value = exc; + type = PyExceptionInstance_Class(exc); + Py_INCREF(type); + } + else { + /* Not something you can raise. You get an exception + anyway, just not what you specified :-) */ + Py_DECREF(exc); + PyErr_SetString(PyExc_TypeError, + "exceptions must derive from BaseException"); + goto raise_error; + } + + if (cause) { + PyObject *fixed_cause; + if (PyExceptionClass_Check(cause)) { + fixed_cause = PyObject_CallObject(cause, NULL); + if (fixed_cause == NULL) + goto raise_error; + Py_DECREF(cause); + } + else if (PyExceptionInstance_Check(cause)) { + fixed_cause = cause; + } + else { + PyErr_SetString(PyExc_TypeError, + "exception causes must derive from " + "BaseException"); + goto raise_error; + } + PyException_SetCause(value, fixed_cause); + } + + PyErr_SetObject(type, value); + /* PyErr_SetObject incref's its arguments */ + Py_XDECREF(value); + Py_XDECREF(type); + return WHY_EXCEPTION; raise_error: - Py_XDECREF(value); - Py_XDECREF(type); - Py_XDECREF(cause); - return WHY_EXCEPTION; + Py_XDECREF(value); + Py_XDECREF(type); + Py_XDECREF(cause); + return WHY_EXCEPTION; } /* Iterate v argcnt times and store the results on the stack (via decreasing @@ -3428,73 +3428,73 @@ raise_error: static int unpack_iterable(PyObject *v, int argcnt, int argcntafter, PyObject **sp) { - int i = 0, j = 0; - Py_ssize_t ll = 0; - PyObject *it; /* iter(v) */ - PyObject *w; - PyObject *l = NULL; /* variable list */ - - 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; - } - - if (argcntafter == -1) { - /* 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"); - goto Error; - } - - l = PySequence_List(it); - if (l == NULL) - goto Error; - *--sp = l; - i++; - - ll = PyList_GET_SIZE(l); - if (ll < argcntafter) { - PyErr_Format(PyExc_ValueError, "need more than %zd values to unpack", - argcnt + ll); - goto Error; - } - - /* Pop the "after-variable" args off the list. */ - for (j = argcntafter; j > 0; j--, i++) { - *--sp = PyList_GET_ITEM(l, ll - j); - } - /* Resize the list. */ - Py_SIZE(l) = ll - argcntafter; - Py_DECREF(it); - return 1; + int i = 0, j = 0; + Py_ssize_t ll = 0; + PyObject *it; /* iter(v) */ + PyObject *w; + PyObject *l = NULL; /* variable list */ + + 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; + } + + if (argcntafter == -1) { + /* 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"); + goto Error; + } + + l = PySequence_List(it); + if (l == NULL) + goto Error; + *--sp = l; + i++; + + ll = PyList_GET_SIZE(l); + if (ll < argcntafter) { + PyErr_Format(PyExc_ValueError, "need more than %zd values to unpack", + argcnt + ll); + goto Error; + } + + /* Pop the "after-variable" args off the list. */ + for (j = argcntafter; j > 0; j--, i++) { + *--sp = PyList_GET_ITEM(l, ll - j); + } + /* Resize the list. */ + Py_SIZE(l) = ll - argcntafter; + Py_DECREF(it); + return 1; Error: - for (; i > 0; i--, sp++) - Py_DECREF(*sp); - Py_XDECREF(it); - return 0; + for (; i > 0; i--, sp++) + Py_DECREF(*sp); + Py_XDECREF(it); + return 0; } @@ -3502,220 +3502,220 @@ Error: 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; + 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); - } + 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 int call_trace_protected(Py_tracefunc func, PyObject *obj, PyFrameObject *frame, - int what, PyObject *arg) + 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); - return 0; - } - else { - Py_XDECREF(type); - Py_XDECREF(value); - Py_XDECREF(traceback); - return -1; - } + 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); + return 0; + } + else { + Py_XDECREF(type); + Py_XDECREF(value); + Py_XDECREF(traceback); + return -1; + } } static int call_trace(Py_tracefunc func, PyObject *obj, PyFrameObject *frame, - int what, PyObject *arg) + 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; + 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; + 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; } /* See Objects/lnotab_notes.txt for a description of how tracing works. */ static int maybe_call_line_trace(Py_tracefunc func, PyObject *obj, - PyFrameObject *frame, int *instr_lb, int *instr_ub, - int *instr_prev) + PyFrameObject *frame, int *instr_lb, int *instr_ub, + int *instr_prev) { - int result = 0; - int line = frame->f_lineno; - - /* If the last instruction executed isn't in the current - instruction window, reset the window. - */ - if (frame->f_lasti < *instr_lb || frame->f_lasti >= *instr_ub) { - PyAddrPair bounds; - line = _PyCode_CheckLineNumber(frame->f_code, frame->f_lasti, - &bounds); - *instr_lb = bounds.ap_lower; - *instr_ub = bounds.ap_upper; - } - /* If the last instruction falls at the start of a line or if - it represents a jump backwards, update the frame's line - number and call the trace function. */ - if (frame->f_lasti == *instr_lb || frame->f_lasti < *instr_prev) { - frame->f_lineno = line; - result = call_trace(func, obj, frame, PyTrace_LINE, Py_None); - } - *instr_prev = frame->f_lasti; - return result; + int result = 0; + int line = frame->f_lineno; + + /* If the last instruction executed isn't in the current + instruction window, reset the window. + */ + if (frame->f_lasti < *instr_lb || frame->f_lasti >= *instr_ub) { + PyAddrPair bounds; + line = _PyCode_CheckLineNumber(frame->f_code, frame->f_lasti, + &bounds); + *instr_lb = bounds.ap_lower; + *instr_ub = bounds.ap_upper; + } + /* If the last instruction falls at the start of a line or if + it represents a jump backwards, update the frame's line + number and call the trace function. */ + if (frame->f_lasti == *instr_lb || frame->f_lasti < *instr_prev) { + frame->f_lineno = line; + 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); + 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_TracingPossible += (func != NULL) - (tstate->c_tracefunc != NULL); - 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)); + PyThreadState *tstate = PyThreadState_GET(); + PyObject *temp = tstate->c_traceobj; + _Py_TracingPossible += (func != NULL) - (tstate->c_tracefunc != NULL); + 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; + 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; + 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 *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); + PyThreadState *tstate = PyThreadState_GET(); + return _PyThreadState_GetFrame(tstate); } 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; - } + 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; - } + if (codeflags & CO_GENERATOR_ALLOWED) { + result = 1; + cf->cf_flags |= CO_GENERATOR_ALLOWED; + } #endif - } - return result; + } + return result; } @@ -3725,186 +3725,186 @@ PyEval_MergeCompilerFlags(PyCompilerFlags *cf) 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; + 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 _PyUnicode_AsString(((PyFunctionObject*)func)->func_name); - else if (PyCFunction_Check(func)) - return ((PyCFunctionObject*)func)->m_ml->ml_name; - else - return func->ob_type->tp_name; + if (PyMethod_Check(func)) + return PyEval_GetFuncName(PyMethod_GET_FUNCTION(func)); + else if (PyFunction_Check(func)) + return _PyUnicode_AsString(((PyFunctionObject*)func)->func_name); + else if (PyCFunction_Check(func)) + return ((PyCFunctionObject*)func)->m_ml->ml_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 - return " object"; + if (PyMethod_Check(func)) + return "()"; + else if (PyFunction_Check(func)) + return "()"; + else if (PyCFunction_Check(func)) + return "()"; + 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); + 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; \ - } \ - } \ - } \ - } \ + 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; \ - } + x = call; \ + } static PyObject * call_function(PyObject ***pp_stack, int oparg #ifdef WITH_TSC - , uint64* pintr0, uint64* pintr1 + , 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; + 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 @@ -3919,275 +3919,275 @@ call_function(PyObject ***pp_stack, int oparg 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 *kwdefs = PyFunction_GET_KW_DEFAULTS(func); - PyObject **d = NULL; - int nd = 0; - - PCALL(PCALL_FUNCTION); - PCALL(PCALL_FAST_FUNCTION); - if (argdefs == NULL && co->co_argcount == n && - co->co_kwonlyargcount == 0 && 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 = Py_SIZE(argdefs); - } - return PyEval_EvalCodeEx(co, globals, - (PyObject *)NULL, (*pp_stack)-n, na, - (*pp_stack)-2*nk, nk, d, nd, kwdefs, - PyFunction_GET_CLOSURE(func)); + PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); + PyObject *globals = PyFunction_GET_GLOBALS(func); + PyObject *argdefs = PyFunction_GET_DEFAULTS(func); + PyObject *kwdefs = PyFunction_GET_KW_DEFAULTS(func); + PyObject **d = NULL; + int nd = 0; + + PCALL(PCALL_FUNCTION); + PCALL(PCALL_FAST_FUNCTION); + if (argdefs == NULL && co->co_argcount == n && + co->co_kwonlyargcount == 0 && 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 = Py_SIZE(argdefs); + } + return PyEval_EvalCodeEx(co, globals, + (PyObject *)NULL, (*pp_stack)-n, na, + (*pp_stack)-2*nk, nk, d, nd, kwdefs, + 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 '%U'", - PyEval_GetFuncName(func), - PyEval_GetFuncDesc(func), - 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; + 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 '%U'", + PyEval_GetFuncName(func), + PyEval_GetFuncDesc(func), + 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 ***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; + 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; + 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; + 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 if (PyCFunction_Check(func)) - PCALL(PCALL_CFUNCTION); - else - PCALL(PCALL_OTHER); + /* 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 if (PyCFunction_Check(func)) + PCALL(PCALL_CFUNCTION); + else + PCALL(PCALL_OTHER); #endif - if (PyCFunction_Check(func)) { - PyThreadState *tstate = PyThreadState_GET(); - C_TRACE(result, PyCFunction_Call(func, callargs, kwdict)); - } - else - result = PyObject_Call(func, callargs, kwdict); + if (PyCFunction_Check(func)) { + PyThreadState *tstate = PyThreadState_GET(); + C_TRACE(result, PyCFunction_Call(func, callargs, kwdict)); + } + else + result = PyObject_Call(func, callargs, kwdict); call_fail: - Py_XDECREF(callargs); - Py_XDECREF(kwdict); - return result; + 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 (!PyDict_Check(kwdict)) { - PyObject *d; - d = PyDict_New(); - if (d == NULL) - goto ext_call_fail; - if (PyDict_Update(d, kwdict) != 0) { - Py_DECREF(d); - /* PyDict_Update raises attribute - * error (percolated from an attempt - * to get 'keys' attribute) instead of - * a type error if its second argument - * is not a mapping. - */ - if (PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Format(PyExc_TypeError, - "%.200s%.200s argument after ** " - "must be a mapping, not %.200s", - PyEval_GetFuncName(func), - PyEval_GetFuncDesc(func), - kwdict->ob_type->tp_name); - } - goto ext_call_fail; - } - Py_DECREF(kwdict); - kwdict = d; - } - } - 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, - "%.200s%.200s argument after * " - "must be a sequence, not %200s", - PyEval_GetFuncName(func), - PyEval_GetFuncDesc(func), - stararg->ob_type->tp_name); - } - 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; + 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 (!PyDict_Check(kwdict)) { + PyObject *d; + d = PyDict_New(); + if (d == NULL) + goto ext_call_fail; + if (PyDict_Update(d, kwdict) != 0) { + Py_DECREF(d); + /* PyDict_Update raises attribute + * error (percolated from an attempt + * to get 'keys' attribute) instead of + * a type error if its second argument + * is not a mapping. + */ + if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Format(PyExc_TypeError, + "%.200s%.200s argument after ** " + "must be a mapping, not %.200s", + PyEval_GetFuncName(func), + PyEval_GetFuncDesc(func), + kwdict->ob_type->tp_name); + } + goto ext_call_fail; + } + Py_DECREF(kwdict); + kwdict = d; + } + } + 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, + "%.200s%.200s argument after * " + "must be a sequence, not %200s", + PyEval_GetFuncName(func), + PyEval_GetFuncDesc(func), + stararg->ob_type->tp_name); + } + 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 if (PyCFunction_Check(func)) - PCALL(PCALL_CFUNCTION); - else - PCALL(PCALL_OTHER); + /* 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 if (PyCFunction_Check(func)) + PCALL(PCALL_CFUNCTION); + else + PCALL(PCALL_OTHER); #endif - if (PyCFunction_Check(func)) { - PyThreadState *tstate = PyThreadState_GET(); - C_TRACE(result, PyCFunction_Call(func, callargs, kwdict)); - } - else - result = PyObject_Call(func, callargs, kwdict); + if (PyCFunction_Check(func)) { + PyThreadState *tstate = PyThreadState_GET(); + C_TRACE(result, PyCFunction_Call(func, callargs, kwdict)); + } + else + result = PyObject_Call(func, callargs, kwdict); ext_call_fail: - Py_XDECREF(callargs); - Py_XDECREF(kwdict); - Py_XDECREF(stararg); - return result; + 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 @@ -4203,245 +4203,245 @@ ext_call_fail: int _PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi) { - if (v != NULL) { - Py_ssize_t x; - 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; + if (v != NULL) { + Py_ssize_t x; + 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; } #define CANNOT_CATCH_MSG "catching classes that do not inherit from "\ - "BaseException is not allowed" + "BaseException is not allowed" 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: - if (PyTuple_Check(w)) { - Py_ssize_t i, length; - length = PyTuple_Size(w); - for (i = 0; i < length; i += 1) { - PyObject *exc = PyTuple_GET_ITEM(w, i); - if (!PyExceptionClass_Check(exc)) { - PyErr_SetString(PyExc_TypeError, - CANNOT_CATCH_MSG); - return NULL; - } - } - } - else { - if (!PyExceptionClass_Check(w)) { - PyErr_SetString(PyExc_TypeError, - CANNOT_CATCH_MSG); - return NULL; - } - } - res = PyErr_GivenExceptionMatches(v, w); - break; - default: - return PyObject_RichCompare(v, w, op); - } - v = res ? Py_True : Py_False; - Py_INCREF(v); - return v; + 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: + if (PyTuple_Check(w)) { + Py_ssize_t i, length; + length = PyTuple_Size(w); + for (i = 0; i < length; i += 1) { + PyObject *exc = PyTuple_GET_ITEM(w, i); + if (!PyExceptionClass_Check(exc)) { + PyErr_SetString(PyExc_TypeError, + CANNOT_CATCH_MSG); + return NULL; + } + } + } + else { + if (!PyExceptionClass_Check(w)) { + PyErr_SetString(PyExc_TypeError, + CANNOT_CATCH_MSG); + return NULL; + } + } + 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; + PyObject *x; - x = PyObject_GetAttr(v, name); - if (x == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Format(PyExc_ImportError, "cannot import name %S", name); - } - return x; + x = PyObject_GetAttr(v, name); + if (x == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Format(PyExc_ImportError, "cannot import name %S", 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 && - PyUnicode_Check(name) && - PyUnicode_AS_UNICODE(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; + 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 && + PyUnicode_Check(name) && + PyUnicode_AS_UNICODE(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 void format_exc_check_arg(PyObject *exc, const char *format_str, PyObject *obj) { - const char *obj_str; + const char *obj_str; - if (!obj) - return; + if (!obj) + return; - obj_str = _PyUnicode_AsString(obj); - if (!obj_str) - return; + obj_str = _PyUnicode_AsString(obj); + if (!obj_str) + return; - PyErr_Format(exc, format_str, obj_str); + PyErr_Format(exc, format_str, obj_str); } static PyObject * unicode_concatenate(PyObject *v, PyObject *w, - PyFrameObject *f, unsigned char *next_instr) + PyFrameObject *f, unsigned char *next_instr) { - /* This function implements 'variable += expr' when both arguments - are (Unicode) strings. */ - Py_ssize_t v_len = PyUnicode_GET_SIZE(v); - Py_ssize_t w_len = PyUnicode_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 && !PyUnicode_CHECK_INTERNED(v)) { - /* Now we own the last reference to 'v', so we can resize it - * in-place. - */ - if (PyUnicode_Resize(&v, new_len) != 0) { - /* XXX if PyUnicode_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(PyUnicode_AS_UNICODE(v) + v_len, - PyUnicode_AS_UNICODE(w), w_len*sizeof(Py_UNICODE)); - return v; - } - else { - /* When in-place resizing is not an option. */ - w = PyUnicode_Concat(v, w); - Py_DECREF(v); - return w; - } + /* This function implements 'variable += expr' when both arguments + are (Unicode) strings. */ + Py_ssize_t v_len = PyUnicode_GET_SIZE(v); + Py_ssize_t w_len = PyUnicode_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 && !PyUnicode_CHECK_INTERNED(v)) { + /* Now we own the last reference to 'v', so we can resize it + * in-place. + */ + if (PyUnicode_Resize(&v, new_len) != 0) { + /* XXX if PyUnicode_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(PyUnicode_AS_UNICODE(v) + v_len, + PyUnicode_AS_UNICODE(w), w_len*sizeof(Py_UNICODE)); + return v; + } + else { + /* When in-place resizing is not an option. */ + w = PyUnicode_Concat(v, w); + Py_DECREF(v); + return w; + } } #ifdef DYNAMIC_EXECUTION_PROFILE @@ -4449,40 +4449,40 @@ unicode_concatenate(PyObject *v, PyObject *w, 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 = PyLong_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; + int i; + PyObject *l = PyList_New(256); + if (l == NULL) return NULL; + for (i = 0; i < 256; i++) { + PyObject *x = PyLong_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); + 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; + 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 } diff --git a/Python/codecs.c b/Python/codecs.c index e6ffa0d3f9..04487a216c 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -30,14 +30,14 @@ int PyCodec_Register(PyObject *search_function) { PyInterpreterState *interp = PyThreadState_GET()->interp; if (interp->codec_search_path == NULL && _PyCodecRegistry_Init()) - goto onError; + goto onError; if (search_function == NULL) { - PyErr_BadArgument(); - goto onError; + PyErr_BadArgument(); + goto onError; } if (!PyCallable_Check(search_function)) { - PyErr_SetString(PyExc_TypeError, "argument must be callable"); - goto onError; + PyErr_SetString(PyExc_TypeError, "argument must be callable"); + goto onError; } return PyList_Append(interp->codec_search_path, search_function); @@ -57,8 +57,8 @@ PyObject *normalizestring(const char *string) PyObject *v; if (len > PY_SSIZE_T_MAX) { - PyErr_SetString(PyExc_OverflowError, "string is too large"); - return NULL; + PyErr_SetString(PyExc_OverflowError, "string is too large"); + return NULL; } p = PyMem_Malloc(len + 1); @@ -70,7 +70,7 @@ PyObject *normalizestring(const char *string) ch = '-'; else ch = tolower(Py_CHARMASK(ch)); - p[i] = ch; + p[i] = ch; } p[i] = '\0'; v = PyUnicode_FromString(p); @@ -102,78 +102,78 @@ PyObject *_PyCodec_Lookup(const char *encoding) Py_ssize_t i, len; if (encoding == NULL) { - PyErr_BadArgument(); - goto onError; + PyErr_BadArgument(); + goto onError; } interp = PyThreadState_GET()->interp; if (interp->codec_search_path == NULL && _PyCodecRegistry_Init()) - goto onError; + 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; + goto onError; PyUnicode_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; + 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; + goto onError; PyTuple_SET_ITEM(args,0,v); len = PyList_Size(interp->codec_search_path); if (len < 0) - goto onError; + goto onError; if (len == 0) { - PyErr_SetString(PyExc_LookupError, - "no codec search functions registered: " - "can't find encoding"); - goto onError; + 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; + 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, + /* XXX Perhaps we should cache misses too ? */ + PyErr_Format(PyExc_LookupError, "unknown encoding: %s", encoding); - goto onError; + goto onError; } /* Cache and return the result */ if (PyDict_SetItem(interp->codec_search_cache, v, result) < 0) { - Py_DECREF(result); - goto onError; + Py_DECREF(result); + goto onError; } Py_DECREF(args); return result; @@ -188,38 +188,38 @@ PyObject *_PyCodec_Lookup(const char *encoding) int PyCodec_KnownEncoding(const char *encoding) { PyObject *codecs; - + codecs = _PyCodec_Lookup(encoding); if (!codecs) { - PyErr_Clear(); - return 0; + PyErr_Clear(); + return 0; } else { - Py_DECREF(codecs); - return 1; + Py_DECREF(codecs); + return 1; } } static PyObject *args_tuple(PyObject *object, - const char *errors) + const char *errors) { PyObject *args; args = PyTuple_New(1 + (errors != NULL)); if (args == NULL) - return NULL; + return NULL; Py_INCREF(object); PyTuple_SET_ITEM(args,0,object); if (errors) { - PyObject *v; - - v = PyUnicode_FromString(errors); - if (v == NULL) { - Py_DECREF(args); - return NULL; - } - PyTuple_SET_ITEM(args, 1, v); + PyObject *v; + + v = PyUnicode_FromString(errors); + if (v == NULL) { + Py_DECREF(args); + return NULL; + } + PyTuple_SET_ITEM(args, 1, v); } return args; } @@ -234,7 +234,7 @@ PyObject *codec_getitem(const char *encoding, int index) codecs = _PyCodec_Lookup(encoding); if (codecs == NULL) - return NULL; + return NULL; v = PyTuple_GET_ITEM(codecs, index); Py_DECREF(codecs); Py_INCREF(v); @@ -245,22 +245,22 @@ PyObject *codec_getitem(const char *encoding, int index) static PyObject *codec_getincrementalcodec(const char *encoding, - const char *errors, - const char *attrname) + const char *errors, + const char *attrname) { PyObject *codecs, *ret, *inccodec; codecs = _PyCodec_Lookup(encoding); if (codecs == NULL) - return NULL; + return NULL; inccodec = PyObject_GetAttrString(codecs, attrname); Py_DECREF(codecs); if (inccodec == NULL) - return NULL; + return NULL; if (errors) - ret = PyObject_CallFunction(inccodec, "s", errors); + ret = PyObject_CallFunction(inccodec, "s", errors); else - ret = PyObject_CallFunction(inccodec, NULL); + ret = PyObject_CallFunction(inccodec, NULL); Py_DECREF(inccodec); return ret; } @@ -269,21 +269,21 @@ PyObject *codec_getincrementalcodec(const char *encoding, static PyObject *codec_getstreamcodec(const char *encoding, - PyObject *stream, - const char *errors, - const int index) + PyObject *stream, + const char *errors, + const int index) { PyObject *codecs, *streamcodec, *codeccls; codecs = _PyCodec_Lookup(encoding); if (codecs == NULL) - return NULL; + return NULL; codeccls = PyTuple_GET_ITEM(codecs, index); if (errors != NULL) - streamcodec = PyObject_CallFunction(codeccls, "Os", stream, errors); + streamcodec = PyObject_CallFunction(codeccls, "Os", stream, errors); else - streamcodec = PyObject_CallFunction(codeccls, "O", stream); + streamcodec = PyObject_CallFunction(codeccls, "O", stream); Py_DECREF(codecs); return streamcodec; } @@ -305,27 +305,27 @@ PyObject *PyCodec_Decoder(const char *encoding) } PyObject *PyCodec_IncrementalEncoder(const char *encoding, - const char *errors) + const char *errors) { return codec_getincrementalcodec(encoding, errors, "incrementalencoder"); } PyObject *PyCodec_IncrementalDecoder(const char *encoding, - const char *errors) + const char *errors) { return codec_getincrementalcodec(encoding, errors, "incrementaldecoder"); } PyObject *PyCodec_StreamReader(const char *encoding, - PyObject *stream, - const char *errors) + PyObject *stream, + const char *errors) { return codec_getstreamcodec(encoding, stream, errors, 2); } PyObject *PyCodec_StreamWriter(const char *encoding, - PyObject *stream, - const char *errors) + PyObject *stream, + const char *errors) { return codec_getstreamcodec(encoding, stream, errors, 3); } @@ -336,8 +336,8 @@ PyObject *PyCodec_StreamWriter(const char *encoding, errors is passed to the encoder factory as argument if non-NULL. */ PyObject *PyCodec_Encode(PyObject *object, - const char *encoding, - const char *errors) + const char *encoding, + const char *errors) { PyObject *encoder = NULL; PyObject *args = NULL, *result = NULL; @@ -345,21 +345,21 @@ PyObject *PyCodec_Encode(PyObject *object, encoder = PyCodec_Encoder(encoding); if (encoder == NULL) - goto onError; + goto onError; args = args_tuple(object, errors); if (args == NULL) - goto onError; + goto onError; result = PyEval_CallObject(encoder, args); if (result == NULL) - goto onError; + goto onError; if (!PyTuple_Check(result) || - PyTuple_GET_SIZE(result) != 2) { - PyErr_SetString(PyExc_TypeError, - "encoder must return a tuple (object, integer)"); - goto onError; + 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); @@ -369,7 +369,7 @@ PyObject *PyCodec_Encode(PyObject *object, Py_DECREF(encoder); Py_DECREF(result); return v; - + onError: Py_XDECREF(result); Py_XDECREF(args); @@ -383,8 +383,8 @@ PyObject *PyCodec_Encode(PyObject *object, errors is passed to the decoder factory as argument if non-NULL. */ PyObject *PyCodec_Decode(PyObject *object, - const char *encoding, - const char *errors) + const char *encoding, + const char *errors) { PyObject *decoder = NULL; PyObject *args = NULL, *result = NULL; @@ -392,20 +392,20 @@ PyObject *PyCodec_Decode(PyObject *object, decoder = PyCodec_Decoder(encoding); if (decoder == NULL) - goto onError; + goto onError; args = args_tuple(object, errors); if (args == NULL) - goto onError; + goto onError; result = PyEval_CallObject(decoder,args); if (result == NULL) - goto onError; + goto onError; if (!PyTuple_Check(result) || - PyTuple_GET_SIZE(result) != 2) { - PyErr_SetString(PyExc_TypeError, - "decoder must return a tuple (object,integer)"); - goto onError; + 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); @@ -433,13 +433,13 @@ int PyCodec_RegisterError(const char *name, PyObject *error) { PyInterpreterState *interp = PyThreadState_GET()->interp; if (interp->codec_search_path == NULL && _PyCodecRegistry_Init()) - return -1; + return -1; if (!PyCallable_Check(error)) { - PyErr_SetString(PyExc_TypeError, "handler must be callable"); - return -1; + PyErr_SetString(PyExc_TypeError, "handler must be callable"); + return -1; } return PyDict_SetItemString(interp->codec_error_registry, - (char *)name, error); + (char *)name, error); } /* Lookup the error handling callback function registered under the @@ -451,15 +451,15 @@ PyObject *PyCodec_LookupError(const char *name) PyInterpreterState *interp = PyThreadState_GET()->interp; if (interp->codec_search_path == NULL && _PyCodecRegistry_Init()) - return NULL; + return NULL; if (name==NULL) - name = "strict"; + name = "strict"; handler = PyDict_GetItemString(interp->codec_error_registry, (char *)name); if (!handler) - PyErr_Format(PyExc_LookupError, "unknown error handler name '%.400s'", name); + PyErr_Format(PyExc_LookupError, "unknown error handler name '%.400s'", name); else - Py_INCREF(handler); + Py_INCREF(handler); return handler; } @@ -482,7 +482,7 @@ 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"); + PyErr_SetString(PyExc_TypeError, "codec must pass exception instance"); return NULL; } @@ -491,20 +491,20 @@ PyObject *PyCodec_IgnoreErrors(PyObject *exc) { Py_ssize_t end; if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { - if (PyUnicodeEncodeError_GetEnd(exc, &end)) - return NULL; + if (PyUnicodeEncodeError_GetEnd(exc, &end)) + return NULL; } else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { - if (PyUnicodeDecodeError_GetEnd(exc, &end)) - return NULL; + if (PyUnicodeDecodeError_GetEnd(exc, &end)) + return NULL; } else if (PyObject_IsInstance(exc, PyExc_UnicodeTranslateError)) { - if (PyUnicodeTranslateError_GetEnd(exc, &end)) - return NULL; + if (PyUnicodeTranslateError_GetEnd(exc, &end)) + return NULL; } else { - wrong_exception_type(exc); - return NULL; + wrong_exception_type(exc); + return NULL; } /* ouch: passing NULL, 0, pos gives None instead of u'' */ return Py_BuildValue("(u#n)", &end, 0, end); @@ -519,155 +519,155 @@ PyObject *PyCodec_ReplaceErrors(PyObject *exc) 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; - i0) { - *outp++ = '0' + c/base; - c %= base; - base /= 10; - } - *outp++ = ';'; - } - restuple = Py_BuildValue("(On)", res, end); - Py_DECREF(res); - Py_DECREF(object); - return restuple; + 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; + wrong_exception_type(exc); + return NULL; } } @@ -679,72 +679,72 @@ static Py_UNICODE hexdigits[] = { 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) { + 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 + 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++ = '\\'; + 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 + 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; + 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; + wrong_exception_type(exc); + return NULL; } } @@ -759,73 +759,73 @@ PyCodec_SurrogatePassErrors(PyObject *exc) Py_ssize_t end; PyObject *res; if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { - Py_UNICODE *p; - Py_UNICODE *startp; - char *outp; - 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); - res = PyBytes_FromStringAndSize(NULL, 3*(end-start)); - if (!res) { - Py_DECREF(object); - return NULL; - } - outp = PyBytes_AsString(res); - for (p = startp+start; p < startp+end; p++) { - Py_UNICODE ch = *p; - if (ch < 0xd800 || ch > 0xdfff) { - /* Not a surrogate, fail with original exception */ - PyErr_SetObject(PyExceptionInstance_Class(exc), exc); - Py_DECREF(res); - Py_DECREF(object); - return NULL; - } - *outp++ = (char)(0xe0 | (ch >> 12)); - *outp++ = (char)(0x80 | ((ch >> 6) & 0x3f)); - *outp++ = (char)(0x80 | (ch & 0x3f)); - } - restuple = Py_BuildValue("(On)", res, end); - Py_DECREF(res); - Py_DECREF(object); - return restuple; + Py_UNICODE *p; + Py_UNICODE *startp; + char *outp; + 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); + res = PyBytes_FromStringAndSize(NULL, 3*(end-start)); + if (!res) { + Py_DECREF(object); + return NULL; + } + outp = PyBytes_AsString(res); + for (p = startp+start; p < startp+end; p++) { + Py_UNICODE ch = *p; + if (ch < 0xd800 || ch > 0xdfff) { + /* Not a surrogate, fail with original exception */ + PyErr_SetObject(PyExceptionInstance_Class(exc), exc); + Py_DECREF(res); + Py_DECREF(object); + return NULL; + } + *outp++ = (char)(0xe0 | (ch >> 12)); + *outp++ = (char)(0x80 | ((ch >> 6) & 0x3f)); + *outp++ = (char)(0x80 | (ch & 0x3f)); + } + restuple = Py_BuildValue("(On)", res, end); + Py_DECREF(res); + Py_DECREF(object); + return restuple; } else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { - unsigned char *p; - Py_UNICODE ch = 0; - if (PyUnicodeDecodeError_GetStart(exc, &start)) - return NULL; - if (!(object = PyUnicodeDecodeError_GetObject(exc))) - return NULL; - if (!(p = (unsigned char*)PyBytes_AsString(object))) { - Py_DECREF(object); - return NULL; - } - /* Try decoding a single surrogate character. If - there are more, let the codec call us again. */ - p += start; - if ((p[0] & 0xf0) == 0xe0 || - (p[1] & 0xc0) == 0x80 || - (p[2] & 0xc0) == 0x80) { - /* it's a three-byte code */ - ch = ((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6) + (p[2] & 0x3f); - if (ch < 0xd800 || ch > 0xdfff) - /* it's not a surrogate - fail */ - ch = 0; - } - Py_DECREF(object); - if (ch == 0) { - PyErr_SetObject(PyExceptionInstance_Class(exc), exc); - return NULL; - } - return Py_BuildValue("(u#n)", &ch, 1, start+3); + unsigned char *p; + Py_UNICODE ch = 0; + if (PyUnicodeDecodeError_GetStart(exc, &start)) + return NULL; + if (!(object = PyUnicodeDecodeError_GetObject(exc))) + return NULL; + if (!(p = (unsigned char*)PyBytes_AsString(object))) { + Py_DECREF(object); + return NULL; + } + /* Try decoding a single surrogate character. If + there are more, let the codec call us again. */ + p += start; + if ((p[0] & 0xf0) == 0xe0 || + (p[1] & 0xc0) == 0x80 || + (p[2] & 0xc0) == 0x80) { + /* it's a three-byte code */ + ch = ((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6) + (p[2] & 0x3f); + if (ch < 0xd800 || ch > 0xdfff) + /* it's not a surrogate - fail */ + ch = 0; + } + Py_DECREF(object); + if (ch == 0) { + PyErr_SetObject(PyExceptionInstance_Class(exc), exc); + return NULL; + } + return Py_BuildValue("(u#n)", &ch, 1, start+3); } else { - wrong_exception_type(exc); - return NULL; + wrong_exception_type(exc); + return NULL; } } @@ -838,74 +838,74 @@ PyCodec_SurrogateEscapeErrors(PyObject *exc) Py_ssize_t end; PyObject *res; if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { - Py_UNICODE *p; - Py_UNICODE *startp; - char *outp; - 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); - res = PyBytes_FromStringAndSize(NULL, end-start); - if (!res) { - Py_DECREF(object); - return NULL; - } - outp = PyBytes_AsString(res); - for (p = startp+start; p < startp+end; p++) { - Py_UNICODE ch = *p; - if (ch < 0xdc80 || ch > 0xdcff) { - /* Not a UTF-8b surrogate, fail with original exception */ - PyErr_SetObject(PyExceptionInstance_Class(exc), exc); - Py_DECREF(res); - Py_DECREF(object); - return NULL; - } - *outp++ = ch - 0xdc00; - } - restuple = Py_BuildValue("(On)", res, end); - Py_DECREF(res); - Py_DECREF(object); - return restuple; + Py_UNICODE *p; + Py_UNICODE *startp; + char *outp; + 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); + res = PyBytes_FromStringAndSize(NULL, end-start); + if (!res) { + Py_DECREF(object); + return NULL; + } + outp = PyBytes_AsString(res); + for (p = startp+start; p < startp+end; p++) { + Py_UNICODE ch = *p; + if (ch < 0xdc80 || ch > 0xdcff) { + /* Not a UTF-8b surrogate, fail with original exception */ + PyErr_SetObject(PyExceptionInstance_Class(exc), exc); + Py_DECREF(res); + Py_DECREF(object); + return NULL; + } + *outp++ = ch - 0xdc00; + } + restuple = Py_BuildValue("(On)", res, end); + Py_DECREF(res); + Py_DECREF(object); + return restuple; } else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { - unsigned char *p; - Py_UNICODE ch[4]; /* decode up to 4 bad bytes. */ - int consumed = 0; - if (PyUnicodeDecodeError_GetStart(exc, &start)) - return NULL; - if (PyUnicodeDecodeError_GetEnd(exc, &end)) - return NULL; - if (!(object = PyUnicodeDecodeError_GetObject(exc))) - return NULL; - if (!(p = (unsigned char*)PyBytes_AsString(object))) { - Py_DECREF(object); - return NULL; - } - while (consumed < 4 && consumed < end-start) { - /* Refuse to escape ASCII bytes. */ - if (p[start+consumed] < 128) - break; - ch[consumed] = 0xdc00 + p[start+consumed]; - consumed++; - } - Py_DECREF(object); - if (!consumed) { - /* codec complained about ASCII byte. */ - PyErr_SetObject(PyExceptionInstance_Class(exc), exc); - return NULL; - } - return Py_BuildValue("(u#n)", ch, consumed, start+consumed); + unsigned char *p; + Py_UNICODE ch[4]; /* decode up to 4 bad bytes. */ + int consumed = 0; + if (PyUnicodeDecodeError_GetStart(exc, &start)) + return NULL; + if (PyUnicodeDecodeError_GetEnd(exc, &end)) + return NULL; + if (!(object = PyUnicodeDecodeError_GetObject(exc))) + return NULL; + if (!(p = (unsigned char*)PyBytes_AsString(object))) { + Py_DECREF(object); + return NULL; + } + while (consumed < 4 && consumed < end-start) { + /* Refuse to escape ASCII bytes. */ + if (p[start+consumed] < 128) + break; + ch[consumed] = 0xdc00 + p[start+consumed]; + consumed++; + } + Py_DECREF(object); + if (!consumed) { + /* codec complained about ASCII byte. */ + PyErr_SetObject(PyExceptionInstance_Class(exc), exc); + return NULL; + } + return Py_BuildValue("(u#n)", ch, consumed, start+consumed); } else { - wrong_exception_type(exc); - return NULL; + wrong_exception_type(exc); + return NULL; } } - + static PyObject *strict_errors(PyObject *self, PyObject *exc) { return PyCodec_StrictErrors(exc); @@ -948,78 +948,78 @@ static PyObject *surrogateescape_errors(PyObject *self, PyObject *exc) static int _PyCodecRegistry_Init(void) { static struct { - char *name; - PyMethodDef def; + char *name; + PyMethodDef def; } methods[] = { - { - "strict", - { - "strict_errors", - strict_errors, - METH_O, - PyDoc_STR("Implements the 'strict' error handling, which " - "raises a UnicodeError on coding errors.") - } - }, - { - "ignore", - { - "ignore_errors", - ignore_errors, - METH_O, - PyDoc_STR("Implements the 'ignore' error handling, which " - "ignores malformed data and continues.") - } - }, - { - "replace", - { - "replace_errors", - replace_errors, - METH_O, - PyDoc_STR("Implements the 'replace' error handling, which " - "replaces malformed data with a replacement marker.") - } - }, - { - "xmlcharrefreplace", - { - "xmlcharrefreplace_errors", - xmlcharrefreplace_errors, - METH_O, - PyDoc_STR("Implements the 'xmlcharrefreplace' error handling, " - "which replaces an unencodable character with the " - "appropriate XML character reference.") - } - }, - { - "backslashreplace", - { - "backslashreplace_errors", - backslashreplace_errors, - METH_O, - PyDoc_STR("Implements the 'backslashreplace' error handling, " - "which replaces an unencodable character with a " - "backslashed escape sequence.") - } - }, - { - "surrogatepass", - { - "surrogatepass", - surrogatepass_errors, - METH_O - } - }, - { - "surrogateescape", - { - "surrogateescape", - surrogateescape_errors, - METH_O - } - } + { + "strict", + { + "strict_errors", + strict_errors, + METH_O, + PyDoc_STR("Implements the 'strict' error handling, which " + "raises a UnicodeError on coding errors.") + } + }, + { + "ignore", + { + "ignore_errors", + ignore_errors, + METH_O, + PyDoc_STR("Implements the 'ignore' error handling, which " + "ignores malformed data and continues.") + } + }, + { + "replace", + { + "replace_errors", + replace_errors, + METH_O, + PyDoc_STR("Implements the 'replace' error handling, which " + "replaces malformed data with a replacement marker.") + } + }, + { + "xmlcharrefreplace", + { + "xmlcharrefreplace_errors", + xmlcharrefreplace_errors, + METH_O, + PyDoc_STR("Implements the 'xmlcharrefreplace' error handling, " + "which replaces an unencodable character with the " + "appropriate XML character reference.") + } + }, + { + "backslashreplace", + { + "backslashreplace_errors", + backslashreplace_errors, + METH_O, + PyDoc_STR("Implements the 'backslashreplace' error handling, " + "which replaces an unencodable character with a " + "backslashed escape sequence.") + } + }, + { + "surrogatepass", + { + "surrogatepass", + surrogatepass_errors, + METH_O + } + }, + { + "surrogateescape", + { + "surrogateescape", + surrogateescape_errors, + METH_O + } + } }; PyInterpreterState *interp = PyThreadState_GET()->interp; @@ -1027,42 +1027,42 @@ static int _PyCodecRegistry_Init(void) unsigned i; if (interp->codec_search_path != NULL) - return 0; + 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"); - } + 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"); + interp->codec_search_cache == NULL || + interp->codec_error_registry == NULL) + Py_FatalError("can't initialize codec registry"); mod = PyImport_ImportModuleNoBlock("encodings"); 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; + 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); interp->codecs_initialized = 1; diff --git a/Python/compile.c b/Python/compile.c index 62fa46c615..fa7dcef5fb 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -5,10 +5,10 @@ * 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. + * 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. + * this file. * 5. Optimize the byte code (peephole optimizations). See peephole.c * * Note that compiler_mod() suggests module, but the module ast type @@ -45,37 +45,37 @@ int Py_OptimizeFlag = 0; #define COMP_DICTCOMP 3 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; + 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; + 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. @@ -88,64 +88,64 @@ compiler IR. enum fblocktype { LOOP, EXCEPT, FINALLY_TRY, FINALLY_END }; struct fblockinfo { - enum fblocktype fb_type; - basicblock *fb_block; + 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 */ - int u_kwonlyargcount; /* number of keyword only 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_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 */ - int u_lineno_set; /* boolean to indicate whether instr - has been generated with current lineno */ + 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 */ + int u_kwonlyargcount; /* number of keyword only 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_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 */ + int u_lineno_set; /* boolean to indicate whether instr + has been generated with current lineno */ }; -/* This struct captures the global state of a compilation. +/* 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 +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; + 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; + 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 */ - PyArena *c_arena; /* pointer to memory allocation arena */ + struct compiler_unit *u; /* compiler state for current block */ + PyObject *c_stack; /* Python list holding compiler_unit ptrs */ + PyArena *c_arena; /* pointer to memory allocation arena */ }; static int compiler_enter_scope(struct compiler *, identifier, void *, int); @@ -166,12 +166,12 @@ 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); + expr_context_ty); static int compiler_push_fblock(struct compiler *, enum fblocktype, - basicblock *); + basicblock *); static void compiler_pop_fblock(struct compiler *, enum fblocktype, - basicblock *); + basicblock *); /* Returns true if there is a loop on the fblock stack. */ static int compiler_in_loop(struct compiler *); @@ -180,10 +180,10 @@ static int expr_constant(expr_ty e); static int compiler_with(struct compiler *, stmt_ty); static int compiler_call_helper(struct compiler *c, int n, - asdl_seq *args, - asdl_seq *keywords, - expr_ty starargs, - expr_ty kwargs); + asdl_seq *args, + asdl_seq *keywords, + expr_ty starargs, + expr_ty kwargs); static PyCodeObject *assemble(struct compiler *, int addNone); static PyObject *__doc__; @@ -193,172 +193,172 @@ 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 Py_UNICODE *p, *name = PyUnicode_AS_UNICODE(ident); - Py_UNICODE *buffer; - size_t nlen, plen; - if (privateobj == NULL || !PyUnicode_Check(privateobj) || - name == NULL || name[0] != '_' || name[1] != '_') { - Py_INCREF(ident); - return ident; - } - p = PyUnicode_AS_UNICODE(privateobj); - nlen = Py_UNICODE_strlen(name); - /* Don't mangle __id__ or names with dots. - - The only time a name with a dot can occur is when - we are compiling an import statement that has a - package name. - - TODO(jhylton): Decide whether we want to support - mangling of the module name, e.g. __M.X. - */ - if ((name[nlen-1] == '_' && name[nlen-2] == '_') - || Py_UNICODE_strchr(name, '.')) { - 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 = Py_UNICODE_strlen(p); - - assert(1 <= PY_SSIZE_T_MAX - nlen); - assert(1 + nlen <= PY_SSIZE_T_MAX - plen); - - ident = PyUnicode_FromStringAndSize(NULL, 1 + nlen + plen); - if (!ident) - return 0; - /* ident = "_" + p[:plen] + name # i.e. 1+plen+nlen bytes */ - buffer = PyUnicode_AS_UNICODE(ident); - buffer[0] = '_'; - Py_UNICODE_strncpy(buffer+1, p, plen); - Py_UNICODE_strcpy(buffer+1+plen, name); - return ident; + /* Name mangling: __private becomes _classname__private. + This is independent from how the name is used. */ + const Py_UNICODE *p, *name = PyUnicode_AS_UNICODE(ident); + Py_UNICODE *buffer; + size_t nlen, plen; + if (privateobj == NULL || !PyUnicode_Check(privateobj) || + name == NULL || name[0] != '_' || name[1] != '_') { + Py_INCREF(ident); + return ident; + } + p = PyUnicode_AS_UNICODE(privateobj); + nlen = Py_UNICODE_strlen(name); + /* Don't mangle __id__ or names with dots. + + The only time a name with a dot can occur is when + we are compiling an import statement that has a + package name. + + TODO(jhylton): Decide whether we want to support + mangling of the module name, e.g. __M.X. + */ + if ((name[nlen-1] == '_' && name[nlen-2] == '_') + || Py_UNICODE_strchr(name, '.')) { + 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 = Py_UNICODE_strlen(p); + + assert(1 <= PY_SSIZE_T_MAX - nlen); + assert(1 + nlen <= PY_SSIZE_T_MAX - plen); + + ident = PyUnicode_FromStringAndSize(NULL, 1 + nlen + plen); + if (!ident) + return 0; + /* ident = "_" + p[:plen] + name # i.e. 1+plen+nlen bytes */ + buffer = PyUnicode_AS_UNICODE(ident); + buffer[0] = '_'; + Py_UNICODE_strncpy(buffer+1, p, plen); + Py_UNICODE_strcpy(buffer+1+plen, name); + return ident; } static int compiler_init(struct compiler *c) { - memset(c, 0, sizeof(struct compiler)); + memset(c, 0, sizeof(struct compiler)); - c->c_stack = PyList_New(0); - if (!c->c_stack) - return 0; + c->c_stack = PyList_New(0); + if (!c->c_stack) + return 0; - return 1; + 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__ = PyUnicode_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; - } - - co = compiler_mod(&c, mod); + PyArena *arena) +{ + struct compiler c; + PyCodeObject *co = NULL; + PyCompilerFlags local_flags; + int merged; + + if (!__doc__) { + __doc__ = PyUnicode_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; + } + + co = compiler_mod(&c, mod); finally: - compiler_free(&c); - assert(co || PyErr_Occurred()); - return co; + 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; + 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); + 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 = PyLong_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; + 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 = PyLong_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 +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. */ @@ -366,182 +366,182 @@ 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 */ - long vi; - assert(PyLong_Check(v)); - vi = PyLong_AS_LONG(v); - scope = (vi >> SCOPE_OFFSET) & SCOPE_MASK; - - if (scope == scope_type || vi & flag) { - PyObject *tuple, *item = PyLong_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; + 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 */ + long vi; + assert(PyLong_Check(v)); + vi = PyLong_AS_LONG(v); + scope = (vi >> SCOPE_OFFSET) & SCOPE_MASK; + + if (scope == scope_type || vi & flag) { + PyObject *tuple, *item = PyLong_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; } static void compiler_unit_check(struct compiler_unit *u) { - basicblock *block; - for (block = u->u_blocks; block != NULL; block = block->b_list) { - assert((void *)block != (void *)0xcbcbcbcb); - assert((void *)block != (void *)0xfbfbfbfb); - assert((void *)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); - } - } + basicblock *block; + for (block = u->u_blocks; block != NULL; block = block->b_list) { + assert((void *)block != (void *)0xcbcbcbcb); + assert((void *)block != (void *)0xfbfbfbfb); + assert((void *)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); + 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_kwonlyargcount = 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_nfblocks = 0; - u->u_firstlineno = lineno; - u->u_lineno = 0; - u->u_lineno_set = 0; - 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 *capsule = PyCapsule_New(c->u, COMPILER_CAPSULE_NAME_COMPILER_UNIT, NULL); - if (!capsule || PyList_Append(c->c_stack, capsule) < 0) { - Py_XDECREF(capsule); - compiler_unit_free(u); - return 0; - } - Py_DECREF(capsule); - 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; + 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_kwonlyargcount = 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_nfblocks = 0; + u->u_firstlineno = lineno; + u->u_lineno = 0; + u->u_lineno_set = 0; + 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 *capsule = PyCapsule_New(c->u, COMPILER_CAPSULE_NAME_COMPILER_UNIT, NULL); + if (!capsule || PyList_Append(c->c_stack, capsule) < 0) { + Py_XDECREF(capsule); + compiler_unit_free(u); + return 0; + } + Py_DECREF(capsule); + 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 *capsule; - - 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) { - capsule = PyList_GET_ITEM(c->c_stack, n); - c->u = (struct compiler_unit *)PyCapsule_GetPointer(capsule, COMPILER_CAPSULE_NAME_COMPILER_UNIT); - assert(c->u); - /* 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; + int n; + PyObject *capsule; + + 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) { + capsule = PyList_GET_ITEM(c->c_stack, n); + c->u = (struct compiler_unit *)PyCapsule_GetPointer(capsule, COMPILER_CAPSULE_NAME_COMPILER_UNIT); + assert(c->u); + /* 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; } @@ -552,50 +552,50 @@ compiler_exit_scope(struct compiler *c) static basicblock * compiler_new_block(struct compiler *c) { - basicblock *b; - struct compiler_unit *u; + 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; + 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; + 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; + 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; + 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 @@ -606,44 +606,44 @@ compiler_use_next_block(struct compiler *c, basicblock *block) 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 (oldsize > (PY_SIZE_MAX >> 1)) { - PyErr_NoMemory(); - return -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++; + 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 (oldsize > (PY_SIZE_MAX >> 1)) { + PyErr_NoMemory(); + return -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 offset off if the @@ -661,210 +661,210 @@ compiler_next_instr(struct compiler *c, basicblock *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 = 1; - b = c->u->u_curblock; - b->b_instr[off].i_lineno = c->u->u_lineno; + basicblock *b; + if (c->u->u_lineno_set) + return; + c->u->u_lineno_set = 1; + 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_INVERT: - return 0; - - case SET_ADD: - case LIST_APPEND: - return -1; - case MAP_ADD: - return -2; - - case BINARY_POWER: - case BINARY_MULTIPLY: - 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 INPLACE_ADD: - case INPLACE_SUBTRACT: - case INPLACE_MULTIPLY: - case INPLACE_MODULO: - return -1; - case STORE_SUBSCR: - return -3; - case STORE_MAP: - return -2; - 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 LOAD_BUILD_CLASS: - 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 SETUP_WITH: - return 7; - case WITH_CLEANUP: - return -1; /* XXX Sometimes more */ - case STORE_LOCALS: - return -1; - case RETURN_VALUE: - return -1; - case IMPORT_STAR: - return -1; - case YIELD_VALUE: - return 0; - - case POP_BLOCK: - return 0; - case POP_EXCEPT: - return 0; /* -3 except if bad bytecode */ - case END_FINALLY: - return -1; /* or -2 or -3 if exception occurred */ - - case STORE_NAME: - return -1; - case DELETE_NAME: - return 0; - case UNPACK_SEQUENCE: - return oparg-1; - case UNPACK_EX: - return (oparg&0xFF) + (oparg>>8); - case FOR_ITER: - return 1; /* or -1, at end of iterator */ - - 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: - case BUILD_SET: - return 1-oparg; - case BUILD_MAP: - return 1; - case LOAD_ATTR: - return 0; - case COMPARE_OP: - return -1; - case IMPORT_NAME: - return -1; - case IMPORT_FROM: - return 1; - - case JUMP_FORWARD: - case JUMP_IF_TRUE_OR_POP: /* -1 if jump not taken */ - case JUMP_IF_FALSE_OR_POP: /* "" */ - case JUMP_ABSOLUTE: - return 0; - - case POP_JUMP_IF_FALSE: - case POP_JUMP_IF_TRUE: - return -1; - - case LOAD_GLOBAL: - return 1; - - case CONTINUE_LOOP: - return 0; - case SETUP_LOOP: - return 0; - case SETUP_EXCEPT: - case SETUP_FINALLY: - return 6; /* can push 3 values for the new exception - + 3 others for the previous exception state */ - - case LOAD_FAST: - return 1; - case STORE_FAST: - return -1; - case DELETE_FAST: - return 0; - - case RAISE_VARARGS: - return -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_INVERT: + return 0; + + case SET_ADD: + case LIST_APPEND: + return -1; + case MAP_ADD: + return -2; + + case BINARY_POWER: + case BINARY_MULTIPLY: + 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 INPLACE_ADD: + case INPLACE_SUBTRACT: + case INPLACE_MULTIPLY: + case INPLACE_MODULO: + return -1; + case STORE_SUBSCR: + return -3; + case STORE_MAP: + return -2; + 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 LOAD_BUILD_CLASS: + 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 SETUP_WITH: + return 7; + case WITH_CLEANUP: + return -1; /* XXX Sometimes more */ + case STORE_LOCALS: + return -1; + case RETURN_VALUE: + return -1; + case IMPORT_STAR: + return -1; + case YIELD_VALUE: + return 0; + + case POP_BLOCK: + return 0; + case POP_EXCEPT: + return 0; /* -3 except if bad bytecode */ + case END_FINALLY: + return -1; /* or -2 or -3 if exception occurred */ + + case STORE_NAME: + return -1; + case DELETE_NAME: + return 0; + case UNPACK_SEQUENCE: + return oparg-1; + case UNPACK_EX: + return (oparg&0xFF) + (oparg>>8); + case FOR_ITER: + return 1; /* or -1, at end of iterator */ + + 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: + case BUILD_SET: + return 1-oparg; + case BUILD_MAP: + return 1; + case LOAD_ATTR: + return 0; + case COMPARE_OP: + return -1; + case IMPORT_NAME: + return -1; + case IMPORT_FROM: + return 1; + + case JUMP_FORWARD: + case JUMP_IF_TRUE_OR_POP: /* -1 if jump not taken */ + case JUMP_IF_FALSE_OR_POP: /* "" */ + case JUMP_ABSOLUTE: + return 0; + + case POP_JUMP_IF_FALSE: + case POP_JUMP_IF_TRUE: + return -1; + + case LOAD_GLOBAL: + return 1; + + case CONTINUE_LOOP: + return 0; + case SETUP_LOOP: + return 0; + case SETUP_EXCEPT: + case SETUP_FINALLY: + return 6; /* can push 3 values for the new exception + + 3 others for the previous exception state */ + + 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) % 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; - case MAKE_FUNCTION: - return -NARGS(oparg) - ((oparg >> 16) & 0xffff); - case MAKE_CLOSURE: - return -1 - NARGS(oparg) - ((oparg >> 16) & 0xffff); + 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; + case MAKE_FUNCTION: + return -NARGS(oparg) - ((oparg >> 16) & 0xffff); + case MAKE_CLOSURE: + return -1 - NARGS(oparg) - ((oparg >> 16) & 0xffff); #undef NARGS - case BUILD_SLICE: - if (oparg == 3) - return -2; - else - return -1; - - 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 */ + case BUILD_SLICE: + if (oparg == 3) + return -2; + else + return -1; + + 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. @@ -874,116 +874,116 @@ opcode_stack_effect(int opcode, int oparg) 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; + 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; - double d; - - /* necessary to make sure types aren't coerced (e.g., int and long) */ - /* _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms */ - if (PyFloat_Check(o)) { - d = PyFloat_AS_DOUBLE(o); - /* all we need is to make the tuple different in either the 0.0 - * or -0.0 case from all others, just to avoid the "coercion". - */ - if (d == 0.0 && copysign(1.0, d) < 0.0) - t = PyTuple_Pack(3, o, o->ob_type, Py_None); - else - t = PyTuple_Pack(2, o, o->ob_type); - } - else if (PyComplex_Check(o)) { - Py_complex z; - int real_negzero, imag_negzero; - /* For the complex case we must make complex(x, 0.) - different from complex(x, -0.) and complex(0., y) - different from complex(-0., y), for any x and y. - All four complex zeros must be distinguished.*/ - z = PyComplex_AsCComplex(o); - real_negzero = z.real == 0.0 && copysign(1.0, z.real) < 0.0; - imag_negzero = z.imag == 0.0 && copysign(1.0, z.imag) < 0.0; - if (real_negzero && imag_negzero) { - t = PyTuple_Pack(5, o, o->ob_type, - Py_None, Py_None, Py_None); - } - else if (imag_negzero) { - t = PyTuple_Pack(4, o, o->ob_type, Py_None, Py_None); - } - else if (real_negzero) { - t = PyTuple_Pack(3, o, o->ob_type, Py_None); - } - else { - t = PyTuple_Pack(2, o, o->ob_type); - } - } - else { - t = PyTuple_Pack(2, o, o->ob_type); - } - if (t == NULL) - return -1; - - v = PyDict_GetItem(dict, t); - if (!v) { - if (PyErr_Occurred()) - return -1; - arg = PyDict_Size(dict); - v = PyLong_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 = PyLong_AsLong(v); - Py_DECREF(t); - return arg; + PyObject *t, *v; + Py_ssize_t arg; + double d; + + /* necessary to make sure types aren't coerced (e.g., int and long) */ + /* _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms */ + if (PyFloat_Check(o)) { + d = PyFloat_AS_DOUBLE(o); + /* all we need is to make the tuple different in either the 0.0 + * or -0.0 case from all others, just to avoid the "coercion". + */ + if (d == 0.0 && copysign(1.0, d) < 0.0) + t = PyTuple_Pack(3, o, o->ob_type, Py_None); + else + t = PyTuple_Pack(2, o, o->ob_type); + } + else if (PyComplex_Check(o)) { + Py_complex z; + int real_negzero, imag_negzero; + /* For the complex case we must make complex(x, 0.) + different from complex(x, -0.) and complex(0., y) + different from complex(-0., y), for any x and y. + All four complex zeros must be distinguished.*/ + z = PyComplex_AsCComplex(o); + real_negzero = z.real == 0.0 && copysign(1.0, z.real) < 0.0; + imag_negzero = z.imag == 0.0 && copysign(1.0, z.imag) < 0.0; + if (real_negzero && imag_negzero) { + t = PyTuple_Pack(5, o, o->ob_type, + Py_None, Py_None, Py_None); + } + else if (imag_negzero) { + t = PyTuple_Pack(4, o, o->ob_type, Py_None, Py_None); + } + else if (real_negzero) { + t = PyTuple_Pack(3, o, o->ob_type, Py_None); + } + else { + t = PyTuple_Pack(2, o, o->ob_type); + } + } + else { + t = PyTuple_Pack(2, o, o->ob_type); + } + if (t == NULL) + return -1; + + v = PyDict_GetItem(dict, t); + if (!v) { + if (PyErr_Occurred()) + return -1; + arg = PyDict_Size(dict); + v = PyLong_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 = PyLong_AsLong(v); + Py_DECREF(t); + return arg; } static int compiler_addop_o(struct compiler *c, int opcode, PyObject *dict, - PyObject *o) + PyObject *o) { int arg = compiler_add_o(c, dict, o); if (arg < 0) - return 0; + return 0; return compiler_addop_i(c, opcode, arg); } static int compiler_addop_name(struct compiler *c, int opcode, PyObject *dict, - PyObject *o) + PyObject *o) { int arg; PyObject *mangled = _Py_Mangle(c->u->u_private, o); if (!mangled) - return 0; + return 0; arg = compiler_add_o(c, dict, mangled); Py_DECREF(mangled); if (arg < 0) - return 0; + return 0; return compiler_addop_i(c, opcode, arg); } @@ -994,43 +994,43 @@ compiler_addop_name(struct compiler *c, int opcode, PyObject *dict, 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; + 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 + 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. */ @@ -1041,50 +1041,50 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute) #define NEW_BLOCK(C) { \ - if (compiler_use_new_block((C)) == NULL) \ - return 0; \ + if (compiler_use_new_block((C)) == NULL) \ + return 0; \ } #define NEXT_BLOCK(C) { \ - if (compiler_next_block((C)) == NULL) \ - return 0; \ + if (compiler_next_block((C)) == NULL) \ + return 0; \ } #define ADDOP(C, OP) { \ - if (!compiler_addop((C), (OP))) \ - return 0; \ + if (!compiler_addop((C), (OP))) \ + return 0; \ } #define ADDOP_IN_SCOPE(C, OP) { \ - if (!compiler_addop((C), (OP))) { \ - compiler_exit_scope(c); \ - return 0; \ - } \ + 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; \ + 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; \ + 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; \ + 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; \ + 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; \ + if (!compiler_addop_j((C), (OP), (O), 0)) \ + return 0; \ } /* VISIT and VISIT_SEQ takes an ASDL type as their second argument. They use @@ -1092,49 +1092,49 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute) */ #define VISIT(C, TYPE, V) {\ - if (!compiler_visit_ ## TYPE((C), (V))) \ - return 0; \ + 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; \ - } \ + 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; \ + 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; \ - } \ + 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; \ - } \ - } \ + 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 0; return s->v.Expr.value->kind == Str_kind; } @@ -1143,67 +1143,67 @@ compiler_isdocstring(stmt_ty s) 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) && Py_OptimizeFlag < 2) { - /* don't generate docstrings if -OO */ - 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; + 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) && Py_OptimizeFlag < 2) { + /* don't generate docstrings if -OO */ + 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 = PyUnicode_InternFromString(""); - 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; + PyCodeObject *co; + int addNone = 1; + static PyObject *module; + if (!module) { + module = PyUnicode_InternFromString(""); + 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 @@ -1214,24 +1214,24 @@ compiler_mod(struct compiler *c, mod_ty mod) 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", - PyBytes_AS_STRING(name), - PyBytes_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); - } + 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", + PyBytes_AS_STRING(name), + PyBytes_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; + return scope; } static int @@ -1240,636 +1240,636 @@ compiler_lookup_arg(PyObject *dict, PyObject *name) PyObject *k, *v; k = PyTuple_Pack(2, name, name->ob_type); if (k == NULL) - return -1; + return -1; v = PyDict_GetItem(dict, k); Py_DECREF(k); if (v == NULL) - return -1; + return -1; return PyLong_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) { - fprintf(stderr, - "lookup %s in %s %d %d\n" - "freevars of %s: %s\n", - PyObject_REPR(name), - PyBytes_AS_STRING(c->u->u_name), - reftype, arg, - _PyUnicode_AsString(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; + 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) { + fprintf(stderr, + "lookup %s in %s %d %d\n" + "freevars of %s: %s\n", + PyObject_REPR(name), + PyBytes_AS_STRING(c->u->u_name), + reftype, arg, + _PyUnicode_AsString(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; + int i; - if (!decos) - return 1; + 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; + for (i = 0; i < asdl_seq_LEN(decos); i++) { + VISIT(c, expr, (expr_ty)asdl_seq_GET(decos, i)); + } + return 1; } static int compiler_visit_kwonlydefaults(struct compiler *c, asdl_seq *kwonlyargs, - asdl_seq *kw_defaults) -{ - int i, default_count = 0; - for (i = 0; i < asdl_seq_LEN(kwonlyargs); i++) { - arg_ty arg = asdl_seq_GET(kwonlyargs, i); - expr_ty default_ = asdl_seq_GET(kw_defaults, i); - if (default_) { - ADDOP_O(c, LOAD_CONST, arg->arg, consts); - if (!compiler_visit_expr(c, default_)) { - return -1; - } - default_count++; - } - } - return default_count; + asdl_seq *kw_defaults) +{ + int i, default_count = 0; + for (i = 0; i < asdl_seq_LEN(kwonlyargs); i++) { + arg_ty arg = asdl_seq_GET(kwonlyargs, i); + expr_ty default_ = asdl_seq_GET(kw_defaults, i); + if (default_) { + ADDOP_O(c, LOAD_CONST, arg->arg, consts); + if (!compiler_visit_expr(c, default_)) { + return -1; + } + default_count++; + } + } + return default_count; } static int compiler_visit_argannotation(struct compiler *c, identifier id, expr_ty annotation, PyObject *names) { - if (annotation) { - VISIT(c, expr, annotation); - if (PyList_Append(names, id)) - return -1; - } - return 0; + if (annotation) { + VISIT(c, expr, annotation); + if (PyList_Append(names, id)) + return -1; + } + return 0; } static int compiler_visit_argannotations(struct compiler *c, asdl_seq* args, PyObject *names) { - int i, error; - for (i = 0; i < asdl_seq_LEN(args); i++) { - arg_ty arg = (arg_ty)asdl_seq_GET(args, i); - error = compiler_visit_argannotation( - c, - arg->arg, - arg->annotation, - names); - if (error) - return error; - } - return 0; + int i, error; + for (i = 0; i < asdl_seq_LEN(args); i++) { + arg_ty arg = (arg_ty)asdl_seq_GET(args, i); + error = compiler_visit_argannotation( + c, + arg->arg, + arg->annotation, + names); + if (error) + return error; + } + return 0; } static int compiler_visit_annotations(struct compiler *c, arguments_ty args, expr_ty returns) { - /* Push arg annotations and a list of the argument names. Return the # - of items pushed. The expressions are evaluated out-of-order wrt the - source code. - - More than 2^16-1 annotations is a SyntaxError. Returns -1 on error. - */ - static identifier return_str; - PyObject *names; - int len; - names = PyList_New(0); - if (!names) - return -1; - - if (compiler_visit_argannotations(c, args->args, names)) - goto error; - if (args->varargannotation && - compiler_visit_argannotation(c, args->vararg, - args->varargannotation, names)) - goto error; - if (compiler_visit_argannotations(c, args->kwonlyargs, names)) - goto error; - if (args->kwargannotation && - compiler_visit_argannotation(c, args->kwarg, - args->kwargannotation, names)) - goto error; - - if (!return_str) { - return_str = PyUnicode_InternFromString("return"); - if (!return_str) - goto error; - } - if (compiler_visit_argannotation(c, return_str, returns, names)) { - goto error; - } - - len = PyList_GET_SIZE(names); - if (len > 65534) { - /* len must fit in 16 bits, and len is incremented below */ - PyErr_SetString(PyExc_SyntaxError, - "too many annotations"); - goto error; - } - if (len) { - /* convert names to a tuple and place on stack */ - PyObject *elt; - int i; - PyObject *s = PyTuple_New(len); - if (!s) - goto error; - for (i = 0; i < len; i++) { - elt = PyList_GET_ITEM(names, i); - Py_INCREF(elt); - PyTuple_SET_ITEM(s, i, elt); - } - ADDOP_O(c, LOAD_CONST, s, consts); - Py_DECREF(s); - len++; /* include the just-pushed tuple */ - } - Py_DECREF(names); - return len; + /* Push arg annotations and a list of the argument names. Return the # + of items pushed. The expressions are evaluated out-of-order wrt the + source code. + + More than 2^16-1 annotations is a SyntaxError. Returns -1 on error. + */ + static identifier return_str; + PyObject *names; + int len; + names = PyList_New(0); + if (!names) + return -1; + + if (compiler_visit_argannotations(c, args->args, names)) + goto error; + if (args->varargannotation && + compiler_visit_argannotation(c, args->vararg, + args->varargannotation, names)) + goto error; + if (compiler_visit_argannotations(c, args->kwonlyargs, names)) + goto error; + if (args->kwargannotation && + compiler_visit_argannotation(c, args->kwarg, + args->kwargannotation, names)) + goto error; + + if (!return_str) { + return_str = PyUnicode_InternFromString("return"); + if (!return_str) + goto error; + } + if (compiler_visit_argannotation(c, return_str, returns, names)) { + goto error; + } + + len = PyList_GET_SIZE(names); + if (len > 65534) { + /* len must fit in 16 bits, and len is incremented below */ + PyErr_SetString(PyExc_SyntaxError, + "too many annotations"); + goto error; + } + if (len) { + /* convert names to a tuple and place on stack */ + PyObject *elt; + int i; + PyObject *s = PyTuple_New(len); + if (!s) + goto error; + for (i = 0; i < len; i++) { + elt = PyList_GET_ITEM(names, i); + Py_INCREF(elt); + PyTuple_SET_ITEM(s, i, elt); + } + ADDOP_O(c, LOAD_CONST, s, consts); + Py_DECREF(s); + len++; /* include the just-pushed tuple */ + } + Py_DECREF(names); + return len; error: - Py_DECREF(names); - return -1; + Py_DECREF(names); + 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; - expr_ty returns = s->v.FunctionDef.returns; - asdl_seq* decos = s->v.FunctionDef.decorator_list; - stmt_ty st; - int i, n, docstring, kw_default_count = 0, arglength; - int num_annotations; - - assert(s->kind == FunctionDef_kind); - - if (!compiler_decorators(c, decos)) - return 0; - if (args->kwonlyargs) { - int res = compiler_visit_kwonlydefaults(c, args->kwonlyargs, - args->kw_defaults); - if (res < 0) - return 0; - kw_default_count = res; - } - if (args->defaults) - VISIT_SEQ(c, expr, args->defaults); - num_annotations = compiler_visit_annotations(c, args, returns); - if (num_annotations < 0) - return 0; - assert((num_annotations & 0xFFFF) == num_annotations); - - 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 && Py_OptimizeFlag < 2) - 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; - } - - c->u->u_argcount = asdl_seq_LEN(args->args); - c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs); - 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; - - arglength = asdl_seq_LEN(args->defaults); - arglength |= kw_default_count << 8; - arglength |= num_annotations << 16; - compiler_make_closure(c, co, arglength); - Py_DECREF(co); - - /* decorators */ - for (i = 0; i < asdl_seq_LEN(decos); i++) { - ADDOP_I(c, CALL_FUNCTION, 1); - } - - return compiler_nameop(c, s->v.FunctionDef.name, Store); + PyCodeObject *co; + PyObject *first_const = Py_None; + arguments_ty args = s->v.FunctionDef.args; + expr_ty returns = s->v.FunctionDef.returns; + asdl_seq* decos = s->v.FunctionDef.decorator_list; + stmt_ty st; + int i, n, docstring, kw_default_count = 0, arglength; + int num_annotations; + + assert(s->kind == FunctionDef_kind); + + if (!compiler_decorators(c, decos)) + return 0; + if (args->kwonlyargs) { + int res = compiler_visit_kwonlydefaults(c, args->kwonlyargs, + args->kw_defaults); + if (res < 0) + return 0; + kw_default_count = res; + } + if (args->defaults) + VISIT_SEQ(c, expr, args->defaults); + num_annotations = compiler_visit_annotations(c, args, returns); + if (num_annotations < 0) + return 0; + assert((num_annotations & 0xFFFF) == num_annotations); + + 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 && Py_OptimizeFlag < 2) + 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; + } + + c->u->u_argcount = asdl_seq_LEN(args->args); + c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs); + 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; + + arglength = asdl_seq_LEN(args->defaults); + arglength |= kw_default_count << 8; + arglength |= num_annotations << 16; + compiler_make_closure(c, co, arglength); + Py_DECREF(co); + + /* decorators */ + 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) { - PyCodeObject *co; - PyObject *str; - int i; - asdl_seq* decos = s->v.ClassDef.decorator_list; - - if (!compiler_decorators(c, decos)) - return 0; - - /* ultimately generate code for: - = __build_class__(, , *, **) - where: - is a function/closure created from the class body; - it has a single argument (__locals__) where the dict - (or MutableSequence) representing the locals is passed - is the class name - is the positional arguments and *varargs argument - is the keyword arguments and **kwds argument - This borrows from compiler_call. - */ - - /* 1. compile the class body into a code object */ - if (!compiler_enter_scope(c, s->v.ClassDef.name, (void *)s, s->lineno)) - return 0; - /* this block represents what we do in the new scope */ - { - /* use the class name for name mangling */ - Py_INCREF(s->v.ClassDef.name); - Py_XDECREF(c->u->u_private); - c->u->u_private = s->v.ClassDef.name; - /* force it to have one mandatory argument */ - c->u->u_argcount = 1; - /* load the first argument (__locals__) ... */ - ADDOP_I(c, LOAD_FAST, 0); - /* ... and store it into f_locals */ - ADDOP_IN_SCOPE(c, STORE_LOCALS); - /* load (global) __name__ ... */ - str = PyUnicode_InternFromString("__name__"); - if (!str || !compiler_nameop(c, str, Load)) { - Py_XDECREF(str); - compiler_exit_scope(c); - return 0; - } - Py_DECREF(str); - /* ... and store it as __module__ */ - str = PyUnicode_InternFromString("__module__"); - if (!str || !compiler_nameop(c, str, Store)) { - Py_XDECREF(str); - compiler_exit_scope(c); - return 0; - } - Py_DECREF(str); - /* compile the body proper */ - if (!compiler_body(c, s->v.ClassDef.body)) { - compiler_exit_scope(c); - return 0; - } - /* return the (empty) __class__ cell */ - str = PyUnicode_InternFromString("__class__"); - if (str == NULL) { - compiler_exit_scope(c); - return 0; - } - i = compiler_lookup_arg(c->u->u_cellvars, str); - Py_DECREF(str); - if (i == -1) { - /* This happens when nobody references the cell */ - PyErr_Clear(); - /* Return None */ - ADDOP_O(c, LOAD_CONST, Py_None, consts); - } - else { - /* Return the cell where to store __class__ */ - ADDOP_I(c, LOAD_CLOSURE, i); - } - ADDOP_IN_SCOPE(c, RETURN_VALUE); - /* create the code object */ - co = assemble(c, 1); - } - /* leave the new scope */ - compiler_exit_scope(c); - if (co == NULL) - return 0; - - /* 2. load the 'build_class' function */ - ADDOP(c, LOAD_BUILD_CLASS); - - /* 3. load a function (or closure) made from the code object */ - compiler_make_closure(c, co, 0); - Py_DECREF(co); - - /* 4. load class name */ - ADDOP_O(c, LOAD_CONST, s->v.ClassDef.name, consts); - - /* 5. generate the rest of the code for the call */ - if (!compiler_call_helper(c, 2, - s->v.ClassDef.bases, - s->v.ClassDef.keywords, - s->v.ClassDef.starargs, - s->v.ClassDef.kwargs)) - return 0; - - /* 6. apply decorators */ - for (i = 0; i < asdl_seq_LEN(decos); i++) { - ADDOP_I(c, CALL_FUNCTION, 1); + PyCodeObject *co; + PyObject *str; + int i; + asdl_seq* decos = s->v.ClassDef.decorator_list; + + if (!compiler_decorators(c, decos)) + return 0; + + /* ultimately generate code for: + = __build_class__(, , *, **) + where: + is a function/closure created from the class body; + it has a single argument (__locals__) where the dict + (or MutableSequence) representing the locals is passed + is the class name + is the positional arguments and *varargs argument + is the keyword arguments and **kwds argument + This borrows from compiler_call. + */ + + /* 1. compile the class body into a code object */ + if (!compiler_enter_scope(c, s->v.ClassDef.name, (void *)s, s->lineno)) + return 0; + /* this block represents what we do in the new scope */ + { + /* use the class name for name mangling */ + Py_INCREF(s->v.ClassDef.name); + Py_XDECREF(c->u->u_private); + c->u->u_private = s->v.ClassDef.name; + /* force it to have one mandatory argument */ + c->u->u_argcount = 1; + /* load the first argument (__locals__) ... */ + ADDOP_I(c, LOAD_FAST, 0); + /* ... and store it into f_locals */ + ADDOP_IN_SCOPE(c, STORE_LOCALS); + /* load (global) __name__ ... */ + str = PyUnicode_InternFromString("__name__"); + if (!str || !compiler_nameop(c, str, Load)) { + Py_XDECREF(str); + compiler_exit_scope(c); + return 0; + } + Py_DECREF(str); + /* ... and store it as __module__ */ + str = PyUnicode_InternFromString("__module__"); + if (!str || !compiler_nameop(c, str, Store)) { + Py_XDECREF(str); + compiler_exit_scope(c); + return 0; + } + Py_DECREF(str); + /* compile the body proper */ + if (!compiler_body(c, s->v.ClassDef.body)) { + compiler_exit_scope(c); + return 0; + } + /* return the (empty) __class__ cell */ + str = PyUnicode_InternFromString("__class__"); + if (str == NULL) { + compiler_exit_scope(c); + return 0; + } + i = compiler_lookup_arg(c->u->u_cellvars, str); + Py_DECREF(str); + if (i == -1) { + /* This happens when nobody references the cell */ + PyErr_Clear(); + /* Return None */ + ADDOP_O(c, LOAD_CONST, Py_None, consts); + } + else { + /* Return the cell where to store __class__ */ + ADDOP_I(c, LOAD_CLOSURE, i); } + ADDOP_IN_SCOPE(c, RETURN_VALUE); + /* create the code object */ + co = assemble(c, 1); + } + /* leave the new scope */ + compiler_exit_scope(c); + if (co == NULL) + return 0; + + /* 2. load the 'build_class' function */ + ADDOP(c, LOAD_BUILD_CLASS); + + /* 3. load a function (or closure) made from the code object */ + compiler_make_closure(c, co, 0); + Py_DECREF(co); + + /* 4. load class name */ + ADDOP_O(c, LOAD_CONST, s->v.ClassDef.name, consts); + + /* 5. generate the rest of the code for the call */ + if (!compiler_call_helper(c, 2, + s->v.ClassDef.bases, + s->v.ClassDef.keywords, + s->v.ClassDef.starargs, + s->v.ClassDef.kwargs)) + return 0; + + /* 6. apply decorators */ + for (i = 0; i < asdl_seq_LEN(decos); i++) { + ADDOP_I(c, CALL_FUNCTION, 1); + } - /* 7. store into */ - if (!compiler_nameop(c, s->v.ClassDef.name, Store)) - return 0; - return 1; + /* 7. store into */ + 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_JABS(c, POP_JUMP_IF_FALSE, next); - VISIT(c, expr, e->v.IfExp.body); - ADDOP_JREL(c, JUMP_FORWARD, end); - compiler_use_next_block(c, next); - VISIT(c, expr, e->v.IfExp.orelse); - compiler_use_next_block(c, end); - return 1; + 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_JABS(c, POP_JUMP_IF_FALSE, next); + VISIT(c, expr, e->v.IfExp.body); + ADDOP_JREL(c, JUMP_FORWARD, end); + compiler_use_next_block(c, next); + 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; - int kw_default_count = 0, arglength; - arguments_ty args = e->v.Lambda.args; - assert(e->kind == Lambda_kind); - - if (!name) { - name = PyUnicode_InternFromString(""); - if (!name) - return 0; - } - - if (args->kwonlyargs) { - int res = compiler_visit_kwonlydefaults(c, args->kwonlyargs, - args->kw_defaults); - if (res < 0) return 0; - kw_default_count = res; - } - if (args->defaults) - VISIT_SEQ(c, expr, args->defaults); - if (!compiler_enter_scope(c, name, (void *)e, e->lineno)) - return 0; - - /* Make None the first constant, so the lambda can't have a - docstring. */ - if (compiler_add_o(c, c->u->u_consts, Py_None) < 0) - return 0; - - c->u->u_argcount = asdl_seq_LEN(args->args); - c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs); - VISIT_IN_SCOPE(c, expr, e->v.Lambda.body); - if (c->u->u_ste->ste_generator) { - ADDOP_IN_SCOPE(c, POP_TOP); - } - else { - ADDOP_IN_SCOPE(c, RETURN_VALUE); - } - co = assemble(c, 1); - compiler_exit_scope(c); - if (co == NULL) - return 0; - - arglength = asdl_seq_LEN(args->defaults); - arglength |= kw_default_count << 8; - compiler_make_closure(c, co, arglength); - Py_DECREF(co); - - return 1; + PyCodeObject *co; + static identifier name; + int kw_default_count = 0, arglength; + arguments_ty args = e->v.Lambda.args; + assert(e->kind == Lambda_kind); + + if (!name) { + name = PyUnicode_InternFromString(""); + if (!name) + return 0; + } + + if (args->kwonlyargs) { + int res = compiler_visit_kwonlydefaults(c, args->kwonlyargs, + args->kw_defaults); + if (res < 0) return 0; + kw_default_count = res; + } + if (args->defaults) + VISIT_SEQ(c, expr, args->defaults); + if (!compiler_enter_scope(c, name, (void *)e, e->lineno)) + return 0; + + /* Make None the first constant, so the lambda can't have a + docstring. */ + if (compiler_add_o(c, c->u->u_consts, Py_None) < 0) + return 0; + + c->u->u_argcount = asdl_seq_LEN(args->args); + c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs); + VISIT_IN_SCOPE(c, expr, e->v.Lambda.body); + if (c->u->u_ste->ste_generator) { + ADDOP_IN_SCOPE(c, POP_TOP); + } + else { + ADDOP_IN_SCOPE(c, RETURN_VALUE); + } + co = assemble(c, 1); + compiler_exit_scope(c); + if (co == NULL) + return 0; + + arglength = asdl_seq_LEN(args->defaults); + arglength |= kw_default_count << 8; + compiler_make_closure(c, co, arglength); + Py_DECREF(co); + + 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; - - 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 { - if (s->v.If.orelse) { - next = compiler_new_block(c); - if (next == NULL) - return 0; - } - else - next = end; - VISIT(c, expr, s->v.If.test); - ADDOP_JABS(c, POP_JUMP_IF_FALSE, next); - VISIT_SEQ(c, stmt, s->v.If.body); - ADDOP_JREL(c, JUMP_FORWARD, end); - if (s->v.If.orelse) { - compiler_use_next_block(c, next); - VISIT_SEQ(c, stmt, s->v.If.orelse); - } - } - compiler_use_next_block(c, end); - return 1; + basicblock *end, *next; + int constant; + assert(s->kind == If_kind); + end = compiler_new_block(c); + if (end == 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 { + if (s->v.If.orelse) { + next = compiler_new_block(c); + if (next == NULL) + return 0; + } + else + next = end; + VISIT(c, expr, s->v.If.test); + ADDOP_JABS(c, POP_JUMP_IF_FALSE, next); + VISIT_SEQ(c, stmt, s->v.If.body); + ADDOP_JREL(c, JUMP_FORWARD, end); + if (s->v.If.orelse) { + compiler_use_next_block(c, next); + 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); - 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; + 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); + 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) { - if (s->v.While.orelse) - VISIT_SEQ(c, stmt, s->v.While.orelse); - 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_JABS(c, POP_JUMP_IF_FALSE, anchor); - } - 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_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; + basicblock *loop, *orelse, *end, *anchor = NULL; + int constant = expr_constant(s->v.While.test); + + if (constant == 0) { + if (s->v.While.orelse) + VISIT_SEQ(c, stmt, s->v.While.orelse); + 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_JABS(c, POP_JUMP_IF_FALSE, anchor); + } + 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_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 continue anywhere under a finally - even if hidden in a sub-try or except. */ - 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; + 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 continue anywhere under a finally + even if hidden in a sub-try or except. */ + 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: finally: " is as follows: - - SETUP_FINALLY L - - POP_BLOCK - LOAD_CONST - L: - END_FINALLY - + + SETUP_FINALLY L + + POP_BLOCK + LOAD_CONST + L: + 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. + 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.) + 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. - + 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), @@ -1880,29 +1880,29 @@ compiler_continue(struct compiler *c) 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); + 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); + 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; + return 1; } /* @@ -1910,864 +1910,864 @@ compiler_try_finally(struct compiler *c, stmt_ty s) (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 - [] - [] POP_BLOCK - [] JUMP_FORWARD L0 - - [tb, val, exc] L1: DUP ) - [tb, val, exc, exc] ) - [tb, val, exc, exc, E1] COMPARE_OP EXC_MATCH ) only if E1 - [tb, val, exc, 1-or-0] POP_JUMP_IF_FALSE L2 ) - [tb, val, exc] POP - [tb, val] (or POP if no V1) - [tb] POP - [] - JUMP_FORWARD L0 - - [tb, val, exc] L2: DUP + + Value stack Label Instruction Argument + [] SETUP_EXCEPT L1 + [] + [] POP_BLOCK + [] JUMP_FORWARD L0 + + [tb, val, exc] L1: DUP ) + [tb, val, exc, exc] ) + [tb, val, exc, exc, E1] COMPARE_OP EXC_MATCH ) only if E1 + [tb, val, exc, 1-or-0] POP_JUMP_IF_FALSE L2 ) + [tb, val, exc] POP + [tb, val] (or POP if no V1) + [tb] POP + [] + JUMP_FORWARD L0 + + [tb, val, exc] L2: DUP .............................etc....................... - [tb, val, exc] Ln+1: END_FINALLY # re-raise exception - - [] L0: - + [tb, val, exc] Ln+1: END_FINALLY # re-raise exception + + [] L0: + 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->v.ExceptHandler.type && i < n-1) - return compiler_error(c, "default 'except:' must be last"); - c->u->u_lineno_set = 0; - c->u->u_lineno = handler->lineno; - except = compiler_new_block(c); - if (except == NULL) - return 0; - if (handler->v.ExceptHandler.type) { - ADDOP(c, DUP_TOP); - VISIT(c, expr, handler->v.ExceptHandler.type); - ADDOP_I(c, COMPARE_OP, PyCmp_EXC_MATCH); - ADDOP_JABS(c, POP_JUMP_IF_FALSE, except); - } - ADDOP(c, POP_TOP); - if (handler->v.ExceptHandler.name) { - basicblock *cleanup_end, *cleanup_body; - - cleanup_end = compiler_new_block(c); - cleanup_body = compiler_new_block(c); - if(!(cleanup_end || cleanup_body)) - return 0; - - compiler_nameop(c, handler->v.ExceptHandler.name, Store); - ADDOP(c, POP_TOP); + 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->v.ExceptHandler.type && i < n-1) + return compiler_error(c, "default 'except:' must be last"); + c->u->u_lineno_set = 0; + c->u->u_lineno = handler->lineno; + except = compiler_new_block(c); + if (except == NULL) + return 0; + if (handler->v.ExceptHandler.type) { + ADDOP(c, DUP_TOP); + VISIT(c, expr, handler->v.ExceptHandler.type); + ADDOP_I(c, COMPARE_OP, PyCmp_EXC_MATCH); + ADDOP_JABS(c, POP_JUMP_IF_FALSE, except); + } + ADDOP(c, POP_TOP); + if (handler->v.ExceptHandler.name) { + basicblock *cleanup_end, *cleanup_body; - /* - try: - # body - except type as name: - try: - # body - finally: - name = None - del name - */ - - /* second try: */ - ADDOP_JREL(c, SETUP_FINALLY, cleanup_end); - compiler_use_next_block(c, cleanup_body); - if (!compiler_push_fblock(c, FINALLY_TRY, cleanup_body)) - return 0; - - /* second # body */ - VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); - ADDOP(c, POP_BLOCK); - ADDOP(c, POP_EXCEPT); - compiler_pop_fblock(c, FINALLY_TRY, cleanup_body); - - /* finally: */ - ADDOP_O(c, LOAD_CONST, Py_None, consts); - compiler_use_next_block(c, cleanup_end); - if (!compiler_push_fblock(c, FINALLY_END, cleanup_end)) - return 0; - - /* name = None */ - ADDOP_O(c, LOAD_CONST, Py_None, consts); - compiler_nameop(c, handler->v.ExceptHandler.name, Store); + cleanup_end = compiler_new_block(c); + cleanup_body = compiler_new_block(c); + if(!(cleanup_end || cleanup_body)) + return 0; - /* del name */ - compiler_nameop(c, handler->v.ExceptHandler.name, Del); + compiler_nameop(c, handler->v.ExceptHandler.name, Store); + ADDOP(c, POP_TOP); - ADDOP(c, END_FINALLY); - compiler_pop_fblock(c, FINALLY_END, cleanup_end); - } - else { - basicblock *cleanup_body; + /* + try: + # body + except type as name: + try: + # body + finally: + name = None + del name + */ + + /* second try: */ + ADDOP_JREL(c, SETUP_FINALLY, cleanup_end); + compiler_use_next_block(c, cleanup_body); + if (!compiler_push_fblock(c, FINALLY_TRY, cleanup_body)) + return 0; + + /* second # body */ + VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); + ADDOP(c, POP_BLOCK); + ADDOP(c, POP_EXCEPT); + compiler_pop_fblock(c, FINALLY_TRY, cleanup_body); + + /* finally: */ + ADDOP_O(c, LOAD_CONST, Py_None, consts); + compiler_use_next_block(c, cleanup_end); + if (!compiler_push_fblock(c, FINALLY_END, cleanup_end)) + return 0; + + /* name = None */ + ADDOP_O(c, LOAD_CONST, Py_None, consts); + compiler_nameop(c, handler->v.ExceptHandler.name, Store); + + /* del name */ + compiler_nameop(c, handler->v.ExceptHandler.name, Del); + + ADDOP(c, END_FINALLY); + compiler_pop_fblock(c, FINALLY_END, cleanup_end); + } + else { + basicblock *cleanup_body; - cleanup_body = compiler_new_block(c); - if(!cleanup_body) - return 0; + cleanup_body = compiler_new_block(c); + if(!cleanup_body) + return 0; - ADDOP(c, POP_TOP); ADDOP(c, POP_TOP); - compiler_use_next_block(c, cleanup_body); - if (!compiler_push_fblock(c, FINALLY_TRY, cleanup_body)) - return 0; - VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); - ADDOP(c, POP_EXCEPT); - compiler_pop_fblock(c, FINALLY_TRY, cleanup_body); - } - ADDOP_JREL(c, JUMP_FORWARD, end); - compiler_use_next_block(c, except); - } - 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; + ADDOP(c, POP_TOP); + compiler_use_next_block(c, cleanup_body); + if (!compiler_push_fblock(c, FINALLY_TRY, cleanup_body)) + return 0; + VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); + ADDOP(c, POP_EXCEPT); + compiler_pop_fblock(c, FINALLY_TRY, cleanup_body); + } + ADDOP_JREL(c, JUMP_FORWARD, end); + compiler_use_next_block(c, except); + } + 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 Py_UNICODE *src = PyUnicode_AS_UNICODE(name); - const Py_UNICODE *dot = Py_UNICODE_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 = Py_UNICODE_strchr(src, '.'); - attr = PyUnicode_FromUnicode(src, - dot ? dot - src : Py_UNICODE_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); + /* 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 Py_UNICODE *src = PyUnicode_AS_UNICODE(name); + const Py_UNICODE *dot = Py_UNICODE_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 = Py_UNICODE_strchr(src, '.'); + attr = PyUnicode_FromUnicode(src, + dot ? dot - src : Py_UNICODE_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; - - level = PyLong_FromLong(0); - 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 Py_UNICODE *base = PyUnicode_AS_UNICODE(alias->name); - Py_UNICODE *dot = Py_UNICODE_strchr(base, '.'); - if (dot) - tmp = PyUnicode_FromUnicode(base, - dot - base); - r = compiler_nameop(c, tmp, Store); - if (dot) { - Py_DECREF(tmp); - } - if (!r) - return r; - } - } - return 1; + /* 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; + + level = PyLong_FromLong(0); + 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 Py_UNICODE *base = PyUnicode_AS_UNICODE(alias->name); + Py_UNICODE *dot = Py_UNICODE_strchr(base, '.'); + if (dot) + tmp = PyUnicode_FromUnicode(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; - static PyObject *empty_string; - - if (!empty_string) { - empty_string = PyUnicode_FromString(""); - if (!empty_string) - return 0; - } - - if (!names) - return 0; - - level = PyLong_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 && s->v.ImportFrom.module && - !PyUnicode_CompareWithASCIIString(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); - if (s->v.ImportFrom.module) { - ADDOP_NAME(c, IMPORT_NAME, s->v.ImportFrom.module, names); - } - else { - ADDOP_NAME(c, IMPORT_NAME, empty_string, 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 && *PyUnicode_AS_UNICODE(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; + int i, n = asdl_seq_LEN(s->v.ImportFrom.names); + + PyObject *names = PyTuple_New(n); + PyObject *level; + static PyObject *empty_string; + + if (!empty_string) { + empty_string = PyUnicode_FromString(""); + if (!empty_string) + return 0; + } + + if (!names) + return 0; + + level = PyLong_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 && s->v.ImportFrom.module && + !PyUnicode_CompareWithASCIIString(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); + if (s->v.ImportFrom.module) { + ADDOP_NAME(c, IMPORT_NAME, s->v.ImportFrom.module, names); + } + else { + ADDOP_NAME(c, IMPORT_NAME, empty_string, 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 && *PyUnicode_AS_UNICODE(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 = PyUnicode_InternFromString("AssertionError"); - if (assertion_error == NULL) - return 0; - } - if (s->v.Assert.test->kind == Tuple_kind && - asdl_seq_LEN(s->v.Assert.test->v.Tuple.elts) > 0) { - const char* msg = - "assertion is always true, perhaps remove parentheses?"; - if (PyErr_WarnExplicit(PyExc_SyntaxWarning, msg, c->c_filename, - c->u->u_lineno, NULL, NULL) == -1) - return 0; - } - VISIT(c, expr, s->v.Assert.test); - end = compiler_new_block(c); - if (end == NULL) - return 0; - ADDOP_JABS(c, POP_JUMP_IF_TRUE, end); - ADDOP_O(c, LOAD_GLOBAL, assertion_error, names); - if (s->v.Assert.msg) { - VISIT(c, expr, s->v.Assert.msg); - ADDOP_I(c, CALL_FUNCTION, 1); - } - ADDOP_I(c, RAISE_VARARGS, 1); - compiler_use_next_block(c, end); - return 1; + static PyObject *assertion_error = NULL; + basicblock *end; + + if (Py_OptimizeFlag) + return 1; + if (assertion_error == NULL) { + assertion_error = PyUnicode_InternFromString("AssertionError"); + if (assertion_error == NULL) + return 0; + } + if (s->v.Assert.test->kind == Tuple_kind && + asdl_seq_LEN(s->v.Assert.test->v.Tuple.elts) > 0) { + const char* msg = + "assertion is always true, perhaps remove parentheses?"; + if (PyErr_WarnExplicit(PyExc_SyntaxWarning, msg, c->c_filename, + c->u->u_lineno, NULL, NULL) == -1) + return 0; + } + VISIT(c, expr, s->v.Assert.test); + end = compiler_new_block(c); + if (end == NULL) + return 0; + ADDOP_JABS(c, POP_JUMP_IF_TRUE, end); + ADDOP_O(c, LOAD_GLOBAL, assertion_error, names); + if (s->v.Assert.msg) { + VISIT(c, expr, s->v.Assert.msg); + ADDOP_I(c, CALL_FUNCTION, 1); + } + ADDOP_I(c, RAISE_VARARGS, 1); + compiler_use_next_block(c, end); + 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 = 0; - - 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 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.exc) { - VISIT(c, expr, s->v.Raise.exc); - n++; - if (s->v.Raise.cause) { - VISIT(c, expr, s->v.Raise.cause); - 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 Global_kind: - case Nonlocal_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; + 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 = 0; + + 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 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.exc) { + VISIT(c, expr, s->v.Raise.exc); + n++; + if (s->v.Raise.cause) { + VISIT(c, expr, s->v.Raise.cause); + 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 Global_kind: + case Nonlocal_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; - default: - PyErr_Format(PyExc_SystemError, - "unary op %d should not be possible", op); - return 0; - } + switch (op) { + case Invert: + return UNARY_INVERT; + case Not: + return UNARY_NOT; + case UAdd: + return UNARY_POSITIVE; + case USub: + return UNARY_NEGATIVE; + default: + PyErr_Format(PyExc_SystemError, + "unary op %d should not be possible", op); + 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: - return BINARY_TRUE_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; - default: - PyErr_Format(PyExc_SystemError, - "binary op %d should not be possible", op); - return 0; - } + switch (op) { + case Add: + return BINARY_ADD; + case Sub: + return BINARY_SUBTRACT; + case Mult: + return BINARY_MULTIPLY; + case Div: + return BINARY_TRUE_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; + default: + PyErr_Format(PyExc_SystemError, + "binary op %d should not be possible", op); + 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; - default: - return PyCmp_BAD; - } + 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; + default: + 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: - return INPLACE_TRUE_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; - default: - PyErr_Format(PyExc_SystemError, - "inplace binary op %d should not be possible", op); - return 0; - } + switch (op) { + case Add: + return INPLACE_ADD; + case Sub: + return INPLACE_SUBTRACT; + case Mult: + return INPLACE_MULTIPLY; + case Div: + return INPLACE_TRUE_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; + default: + 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! */ - - 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 || PyUnicode_AS_UNICODE(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", - 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); + 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! */ + + 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 || PyUnicode_AS_UNICODE(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", + 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_OR_POP; - else - jumpi = JUMP_IF_TRUE_OR_POP; - 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_JABS(c, jumpi, end); - } - VISIT(c, expr, (expr_ty)asdl_seq_GET(s, n)); - compiler_use_next_block(c, end); - return 1; + basicblock *end; + int jumpi, i, n; + asdl_seq *s; + + assert(e->kind == BoolOp_kind); + if (e->v.BoolOp.op == And) + jumpi = JUMP_IF_FALSE_OR_POP; + else + jumpi = JUMP_IF_TRUE_OR_POP; + 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_JABS(c, jumpi, end); + } + 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) { - int i, seen_star = 0; - for (i = 0; i < n; i++) { - expr_ty elt = asdl_seq_GET(e->v.List.elts, i); - if (elt->kind == Starred_kind && !seen_star) { - if ((i >= (1 << 8)) || - (n-i-1 >= (INT_MAX >> 8))) - return compiler_error(c, - "too many expressions in " - "star-unpacking assignment"); - ADDOP_I(c, UNPACK_EX, (i + ((n-i-1) << 8))); - seen_star = 1; - asdl_seq_SET(e->v.List.elts, i, elt->v.Starred.value); - } else if (elt->kind == Starred_kind) { - return compiler_error(c, - "two starred expressions in assignment"); - } - } - if (!seen_star) { - 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; + int n = asdl_seq_LEN(e->v.List.elts); + if (e->v.List.ctx == Store) { + int i, seen_star = 0; + for (i = 0; i < n; i++) { + expr_ty elt = asdl_seq_GET(e->v.List.elts, i); + if (elt->kind == Starred_kind && !seen_star) { + if ((i >= (1 << 8)) || + (n-i-1 >= (INT_MAX >> 8))) + return compiler_error(c, + "too many expressions in " + "star-unpacking assignment"); + ADDOP_I(c, UNPACK_EX, (i + ((n-i-1) << 8))); + seen_star = 1; + asdl_seq_SET(e->v.List.elts, i, elt->v.Starred.value); + } else if (elt->kind == Starred_kind) { + return compiler_error(c, + "two starred expressions in assignment"); + } + } + if (!seen_star) { + 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) { - int i, seen_star = 0; - for (i = 0; i < n; i++) { - expr_ty elt = asdl_seq_GET(e->v.Tuple.elts, i); - if (elt->kind == Starred_kind && !seen_star) { - if ((i >= (1 << 8)) || - (n-i-1 >= (INT_MAX >> 8))) - return compiler_error(c, - "too many expressions in " - "star-unpacking assignment"); - ADDOP_I(c, UNPACK_EX, (i + ((n-i-1) << 8))); - seen_star = 1; - asdl_seq_SET(e->v.Tuple.elts, i, elt->v.Starred.value); - } else if (elt->kind == Starred_kind) { - return compiler_error(c, - "two starred expressions in assignment"); - } - } - if (!seen_star) { - 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; + int n = asdl_seq_LEN(e->v.Tuple.elts); + if (e->v.Tuple.ctx == Store) { + int i, seen_star = 0; + for (i = 0; i < n; i++) { + expr_ty elt = asdl_seq_GET(e->v.Tuple.elts, i); + if (elt->kind == Starred_kind && !seen_star) { + if ((i >= (1 << 8)) || + (n-i-1 >= (INT_MAX >> 8))) + return compiler_error(c, + "too many expressions in " + "star-unpacking assignment"); + ADDOP_I(c, UNPACK_EX, (i + ((n-i-1) << 8))); + seen_star = 1; + asdl_seq_SET(e->v.Tuple.elts, i, elt->v.Starred.value); + } else if (elt->kind == Starred_kind) { + return compiler_error(c, + "two starred expressions in assignment"); + } + } + if (!seen_star) { + 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_JABS(c, JUMP_IF_FALSE_OR_POP, cleanup); - NEXT_BLOCK(c); - 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; + 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_JABS(c, JUMP_IF_FALSE_OR_POP, cleanup); + NEXT_BLOCK(c); + 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; } static int compiler_call(struct compiler *c, expr_ty e) { - VISIT(c, expr, e->v.Call.func); - return compiler_call_helper(c, 0, - e->v.Call.args, - e->v.Call.keywords, - e->v.Call.starargs, - e->v.Call.kwargs); + VISIT(c, expr, e->v.Call.func); + return compiler_call_helper(c, 0, + e->v.Call.args, + e->v.Call.keywords, + e->v.Call.starargs, + e->v.Call.kwargs); } /* shared code between compiler_call and compiler_class */ static int compiler_call_helper(struct compiler *c, - int n, /* Args already pushed */ - asdl_seq *args, - asdl_seq *keywords, - expr_ty starargs, - expr_ty kwargs) -{ - int code = 0; - - n += asdl_seq_LEN(args); - VISIT_SEQ(c, expr, args); - if (keywords) { - VISIT_SEQ(c, keyword, keywords); - n |= asdl_seq_LEN(keywords) << 8; - } - if (starargs) { - VISIT(c, expr, starargs); - code |= 1; - } - if (kwargs) { - VISIT(c, expr, 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; + int n, /* Args already pushed */ + asdl_seq *args, + asdl_seq *keywords, + expr_ty starargs, + expr_ty kwargs) +{ + int code = 0; + + n += asdl_seq_LEN(args); + VISIT_SEQ(c, expr, args); + if (keywords) { + VISIT_SEQ(c, keyword, keywords); + n |= asdl_seq_LEN(keywords) << 8; + } + if (starargs) { + VISIT(c, expr, starargs); + code |= 1; + } + if (kwargs) { + VISIT(c, expr, 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; } @@ -2787,228 +2787,228 @@ compiler_call_helper(struct compiler *c, */ static int -compiler_comprehension_generator(struct compiler *c, - asdl_seq *generators, int gen_index, - expr_ty elt, expr_ty val, int type) -{ - /* generate code for the iterator, then each of the ifs, - and then write to the element */ - - comprehension_ty gen; - 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; - - gen = (comprehension_ty)asdl_seq_GET(generators, gen_index); - - 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, gen->iter); - ADDOP(c, GET_ITER); - } - compiler_use_next_block(c, start); - ADDOP_JREL(c, FOR_ITER, anchor); - NEXT_BLOCK(c); - VISIT(c, expr, gen->target); - - /* XXX this needs to be cleaned up...a lot! */ - n = asdl_seq_LEN(gen->ifs); - for (i = 0; i < n; i++) { - expr_ty e = (expr_ty)asdl_seq_GET(gen->ifs, i); - VISIT(c, expr, e); - ADDOP_JABS(c, POP_JUMP_IF_FALSE, if_cleanup); - NEXT_BLOCK(c); - } - - if (++gen_index < asdl_seq_LEN(generators)) - if (!compiler_comprehension_generator(c, - generators, gen_index, - elt, val, type)) - return 0; - - /* only append after the last for generator */ - if (gen_index >= asdl_seq_LEN(generators)) { - /* comprehension specific code */ - switch (type) { - case COMP_GENEXP: - VISIT(c, expr, elt); - ADDOP(c, YIELD_VALUE); - ADDOP(c, POP_TOP); - break; - case COMP_LISTCOMP: - VISIT(c, expr, elt); - ADDOP_I(c, LIST_APPEND, gen_index + 1); - break; - case COMP_SETCOMP: - VISIT(c, expr, elt); - ADDOP_I(c, SET_ADD, gen_index + 1); - break; - case COMP_DICTCOMP: - /* With 'd[k] = v', v is evaluated before k, so we do - the same. */ - VISIT(c, expr, val); - VISIT(c, expr, elt); - ADDOP_I(c, MAP_ADD, gen_index + 1); - break; - default: - return 0; - } - - compiler_use_next_block(c, skip); - } - compiler_use_next_block(c, if_cleanup); - ADDOP_JABS(c, JUMP_ABSOLUTE, start); - compiler_use_next_block(c, anchor); - - return 1; +compiler_comprehension_generator(struct compiler *c, + asdl_seq *generators, int gen_index, + expr_ty elt, expr_ty val, int type) +{ + /* generate code for the iterator, then each of the ifs, + and then write to the element */ + + comprehension_ty gen; + 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; + + gen = (comprehension_ty)asdl_seq_GET(generators, gen_index); + + 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, gen->iter); + ADDOP(c, GET_ITER); + } + compiler_use_next_block(c, start); + ADDOP_JREL(c, FOR_ITER, anchor); + NEXT_BLOCK(c); + VISIT(c, expr, gen->target); + + /* XXX this needs to be cleaned up...a lot! */ + n = asdl_seq_LEN(gen->ifs); + for (i = 0; i < n; i++) { + expr_ty e = (expr_ty)asdl_seq_GET(gen->ifs, i); + VISIT(c, expr, e); + ADDOP_JABS(c, POP_JUMP_IF_FALSE, if_cleanup); + NEXT_BLOCK(c); + } + + if (++gen_index < asdl_seq_LEN(generators)) + if (!compiler_comprehension_generator(c, + generators, gen_index, + elt, val, type)) + return 0; + + /* only append after the last for generator */ + if (gen_index >= asdl_seq_LEN(generators)) { + /* comprehension specific code */ + switch (type) { + case COMP_GENEXP: + VISIT(c, expr, elt); + ADDOP(c, YIELD_VALUE); + ADDOP(c, POP_TOP); + break; + case COMP_LISTCOMP: + VISIT(c, expr, elt); + ADDOP_I(c, LIST_APPEND, gen_index + 1); + break; + case COMP_SETCOMP: + VISIT(c, expr, elt); + ADDOP_I(c, SET_ADD, gen_index + 1); + break; + case COMP_DICTCOMP: + /* With 'd[k] = v', v is evaluated before k, so we do + the same. */ + VISIT(c, expr, val); + VISIT(c, expr, elt); + ADDOP_I(c, MAP_ADD, gen_index + 1); + break; + default: + return 0; + } + + compiler_use_next_block(c, skip); + } + compiler_use_next_block(c, if_cleanup); + ADDOP_JABS(c, JUMP_ABSOLUTE, start); + compiler_use_next_block(c, anchor); + + return 1; } static int compiler_comprehension(struct compiler *c, expr_ty e, int type, identifier name, - asdl_seq *generators, expr_ty elt, expr_ty val) -{ - PyCodeObject *co = NULL; - expr_ty outermost_iter; - - outermost_iter = ((comprehension_ty) - asdl_seq_GET(generators, 0))->iter; - - if (!compiler_enter_scope(c, name, (void *)e, e->lineno)) - goto error; - - if (type != COMP_GENEXP) { - int op; - switch (type) { - case COMP_LISTCOMP: - op = BUILD_LIST; - break; - case COMP_SETCOMP: - op = BUILD_SET; - break; - case COMP_DICTCOMP: - op = BUILD_MAP; - break; - default: - PyErr_Format(PyExc_SystemError, - "unknown comprehension type %d", type); - goto error_in_scope; - } - - ADDOP_I(c, op, 0); - } - - if (!compiler_comprehension_generator(c, generators, 0, elt, - val, type)) - goto error_in_scope; - - if (type != COMP_GENEXP) { - ADDOP(c, RETURN_VALUE); - } - - co = assemble(c, 1); - compiler_exit_scope(c); - if (co == NULL) - goto error; - - if (!compiler_make_closure(c, co, 0)) - goto error; - Py_DECREF(co); - - VISIT(c, expr, outermost_iter); - ADDOP(c, GET_ITER); - ADDOP_I(c, CALL_FUNCTION, 1); - return 1; + asdl_seq *generators, expr_ty elt, expr_ty val) +{ + PyCodeObject *co = NULL; + expr_ty outermost_iter; + + outermost_iter = ((comprehension_ty) + asdl_seq_GET(generators, 0))->iter; + + if (!compiler_enter_scope(c, name, (void *)e, e->lineno)) + goto error; + + if (type != COMP_GENEXP) { + int op; + switch (type) { + case COMP_LISTCOMP: + op = BUILD_LIST; + break; + case COMP_SETCOMP: + op = BUILD_SET; + break; + case COMP_DICTCOMP: + op = BUILD_MAP; + break; + default: + PyErr_Format(PyExc_SystemError, + "unknown comprehension type %d", type); + goto error_in_scope; + } + + ADDOP_I(c, op, 0); + } + + if (!compiler_comprehension_generator(c, generators, 0, elt, + val, type)) + goto error_in_scope; + + if (type != COMP_GENEXP) { + ADDOP(c, RETURN_VALUE); + } + + co = assemble(c, 1); + compiler_exit_scope(c); + if (co == NULL) + goto error; + + if (!compiler_make_closure(c, co, 0)) + goto error; + Py_DECREF(co); + + VISIT(c, expr, outermost_iter); + ADDOP(c, GET_ITER); + ADDOP_I(c, CALL_FUNCTION, 1); + return 1; error_in_scope: - compiler_exit_scope(c); + compiler_exit_scope(c); error: - Py_XDECREF(co); - return 0; + Py_XDECREF(co); + return 0; } static int compiler_genexp(struct compiler *c, expr_ty e) { - static identifier name; - if (!name) { - name = PyUnicode_FromString(""); - if (!name) - return 0; - } - assert(e->kind == GeneratorExp_kind); - return compiler_comprehension(c, e, COMP_GENEXP, name, - e->v.GeneratorExp.generators, - e->v.GeneratorExp.elt, NULL); + static identifier name; + if (!name) { + name = PyUnicode_FromString(""); + if (!name) + return 0; + } + assert(e->kind == GeneratorExp_kind); + return compiler_comprehension(c, e, COMP_GENEXP, name, + e->v.GeneratorExp.generators, + e->v.GeneratorExp.elt, NULL); } static int compiler_listcomp(struct compiler *c, expr_ty e) { - static identifier name; - if (!name) { - name = PyUnicode_FromString(""); - if (!name) - return 0; - } - assert(e->kind == ListComp_kind); - return compiler_comprehension(c, e, COMP_LISTCOMP, name, - e->v.ListComp.generators, - e->v.ListComp.elt, NULL); + static identifier name; + if (!name) { + name = PyUnicode_FromString(""); + if (!name) + return 0; + } + assert(e->kind == ListComp_kind); + return compiler_comprehension(c, e, COMP_LISTCOMP, name, + e->v.ListComp.generators, + e->v.ListComp.elt, NULL); } static int compiler_setcomp(struct compiler *c, expr_ty e) { - static identifier name; - if (!name) { - name = PyUnicode_FromString(""); - if (!name) - return 0; - } - assert(e->kind == SetComp_kind); - return compiler_comprehension(c, e, COMP_SETCOMP, name, - e->v.SetComp.generators, - e->v.SetComp.elt, NULL); + static identifier name; + if (!name) { + name = PyUnicode_FromString(""); + if (!name) + return 0; + } + assert(e->kind == SetComp_kind); + return compiler_comprehension(c, e, COMP_SETCOMP, name, + e->v.SetComp.generators, + e->v.SetComp.elt, NULL); } static int compiler_dictcomp(struct compiler *c, expr_ty e) { - static identifier name; - if (!name) { - name = PyUnicode_FromString(""); - if (!name) - return 0; - } - assert(e->kind == DictComp_kind); - return compiler_comprehension(c, e, COMP_DICTCOMP, name, - e->v.DictComp.generators, - e->v.DictComp.key, e->v.DictComp.value); + static identifier name; + if (!name) { + name = PyUnicode_FromString(""); + if (!name) + return 0; + } + assert(e->kind == DictComp_kind); + return compiler_comprehension(c, e, COMP_DICTCOMP, name, + e->v.DictComp.generators, + e->v.DictComp.key, e->v.DictComp.value); } 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; + ADDOP_O(c, LOAD_CONST, k->arg, consts); + VISIT(c, expr, k->value); + return 1; } -/* Test whether expression is constant. For constants, report +/* 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. @@ -3017,39 +3017,39 @@ compiler_visit_keyword(struct compiler *c, keyword_ty k) static int expr_constant(expr_ty e) { - char *id; - switch (e->kind) { - case Ellipsis_kind: - return 1; - case Num_kind: - return PyObject_IsTrue(e->v.Num.n); - case Str_kind: - return PyObject_IsTrue(e->v.Str.s); - case Name_kind: - /* optimize away names that can't be reassigned */ - id = PyBytes_AS_STRING( - _PyUnicode_AsDefaultEncodedString(e->v.Name.id, NULL)); - if (strcmp(id, "True") == 0) return 1; - if (strcmp(id, "False") == 0) return 0; - if (strcmp(id, "None") == 0) return 0; - if (strcmp(id, "__debug__") == 0) - return ! Py_OptimizeFlag; - /* fall through */ - default: - return -1; - } + char *id; + switch (e->kind) { + case Ellipsis_kind: + return 1; + case Num_kind: + return PyObject_IsTrue(e->v.Num.n); + case Str_kind: + return PyObject_IsTrue(e->v.Str.s); + case Name_kind: + /* optimize away names that can't be reassigned */ + id = PyBytes_AS_STRING( + _PyUnicode_AsDefaultEncodedString(e->v.Name.id, NULL)); + if (strcmp(id, "True") == 0) return 1; + if (strcmp(id, "False") == 0) return 0; + if (strcmp(id, "None") == 0) return 0; + if (strcmp(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: + 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__() @@ -3058,9 +3058,9 @@ expr_constant(expr_ty e) BLOCK finally: if an exception was raised: - exc = copy of (exception, instance, traceback) + exc = copy of (exception, instance, traceback) else: - exc = (None, None, None) + exc = (None, None, None) exit(*exc) */ static int @@ -3073,7 +3073,7 @@ compiler_with(struct compiler *c, stmt_ty s) block = compiler_new_block(c); finally = compiler_new_block(c); if (!block || !finally) - return 0; + return 0; /* Evaluate EXPR */ VISIT(c, expr, s->v.With.context_expr); @@ -3082,15 +3082,15 @@ compiler_with(struct compiler *c, stmt_ty s) /* SETUP_WITH pushes a finally block. */ compiler_use_next_block(c, block); if (!compiler_push_fblock(c, FINALLY_TRY, block)) { - return 0; + return 0; } if (s->v.With.optional_vars) { - VISIT(c, expr, s->v.With.optional_vars); + VISIT(c, expr, s->v.With.optional_vars); } else { - /* Discard result from context.__enter__() */ - ADDOP(c, POP_TOP); + /* Discard result from context.__enter__() */ + ADDOP(c, POP_TOP); } /* BLOCK code */ @@ -3103,7 +3103,7 @@ compiler_with(struct compiler *c, stmt_ty s) ADDOP_O(c, LOAD_CONST, Py_None, consts); compiler_use_next_block(c, finally); if (!compiler_push_fblock(c, FINALLY_END, finally)) - return 0; + return 0; /* Finally block starts; context.__exit__ is on the stack under the exception or return information. Just issue our magic @@ -3119,240 +3119,240 @@ compiler_with(struct compiler *c, stmt_ty s) 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 = 0; - } - 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: - n = asdl_seq_LEN(e->v.Dict.values); - ADDOP_I(c, BUILD_MAP, (n>0xFFFF ? 0xFFFF : n)); - for (i = 0; i < n; i++) { - VISIT(c, expr, - (expr_ty)asdl_seq_GET(e->v.Dict.values, i)); - VISIT(c, expr, - (expr_ty)asdl_seq_GET(e->v.Dict.keys, i)); - ADDOP(c, STORE_MAP); - } - break; - case Set_kind: - n = asdl_seq_LEN(e->v.Set.elts); - VISIT_SEQ(c, expr, e->v.Set.elts); - ADDOP_I(c, BUILD_SET, n); - break; - case GeneratorExp_kind: - return compiler_genexp(c, e); - case ListComp_kind: - return compiler_listcomp(c, e); - case SetComp_kind: - return compiler_setcomp(c, e); - case DictComp_kind: - return compiler_dictcomp(c, e); - case Yield_kind: - if (c->u->u_ste->ste_type != FunctionBlock) - return compiler_error(c, "'yield' outside function"); - 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 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; - case Bytes_kind: - ADDOP_O(c, LOAD_CONST, e->v.Bytes.s, consts); - break; - case Ellipsis_kind: - ADDOP_O(c, LOAD_CONST, Py_Ellipsis, 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 Starred_kind: - switch (e->v.Starred.ctx) { - case Store: - /* In all legitimate cases, the Starred node was already replaced - * by compiler_list/compiler_tuple. XXX: is that okay? */ - return compiler_error(c, - "starred assignment target must be in a list or tuple"); - default: - return compiler_error(c, - "can use starred expression only as assignment target"); - } - 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; + 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 = 0; + } + 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: + n = asdl_seq_LEN(e->v.Dict.values); + ADDOP_I(c, BUILD_MAP, (n>0xFFFF ? 0xFFFF : n)); + for (i = 0; i < n; i++) { + VISIT(c, expr, + (expr_ty)asdl_seq_GET(e->v.Dict.values, i)); + VISIT(c, expr, + (expr_ty)asdl_seq_GET(e->v.Dict.keys, i)); + ADDOP(c, STORE_MAP); + } + break; + case Set_kind: + n = asdl_seq_LEN(e->v.Set.elts); + VISIT_SEQ(c, expr, e->v.Set.elts); + ADDOP_I(c, BUILD_SET, n); + break; + case GeneratorExp_kind: + return compiler_genexp(c, e); + case ListComp_kind: + return compiler_listcomp(c, e); + case SetComp_kind: + return compiler_setcomp(c, e); + case DictComp_kind: + return compiler_dictcomp(c, e); + case Yield_kind: + if (c->u->u_ste->ste_type != FunctionBlock) + return compiler_error(c, "'yield' outside function"); + 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 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; + case Bytes_kind: + ADDOP_O(c, LOAD_CONST, e->v.Bytes.s, consts); + break; + case Ellipsis_kind: + ADDOP_O(c, LOAD_CONST, Py_Ellipsis, 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 Starred_kind: + switch (e->v.Starred.ctx) { + case Store: + /* In all legitimate cases, the Starred node was already replaced + * by compiler_list/compiler_tuple. XXX: is that okay? */ + return compiler_error(c, + "starred assignment target must be in a list or tuple"); + default: + return compiler_error(c, + "can use starred expression only as assignment target"); + } + 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; + 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; + 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); + 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; + 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. @@ -3361,143 +3361,143 @@ compiler_in_loop(struct compiler *c) { 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); + 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; + 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_visit_nested_slice(struct compiler *c, slice_ty s, - expr_context_ty ctx) -{ - switch (s->kind) { - 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; + 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_visit_nested_slice(struct compiler *c, slice_ty s, + expr_context_ty ctx) +{ + switch (s->kind) { + 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 Slice_kind: - kindname = "slice"; - 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); + char * kindname = NULL; + switch (s->kind) { + case Index_kind: + kindname = "index"; + if (ctx != AugStore) { + VISIT(c, expr, s->v.Index.value); + } + break; + case Slice_kind: + kindname = "slice"; + 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); } /* End of the compiler section, beginning of the assembler section */ @@ -3509,73 +3509,73 @@ compiler_visit_slice(struct compiler *c, slice_ty s, expr_context_ty ctx) */ 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 */ + 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 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; + 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, target_depth; - 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) { - target_depth = depth; - if (instr->i_opcode == FOR_ITER) { - target_depth = depth-2; - } else if (instr->i_opcode == SETUP_FINALLY || - instr->i_opcode == SETUP_EXCEPT) { - target_depth = depth+3; - if (target_depth > maxdepth) - maxdepth = target_depth; - } - maxdepth = stackdepth_walk(c, instr->i_target, - 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); + int i, target_depth; + 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) { + target_depth = depth; + if (instr->i_opcode == FOR_ITER) { + target_depth = depth-2; + } else if (instr->i_opcode == SETUP_FINALLY || + instr->i_opcode == SETUP_EXCEPT) { + target_depth = depth+3; + if (target_depth > maxdepth) + maxdepth = target_depth; + } + maxdepth = stackdepth_walk(c, instr->i_target, + 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; + b->b_seen = 0; + return maxdepth; } /* Find the flow path that needs the largest stack. We assume that @@ -3584,49 +3584,49 @@ out: 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); + 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 = PyBytes_FromStringAndSize(NULL, DEFAULT_CODE_SIZE); - if (!a->a_bytecode) - return 0; - a->a_lnotab = PyBytes_FromStringAndSize(NULL, DEFAULT_LNOTAB_SIZE); - if (!a->a_lnotab) - return 0; - if (nblocks > PY_SIZE_MAX / sizeof(basicblock *)) { - PyErr_NoMemory(); - return 0; - } - a->a_postorder = (basicblock **)PyObject_Malloc( - sizeof(basicblock *) * nblocks); - if (!a->a_postorder) { - PyErr_NoMemory(); - return 0; - } - return 1; + memset(a, 0, sizeof(struct assembler)); + a->a_lineno = firstlineno; + a->a_bytecode = PyBytes_FromStringAndSize(NULL, DEFAULT_CODE_SIZE); + if (!a->a_bytecode) + return 0; + a->a_lnotab = PyBytes_FromStringAndSize(NULL, DEFAULT_LNOTAB_SIZE); + if (!a->a_lnotab) + return 0; + if (nblocks > PY_SIZE_MAX / sizeof(basicblock *)) { + PyErr_NoMemory(); + 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); + 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. */ @@ -3634,22 +3634,22 @@ assemble_free(struct assembler *a) static int instrsize(struct instr *instr) { - if (!instr->i_hasarg) - return 1; /* 1 byte for the opcode*/ - if (instr->i_oparg > 0xffff) - return 6; /* 1 (opcode) + 1 (EXTENDED_ARG opcode) + 2 (oparg) + 2(oparg extended) */ - return 3; /* 1 (opcode) + 2 (oparg) */ + if (!instr->i_hasarg) + return 1; /* 1 byte for the opcode*/ + if (instr->i_oparg > 0xffff) + return 6; /* 1 (opcode) + 1 (EXTENDED_ARG opcode) + 2 (oparg) + 2(oparg extended) */ + return 3; /* 1 (opcode) + 2 (oparg) */ } static int blocksize(basicblock *b) { - int i; - int size = 0; + int i; + int size = 0; - for (i = 0; i < b->b_iused; i++) - size += instrsize(&b->b_instr[i]); - return size; + for (i = 0; i < b->b_iused; i++) + size += instrsize(&b->b_instr[i]); + return size; } /* Appends a pair to the end of the line number table, a_lnotab, representing @@ -3659,94 +3659,94 @@ blocksize(basicblock *b) 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); - - if(d_bytecode == 0 && d_lineno == 0) - return 1; - - if (d_bytecode > 255) { - int j, nbytes, ncodes = d_bytecode / 255; - nbytes = a->a_lnotab_off + 2 * ncodes; - len = PyBytes_GET_SIZE(a->a_lnotab); - if (nbytes >= len) { - if ((len <= INT_MAX / 2) && (len * 2 < nbytes)) - len = nbytes; - else if (len <= INT_MAX / 2) - len *= 2; - else { - PyErr_NoMemory(); - return 0; - } - if (_PyBytes_Resize(&a->a_lnotab, len) < 0) - return 0; - } - lnotab = (unsigned char *) - PyBytes_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 = PyBytes_GET_SIZE(a->a_lnotab); - if (nbytes >= len) { - if ((len <= INT_MAX / 2) && len * 2 < nbytes) - len = nbytes; - else if (len <= INT_MAX / 2) - len *= 2; - else { - PyErr_NoMemory(); - return 0; - } - if (_PyBytes_Resize(&a->a_lnotab, len) < 0) - return 0; - } - lnotab = (unsigned char *) - PyBytes_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 = PyBytes_GET_SIZE(a->a_lnotab); - if (a->a_lnotab_off + 2 >= len) { - if (_PyBytes_Resize(&a->a_lnotab, len * 2) < 0) - return 0; - } - lnotab = (unsigned char *) - PyBytes_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; + 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); + + if(d_bytecode == 0 && d_lineno == 0) + return 1; + + if (d_bytecode > 255) { + int j, nbytes, ncodes = d_bytecode / 255; + nbytes = a->a_lnotab_off + 2 * ncodes; + len = PyBytes_GET_SIZE(a->a_lnotab); + if (nbytes >= len) { + if ((len <= INT_MAX / 2) && (len * 2 < nbytes)) + len = nbytes; + else if (len <= INT_MAX / 2) + len *= 2; + else { + PyErr_NoMemory(); + return 0; + } + if (_PyBytes_Resize(&a->a_lnotab, len) < 0) + return 0; + } + lnotab = (unsigned char *) + PyBytes_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 = PyBytes_GET_SIZE(a->a_lnotab); + if (nbytes >= len) { + if ((len <= INT_MAX / 2) && len * 2 < nbytes) + len = nbytes; + else if (len <= INT_MAX / 2) + len *= 2; + else { + PyErr_NoMemory(); + return 0; + } + if (_PyBytes_Resize(&a->a_lnotab, len) < 0) + return 0; + } + lnotab = (unsigned char *) + PyBytes_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 = PyBytes_GET_SIZE(a->a_lnotab); + if (a->a_lnotab_off + 2 >= len) { + if (_PyBytes_Resize(&a->a_lnotab, len * 2) < 0) + return 0; + } + lnotab = (unsigned char *) + PyBytes_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() @@ -3757,227 +3757,227 @@ assemble_lnotab(struct assembler *a, struct instr *i) static int assemble_emit(struct assembler *a, struct instr *i) { - int size, arg = 0, ext = 0; - Py_ssize_t len = PyBytes_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 (len > PY_SSIZE_T_MAX / 2) - return 0; - if (_PyBytes_Resize(&a->a_bytecode, len * 2) < 0) - return 0; - } - code = PyBytes_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; + int size, arg = 0, ext = 0; + Py_ssize_t len = PyBytes_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 (len > PY_SSIZE_T_MAX / 2) + return 0; + if (_PyBytes_Resize(&a->a_bytecode, len * 2) < 0) + return 0; + } + code = PyBytes_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 = 0, last_extended_arg_count; - int i; - - /* Compute the size of each block and fixup jump args. - Replace block pointer with position in bytecode. */ - do { - 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; - } - last_extended_arg_count = extended_arg_count; - 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. - - 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. - */ - } while (last_extended_arg_count != extended_arg_count); + basicblock *b; + int bsize, totsize, extended_arg_count = 0, last_extended_arg_count; + int i; + + /* Compute the size of each block and fixup jump args. + Replace block pointer with position in bytecode. */ + do { + 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; + } + last_extended_arg_count = extended_arg_count; + 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. + + 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. + */ + } while (last_extended_arg_count != extended_arg_count); } 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 = PyLong_AS_LONG(v); - /* The keys of the dictionary are tuples. (see compiler_add_o) - The object we want is always first, though. */ - 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; + 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 = PyLong_AS_LONG(v); + /* The keys of the dictionary are tuples. (see compiler_add_o) + The object we want is always first, though. */ + 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; - } - - /* (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; + 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; + } + + /* (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 = PyUnicode_DecodeFSDefault(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 = PyCode_Optimize(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, c->u->u_kwonlyargcount, - nlocals, stackdepth(c), flags, - bytecode, consts, names, varnames, - freevars, cellvars, - filename, c->u->u_name, - c->u->u_firstlineno, - a->a_lnotab); + 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 = PyUnicode_DecodeFSDefault(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 = PyCode_Optimize(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, c->u->u_kwonlyargcount, + 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; + 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; } @@ -3986,90 +3986,90 @@ makecode(struct compiler *c, struct assembler *a) 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]; + 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); + *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); + 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); - } - } + 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 (_PyBytes_Resize(&a.a_lnotab, a.a_lnotab_off) < 0) - goto error; - if (_PyBytes_Resize(&a.a_bytecode, a.a_offset) < 0) - goto error; - - co = makecode(c, &a); + 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 (_PyBytes_Resize(&a.a_lnotab, a.a_lnotab_off) < 0) + goto error; + if (_PyBytes_Resize(&a.a_bytecode, a.a_offset) < 0) + goto error; + + co = makecode(c, &a); error: - assemble_free(&a); - return co; + assemble_free(&a); + return co; } diff --git a/Python/dynload_aix.c b/Python/dynload_aix.c index 7a604f2238..8d56d7d008 100644 --- a/Python/dynload_aix.c +++ b/Python/dynload_aix.c @@ -4,10 +4,10 @@ #include "Python.h" #include "importdl.h" -#include /* for isdigit() */ -#include /* for global errno */ -#include /* for strerror() */ -#include /* for malloc(), free() */ +#include /* for isdigit() */ +#include /* for global errno */ +#include /* for strerror() */ +#include /* for malloc(), free() */ #include @@ -22,85 +22,85 @@ extern char *Py_GetProgramName(void); typedef struct Module { - struct Module *next; - void *entry; + struct Module *next; + void *entry; } Module, *ModulePtr; const struct filedescr _PyImport_DynLoadFiletab[] = { - {".so", "rb", C_EXTENSION}, - {"module.so", "rb", C_EXTENSION}, - {0, 0} + {".so", "rb", C_EXTENSION}, + {"module.so", "rb", C_EXTENSION}, + {0, 0} }; static int aix_getoldmodules(void **modlistptr) { - register ModulePtr modptr, prevmodptr; - register struct ld_info *ldiptr; - register char *ldibuf; - register int errflag, bufsize = 1024; - register unsigned int offset; - char *progname = Py_GetProgramName(); - - /* - -- Get the list of loaded modules into ld_info structures. - */ - if ((ldibuf = malloc(bufsize)) == NULL) { - PyErr_SetString(PyExc_ImportError, strerror(errno)); - return -1; - } - while ((errflag = loadquery(L_GETINFO, ldibuf, bufsize)) == -1 - && errno == ENOMEM) { - free(ldibuf); - bufsize += 1024; - if ((ldibuf = malloc(bufsize)) == NULL) { - PyErr_SetString(PyExc_ImportError, strerror(errno)); - return -1; - } - } - if (errflag == -1) { - PyErr_SetString(PyExc_ImportError, strerror(errno)); - return -1; - } - /* - -- Make the modules list from the ld_info structures. - */ - ldiptr = (struct ld_info *)ldibuf; - prevmodptr = NULL; - do { - if (strstr(progname, ldiptr->ldinfo_filename) == NULL && - strstr(ldiptr->ldinfo_filename, "python") == NULL) { - /* - -- Extract only the modules belonging to the main - -- executable + those containing "python" as a - -- substring (like the "python[version]" binary or - -- "libpython[version].a" in case it's a shared lib). - */ - offset = (unsigned int)ldiptr->ldinfo_next; - ldiptr = (struct ld_info *)((char*)ldiptr + offset); - continue; - } - if ((modptr = (ModulePtr)malloc(sizeof(Module))) == NULL) { - PyErr_SetString(PyExc_ImportError, strerror(errno)); - while (*modlistptr) { - modptr = (ModulePtr)*modlistptr; - *modlistptr = (void *)modptr->next; - free(modptr); - } - return -1; - } - modptr->entry = ldiptr->ldinfo_dataorg; - modptr->next = NULL; - if (prevmodptr == NULL) - *modlistptr = (void *)modptr; - else - prevmodptr->next = modptr; - prevmodptr = modptr; - offset = (unsigned int)ldiptr->ldinfo_next; - ldiptr = (struct ld_info *)((char*)ldiptr + offset); - } while (offset); - free(ldibuf); - return 0; + register ModulePtr modptr, prevmodptr; + register struct ld_info *ldiptr; + register char *ldibuf; + register int errflag, bufsize = 1024; + register unsigned int offset; + char *progname = Py_GetProgramName(); + + /* + -- Get the list of loaded modules into ld_info structures. + */ + if ((ldibuf = malloc(bufsize)) == NULL) { + PyErr_SetString(PyExc_ImportError, strerror(errno)); + return -1; + } + while ((errflag = loadquery(L_GETINFO, ldibuf, bufsize)) == -1 + && errno == ENOMEM) { + free(ldibuf); + bufsize += 1024; + if ((ldibuf = malloc(bufsize)) == NULL) { + PyErr_SetString(PyExc_ImportError, strerror(errno)); + return -1; + } + } + if (errflag == -1) { + PyErr_SetString(PyExc_ImportError, strerror(errno)); + return -1; + } + /* + -- Make the modules list from the ld_info structures. + */ + ldiptr = (struct ld_info *)ldibuf; + prevmodptr = NULL; + do { + if (strstr(progname, ldiptr->ldinfo_filename) == NULL && + strstr(ldiptr->ldinfo_filename, "python") == NULL) { + /* + -- Extract only the modules belonging to the main + -- executable + those containing "python" as a + -- substring (like the "python[version]" binary or + -- "libpython[version].a" in case it's a shared lib). + */ + offset = (unsigned int)ldiptr->ldinfo_next; + ldiptr = (struct ld_info *)((char*)ldiptr + offset); + continue; + } + if ((modptr = (ModulePtr)malloc(sizeof(Module))) == NULL) { + PyErr_SetString(PyExc_ImportError, strerror(errno)); + while (*modlistptr) { + modptr = (ModulePtr)*modlistptr; + *modlistptr = (void *)modptr->next; + free(modptr); + } + return -1; + } + modptr->entry = ldiptr->ldinfo_dataorg; + modptr->next = NULL; + if (prevmodptr == NULL) + *modlistptr = (void *)modptr; + else + prevmodptr->next = modptr; + prevmodptr = modptr; + offset = (unsigned int)ldiptr->ldinfo_next; + ldiptr = (struct ld_info *)((char*)ldiptr + offset); + } while (offset); + free(ldibuf); + return 0; } @@ -108,76 +108,76 @@ static void aix_loaderror(const char *pathname) { - char *message[1024], errbuf[1024]; - register int i,j; - - 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])) + 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 const struct filedescr _PyImport_DynLoadFiletab[] = { - {".so", "rb", C_EXTENSION}, - {"module.so", "rb", C_EXTENSION}, - {0, 0} + {".so", "rb", C_EXTENSION}, + {"module.so", "rb", C_EXTENSION}, + {0, 0} }; /* @@ -29,86 +29,86 @@ const struct filedescr _PyImport_DynLoadFiletab[] = { #define LINKOPTIONS NSLINKMODULE_OPTION_BINDNOW|NSLINKMODULE_OPTION_RETURN_ON_ERROR #else #define LINKOPTIONS NSLINKMODULE_OPTION_BINDNOW| \ - NSLINKMODULE_OPTION_RETURN_ON_ERROR|NSLINKMODULE_OPTION_PRIVATE + NSLINKMODULE_OPTION_RETURN_ON_ERROR|NSLINKMODULE_OPTION_PRIVATE #endif dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, - const char *pathname, FILE *fp) + const char *pathname, FILE *fp) { - dl_funcptr p = NULL; - char funcname[258]; - NSObjectFileImageReturnCode rc; - NSObjectFileImage image; - NSModule newModule; - NSSymbol theSym; - const char *errString; - char errBuf[512]; + dl_funcptr p = NULL; + char funcname[258]; + NSObjectFileImageReturnCode rc; + NSObjectFileImage image; + NSModule newModule; + NSSymbol theSym; + const char *errString; + char errBuf[512]; - PyOS_snprintf(funcname, sizeof(funcname), "_PyInit_%.200s", shortname); + PyOS_snprintf(funcname, sizeof(funcname), "_PyInit_%.200s", shortname); #ifdef USE_DYLD_GLOBAL_NAMESPACE - if (NSIsSymbolNameDefined(funcname)) { - theSym = NSLookupAndBindSymbol(funcname); - p = (dl_funcptr)NSAddressOfSymbol(theSym); - return p; - } + if (NSIsSymbolNameDefined(funcname)) { + theSym = NSLookupAndBindSymbol(funcname); + p = (dl_funcptr)NSAddressOfSymbol(theSym); + return p; + } #endif - rc = NSCreateObjectFileImageFromFile(pathname, &image); - switch(rc) { - default: - case NSObjectFileImageFailure: - case NSObjectFileImageFormat: - /* for these a message is printed on stderr by dyld */ - errString = "Can't create object file image"; - break; - case NSObjectFileImageSuccess: - errString = NULL; - break; - case NSObjectFileImageInappropriateFile: - errString = "Inappropriate file type for dynamic loading"; - break; - case NSObjectFileImageArch: - errString = "Wrong CPU type in object file"; - break; - case NSObjectFileImageAccess: - errString = "Can't read object file (no access)"; - break; - } - if (errString == NULL) { - newModule = NSLinkModule(image, pathname, LINKOPTIONS); - if (newModule == NULL) { - int errNo; - const char *fileName, *moreErrorStr; - NSLinkEditErrors c; - NSLinkEditError( &c, &errNo, &fileName, &moreErrorStr ); - PyOS_snprintf(errBuf, 512, "Failure linking new module: %s: %s", - fileName, moreErrorStr); - errString = errBuf; - } - } - if (errString != NULL) { - PyErr_SetString(PyExc_ImportError, errString); - return NULL; - } + rc = NSCreateObjectFileImageFromFile(pathname, &image); + switch(rc) { + default: + case NSObjectFileImageFailure: + case NSObjectFileImageFormat: + /* for these a message is printed on stderr by dyld */ + errString = "Can't create object file image"; + break; + case NSObjectFileImageSuccess: + errString = NULL; + break; + case NSObjectFileImageInappropriateFile: + errString = "Inappropriate file type for dynamic loading"; + break; + case NSObjectFileImageArch: + errString = "Wrong CPU type in object file"; + break; + case NSObjectFileImageAccess: + errString = "Can't read object file (no access)"; + break; + } + if (errString == NULL) { + newModule = NSLinkModule(image, pathname, LINKOPTIONS); + if (newModule == NULL) { + int errNo; + const char *fileName, *moreErrorStr; + NSLinkEditErrors c; + NSLinkEditError( &c, &errNo, &fileName, &moreErrorStr ); + PyOS_snprintf(errBuf, 512, "Failure linking new module: %s: %s", + fileName, moreErrorStr); + errString = errBuf; + } + } + if (errString != NULL) { + PyErr_SetString(PyExc_ImportError, errString); + return NULL; + } #ifdef USE_DYLD_GLOBAL_NAMESPACE - if (!NSIsSymbolNameDefined(funcname)) { - /* UnlinkModule() isn't implemented in current versions, but calling it does no harm */ - /* NSUnLinkModule(newModule, FALSE); removed: causes problems for ObjC code */ - PyErr_Format(PyExc_ImportError, - "Loaded module does not contain symbol %.200s", - funcname); - return NULL; - } - theSym = NSLookupAndBindSymbol(funcname); + if (!NSIsSymbolNameDefined(funcname)) { + /* UnlinkModule() isn't implemented in current versions, but calling it does no harm */ + /* NSUnLinkModule(newModule, FALSE); removed: causes problems for ObjC code */ + PyErr_Format(PyExc_ImportError, + "Loaded module does not contain symbol %.200s", + funcname); + return NULL; + } + theSym = NSLookupAndBindSymbol(funcname); #else - theSym = NSLookupSymbolInModule(newModule, funcname); - if ( theSym == NULL ) { - /* NSUnLinkModule(newModule, FALSE); removed: causes problems for ObjC code */ - PyErr_Format(PyExc_ImportError, - "Loaded module does not contain symbol %.200s", - funcname); - return NULL; - } + theSym = NSLookupSymbolInModule(newModule, funcname); + if ( theSym == NULL ) { + /* NSUnLinkModule(newModule, FALSE); removed: causes problems for ObjC code */ + PyErr_Format(PyExc_ImportError, + "Loaded module does not contain symbol %.200s", + funcname); + return NULL; + } #endif - p = (dl_funcptr)NSAddressOfSymbol(theSym); - return p; + p = (dl_funcptr)NSAddressOfSymbol(theSym); + return p; } diff --git a/Python/dynload_os2.c b/Python/dynload_os2.c index afa14ea5f5..101c024bbe 100644 --- a/Python/dynload_os2.c +++ b/Python/dynload_os2.c @@ -10,37 +10,37 @@ const struct filedescr _PyImport_DynLoadFiletab[] = { - {".pyd", "rb", C_EXTENSION}, - {".dll", "rb", C_EXTENSION}, - {0, 0} + {".pyd", "rb", C_EXTENSION}, + {".dll", "rb", C_EXTENSION}, + {0, 0} }; dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, - const char *pathname, FILE *fp) + const char *pathname, FILE *fp) { - dl_funcptr p; - APIRET rc; - HMODULE hDLL; - char failreason[256]; - char funcname[258]; - - 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), "PyInit_%.200s", shortname); - rc = DosQueryProcAddr(hDLL, 0L, funcname, &p); - if (rc != NO_ERROR) - p = NULL; /* Signify Failure to Acquire Entrypoint */ - return p; + 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), "PyInit_%.200s", shortname); + rc = DosQueryProcAddr(hDLL, 0L, funcname, &p); + if (rc != NO_ERROR) + p = NULL; /* Signify Failure to Acquire Entrypoint */ + return p; } diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c index ac8cd4286b..87dae27ed4 100644 --- a/Python/dynload_shlib.c +++ b/Python/dynload_shlib.c @@ -33,111 +33,111 @@ const struct filedescr _PyImport_DynLoadFiletab[] = { #ifdef __CYGWIN__ - {".dll", "rb", C_EXTENSION}, - {"module.dll", "rb", C_EXTENSION}, + {".dll", "rb", C_EXTENSION}, + {"module.dll", "rb", C_EXTENSION}, #else #if defined(PYOS_OS2) && defined(PYCC_GCC) - {".pyd", "rb", C_EXTENSION}, - {".dll", "rb", C_EXTENSION}, + {".pyd", "rb", C_EXTENSION}, + {".dll", "rb", C_EXTENSION}, #else #ifdef __VMS - {".exe", "rb", C_EXTENSION}, - {".EXE", "rb", C_EXTENSION}, - {"module.exe", "rb", C_EXTENSION}, - {"MODULE.EXE", "rb", C_EXTENSION}, + {".exe", "rb", C_EXTENSION}, + {".EXE", "rb", C_EXTENSION}, + {"module.exe", "rb", C_EXTENSION}, + {"MODULE.EXE", "rb", C_EXTENSION}, #else - {".so", "rb", C_EXTENSION}, - {"module.so", "rb", C_EXTENSION}, + {".so", "rb", C_EXTENSION}, + {"module.so", "rb", C_EXTENSION}, #endif #endif #endif - {0, 0} + {0, 0} }; static struct { - dev_t dev; + dev_t dev; #ifdef __VMS - ino_t ino[3]; + ino_t ino[3]; #else - ino_t ino; + ino_t ino; #endif - void *handle; + void *handle; } handles[128]; static int nhandles = 0; dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, - const char *pathname, FILE *fp) + const char *pathname, FILE *fp) { - dl_funcptr p; - void *handle; - char funcname[258]; - char pathbuf[260]; - int dlopenflags=0; - - if (strchr(pathname, '/') == NULL) { - /* Prefix bare filename with "./" */ - PyOS_snprintf(pathbuf, sizeof(pathbuf), "./%-.255s", pathname); - pathname = pathbuf; - } - - PyOS_snprintf(funcname, sizeof(funcname), - LEAD_UNDERSCORE "PyInit_%.200s", shortname); - - 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; + 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 "PyInit_%.200s", shortname); + + if (fp != NULL) { + int i; + struct stat statb; + fstat(fileno(fp), &statb); + for (i = 0; i < nhandles; i++) { + if (statb.st_dev == handles[i].dev && + statb.st_ino == handles[i].ino) { + p = (dl_funcptr) dlsym(handles[i].handle, + funcname); + return p; + } + } + if (nhandles < 128) { + handles[nhandles].dev = statb.st_dev; #ifdef __VMS - handles[nhandles].ino[0] = statb.st_ino[0]; - handles[nhandles].ino[1] = statb.st_ino[1]; - handles[nhandles].ino[2] = statb.st_ino[2]; + handles[nhandles].ino[0] = statb.st_ino[0]; + handles[nhandles].ino[1] = statb.st_ino[1]; + handles[nhandles].ino[2] = statb.st_ino[2]; #else - handles[nhandles].ino = statb.st_ino; + handles[nhandles].ino = statb.st_ino; #endif - } - } + } + } #if !(defined(PYOS_OS2) && defined(PYCC_GCC)) - dlopenflags = PyThreadState_GET()->interp->dlopenflags; + dlopenflags = PyThreadState_GET()->interp->dlopenflags; #endif - if (Py_VerboseFlag) - PySys_WriteStderr("dlopen(\"%s\", %x);\n", pathname, - dlopenflags); + if (Py_VerboseFlag) + PySys_WriteStderr("dlopen(\"%s\", %x);\n", pathname, + dlopenflags); #ifdef __VMS - /* VMS currently don't allow a pathname, use a logical name instead */ - /* Concatenate 'python_module_' and shortname */ - /* so "import vms.bar" will use the logical python_module_bar */ - /* As C module use only one name space this is probably not a */ - /* important limitation */ - PyOS_snprintf(pathbuf, sizeof(pathbuf), "python_module_%-.200s", - shortname); - pathname = pathbuf; + /* VMS currently don't allow a pathname, use a logical name instead */ + /* Concatenate 'python_module_' and shortname */ + /* so "import vms.bar" will use the logical python_module_bar */ + /* As C module use only one name space this is probably not a */ + /* important limitation */ + PyOS_snprintf(pathbuf, sizeof(pathbuf), "python_module_%-.200s", + shortname); + pathname = pathbuf; #endif - handle = dlopen(pathname, dlopenflags); - - 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; + 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/Python/dynload_win.c b/Python/dynload_win.c index 61c5664da4..e7d61ce8e0 100644 --- a/Python/dynload_win.c +++ b/Python/dynload_win.c @@ -17,11 +17,11 @@ void _Py_DeactivateActCtx(ULONG_PTR cookie); const struct filedescr _PyImport_DynLoadFiletab[] = { #ifdef _DEBUG - {"_d.pyd", "rb", C_EXTENSION}, + {"_d.pyd", "rb", C_EXTENSION}, #else - {".pyd", "rb", C_EXTENSION}, + {".pyd", "rb", C_EXTENSION}, #endif - {0, 0} + {0, 0} }; @@ -29,18 +29,18 @@ const struct filedescr _PyImport_DynLoadFiletab[] = { C RTL implementations */ static int strcasecmp (char *string1, char *string2) -{ - int first, second; +{ + int first, second; - do { - first = tolower(*string1); - second = tolower(*string2); - string1++; - string2++; - } while (first && first == second); + do { + first = tolower(*string1); + second = tolower(*string2); + string1++; + string2++; + } while (first && first == second); - return (first - second); -} + return (first - second); +} /* Function to return the name of the "python" DLL that the supplied module @@ -66,213 +66,213 @@ static int strcasecmp (char *string1, char *string2) static char *GetPythonImport (HINSTANCE hModule) { - unsigned char *dllbase, *import_data, *import_name; - DWORD pe_offset, opt_offset; - WORD opt_magic; - int num_dict_off, import_off; - - /* 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; + 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] != '.') { + while (*pch && pch[0] != '_' && pch[1] != 'd' && pch[2] != '.') { #else - while (*pch && *pch != '.') { + while (*pch && *pch != '.') { #endif - if (*pch >= '0' && *pch <= '9') { - pch++; - } else { - pch = NULL; - break; - } - } - - if (pch) { - /* Found it - return the name */ - return import_name; - } - } - import_data += 20; - } - } - - return NULL; + 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) + const char *pathname, FILE *fp) { - dl_funcptr p; - char funcname[258], *import_python; - - PyOS_snprintf(funcname, sizeof(funcname), "PyInit_%.200s", shortname); - - { - HINSTANCE hDLL = NULL; - char pathbuf[260]; - LPTSTR dummy; - unsigned int old_mode; - ULONG_PTR cookie = 0; - /* We use LoadLibraryEx so Windows looks for dependent DLLs - in directory of pathname first. However, Windows95 - can sometimes not work correctly unless the absolute - path is used. If GetFullPathName() fails, the LoadLibrary - will certainly fail too, so use its error code */ - - /* Don't display a message box when Python can't load a DLL */ - old_mode = SetErrorMode(SEM_FAILCRITICALERRORS); - - if (GetFullPathName(pathname, - sizeof(pathbuf), - pathbuf, - &dummy)) { - ULONG_PTR cookie = _Py_ActivateActCtx(); - /* XXX This call doesn't exist in Windows CE */ - hDLL = LoadLibraryEx(pathname, NULL, - LOAD_WITH_ALTERED_SEARCH_PATH); - _Py_DeactivateActCtx(cookie); - } - - /* restore old error mode settings */ - SetErrorMode(old_mode); - - if (hDLL==NULL){ - PyObject *message; - unsigned int errorCode; - - /* Get an error string from Win32 error code */ - wchar_t theInfo[256]; /* Pointer to error text - from system */ - int theLength; /* Length of error text */ - - errorCode = GetLastError(); - - theLength = FormatMessageW( - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, /* flags */ - NULL, /* message source */ - errorCode, /* the message (error) ID */ - MAKELANGID(LANG_NEUTRAL, - SUBLANG_DEFAULT), - /* Default language */ - theInfo, /* the buffer */ - sizeof(theInfo), /* the buffer size */ - NULL); /* no additional format args. */ - - /* Problem: could not get the error message. - This should not happen if called correctly. */ - if (theLength == 0) { - message = PyUnicode_FromFormat( - "DLL load failed with error code %d", - errorCode); - } else { - /* For some reason a \r\n - is appended to the text */ - if (theLength >= 2 && - theInfo[theLength-2] == '\r' && - theInfo[theLength-1] == '\n') { - theLength -= 2; - theInfo[theLength] = '\0'; - } - message = PyUnicode_FromString( - "DLL load failed: "); - - PyUnicode_AppendAndDel(&message, - PyUnicode_FromUnicode( - theInfo, - theLength)); - } - PyErr_SetObject(PyExc_ImportError, message); - Py_XDECREF(message); - return NULL; - } else { - char buffer[256]; + dl_funcptr p; + char funcname[258], *import_python; + + PyOS_snprintf(funcname, sizeof(funcname), "PyInit_%.200s", shortname); + + { + HINSTANCE hDLL = NULL; + char pathbuf[260]; + LPTSTR dummy; + unsigned int old_mode; + ULONG_PTR cookie = 0; + /* We use LoadLibraryEx so Windows looks for dependent DLLs + in directory of pathname first. However, Windows95 + can sometimes not work correctly unless the absolute + path is used. If GetFullPathName() fails, the LoadLibrary + will certainly fail too, so use its error code */ + + /* Don't display a message box when Python can't load a DLL */ + old_mode = SetErrorMode(SEM_FAILCRITICALERRORS); + + if (GetFullPathName(pathname, + sizeof(pathbuf), + pathbuf, + &dummy)) { + ULONG_PTR cookie = _Py_ActivateActCtx(); + /* XXX This call doesn't exist in Windows CE */ + hDLL = LoadLibraryEx(pathname, NULL, + LOAD_WITH_ALTERED_SEARCH_PATH); + _Py_DeactivateActCtx(cookie); + } + + /* restore old error mode settings */ + SetErrorMode(old_mode); + + if (hDLL==NULL){ + PyObject *message; + unsigned int errorCode; + + /* Get an error string from Win32 error code */ + wchar_t theInfo[256]; /* Pointer to error text + from system */ + int theLength; /* Length of error text */ + + errorCode = GetLastError(); + + theLength = FormatMessageW( + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, /* flags */ + NULL, /* message source */ + errorCode, /* the message (error) ID */ + MAKELANGID(LANG_NEUTRAL, + SUBLANG_DEFAULT), + /* Default language */ + theInfo, /* the buffer */ + sizeof(theInfo), /* the buffer size */ + NULL); /* no additional format args. */ + + /* Problem: could not get the error message. + This should not happen if called correctly. */ + if (theLength == 0) { + message = PyUnicode_FromFormat( + "DLL load failed with error code %d", + errorCode); + } else { + /* For some reason a \r\n + is appended to the text */ + if (theLength >= 2 && + theInfo[theLength-2] == '\r' && + theInfo[theLength-1] == '\n') { + theLength -= 2; + theInfo[theLength] = '\0'; + } + message = PyUnicode_FromString( + "DLL load failed: "); + + PyUnicode_AppendAndDel(&message, + PyUnicode_FromUnicode( + theInfo, + theLength)); + } + PyErr_SetObject(PyExc_ImportError, message); + Py_XDECREF(message); + return NULL; + } else { + char buffer[256]; #ifdef _DEBUG - PyOS_snprintf(buffer, sizeof(buffer), "python%d%d_d.dll", + PyOS_snprintf(buffer, sizeof(buffer), "python%d%d_d.dll", #else - PyOS_snprintf(buffer, sizeof(buffer), "python%d%d.dll", + PyOS_snprintf(buffer, sizeof(buffer), "python%d%d.dll", #endif - PY_MAJOR_VERSION,PY_MINOR_VERSION); - import_python = GetPythonImport(hDLL); - - 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; + 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/Python/errors.c b/Python/errors.c index 274bdbe476..e98d7a946c 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -24,166 +24,166 @@ extern "C" { void PyErr_Restore(PyObject *type, PyObject *value, PyObject *traceback) { - PyThreadState *tstate = PyThreadState_GET(); - PyObject *oldtype, *oldvalue, *oldtraceback; + 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; - } + 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; + /* 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; + tstate->curexc_type = type; + tstate->curexc_value = value; + tstate->curexc_traceback = traceback; - Py_XDECREF(oldtype); - Py_XDECREF(oldvalue); - Py_XDECREF(oldtraceback); + Py_XDECREF(oldtype); + Py_XDECREF(oldvalue); + Py_XDECREF(oldtraceback); } void PyErr_SetObject(PyObject *exception, PyObject *value) { - PyThreadState *tstate = PyThreadState_GET(); - PyObject *exc_value; - PyObject *tb = NULL; - - if (exception != NULL && - !PyExceptionClass_Check(exception)) { - PyErr_Format(PyExc_SystemError, - "exception %R not a BaseException subclass", - exception); - return; - } - Py_XINCREF(value); - exc_value = tstate->exc_value; - if (exc_value != NULL && exc_value != Py_None) { - /* Implicit exception chaining */ - Py_INCREF(exc_value); - if (value == NULL || !PyExceptionInstance_Check(value)) { - /* We must normalize the value right now */ - PyObject *args, *fixed_value; - if (value == NULL || value == Py_None) - args = PyTuple_New(0); - else if (PyTuple_Check(value)) { - Py_INCREF(value); - args = value; - } - else - args = PyTuple_Pack(1, value); - fixed_value = args ? - PyEval_CallObject(exception, args) : NULL; - Py_XDECREF(args); - Py_XDECREF(value); - if (fixed_value == NULL) - return; - value = fixed_value; - } - /* Avoid reference cycles through the context chain. - This is O(chain length) but context chains are - usually very short. Sensitive readers may try - to inline the call to PyException_GetContext. */ - if (exc_value != value) { - PyObject *o = exc_value, *context; - while ((context = PyException_GetContext(o))) { - Py_DECREF(context); - if (context == value) { - PyException_SetContext(o, NULL); - break; - } - o = context; - } - PyException_SetContext(value, exc_value); - } else { - Py_DECREF(exc_value); - } - } - if (value != NULL && PyExceptionInstance_Check(value)) - tb = PyException_GetTraceback(value); - Py_XINCREF(exception); - PyErr_Restore(exception, value, tb); + PyThreadState *tstate = PyThreadState_GET(); + PyObject *exc_value; + PyObject *tb = NULL; + + if (exception != NULL && + !PyExceptionClass_Check(exception)) { + PyErr_Format(PyExc_SystemError, + "exception %R not a BaseException subclass", + exception); + return; + } + Py_XINCREF(value); + exc_value = tstate->exc_value; + if (exc_value != NULL && exc_value != Py_None) { + /* Implicit exception chaining */ + Py_INCREF(exc_value); + if (value == NULL || !PyExceptionInstance_Check(value)) { + /* We must normalize the value right now */ + PyObject *args, *fixed_value; + if (value == NULL || value == Py_None) + args = PyTuple_New(0); + else if (PyTuple_Check(value)) { + Py_INCREF(value); + args = value; + } + else + args = PyTuple_Pack(1, value); + fixed_value = args ? + PyEval_CallObject(exception, args) : NULL; + Py_XDECREF(args); + Py_XDECREF(value); + if (fixed_value == NULL) + return; + value = fixed_value; + } + /* Avoid reference cycles through the context chain. + This is O(chain length) but context chains are + usually very short. Sensitive readers may try + to inline the call to PyException_GetContext. */ + if (exc_value != value) { + PyObject *o = exc_value, *context; + while ((context = PyException_GetContext(o))) { + Py_DECREF(context); + if (context == value) { + PyException_SetContext(o, NULL); + break; + } + o = context; + } + PyException_SetContext(value, exc_value); + } else { + Py_DECREF(exc_value); + } + } + if (value != NULL && PyExceptionInstance_Check(value)) + tb = PyException_GetTraceback(value); + Py_XINCREF(exception); + PyErr_Restore(exception, value, tb); } void PyErr_SetNone(PyObject *exception) { - PyErr_SetObject(exception, (PyObject *)NULL); + PyErr_SetObject(exception, (PyObject *)NULL); } void PyErr_SetString(PyObject *exception, const char *string) { - PyObject *value = PyUnicode_FromString(string); - PyErr_SetObject(exception, value); - Py_XDECREF(value); + PyObject *value = PyUnicode_FromString(string); + PyErr_SetObject(exception, value); + Py_XDECREF(value); } PyObject * PyErr_Occurred(void) { - PyThreadState *tstate = PyThreadState_GET(); + PyThreadState *tstate = PyThreadState_GET(); - return tstate->curexc_type; + return tstate->curexc_type; } int PyErr_GivenExceptionMatches(PyObject *err, PyObject *exc) { - if (err == NULL || exc == NULL) { - /* maybe caused by "import exceptions" that failed early on */ - return 0; - } - if (PyTuple_Check(exc)) { - Py_ssize_t i, n; - n = PyTuple_Size(exc); - for (i = 0; i < n; i++) { - /* Test recursively */ - if (PyErr_GivenExceptionMatches( - err, PyTuple_GET_ITEM(exc, i))) - { - return 1; - } - } - return 0; - } - /* err might be an instance, so check its class. */ - if (PyExceptionInstance_Check(err)) - err = PyExceptionInstance_Class(err); - - if (PyExceptionClass_Check(err) && PyExceptionClass_Check(exc)) { - int res = 0; - PyObject *exception, *value, *tb; - PyErr_Fetch(&exception, &value, &tb); - /* PyObject_IsSubclass() can recurse and therefore is - not safe (see test_bad_getattr in test.pickletester). */ - res = PyType_IsSubtype((PyTypeObject *)err, (PyTypeObject *)exc); - /* This function must not fail, so print the error here */ - if (res == -1) { - PyErr_WriteUnraisable(err); - res = 0; - } - PyErr_Restore(exception, value, tb); - return res; - } - - return err == exc; + if (err == NULL || exc == NULL) { + /* maybe caused by "import exceptions" that failed early on */ + return 0; + } + if (PyTuple_Check(exc)) { + Py_ssize_t i, n; + n = PyTuple_Size(exc); + for (i = 0; i < n; i++) { + /* Test recursively */ + if (PyErr_GivenExceptionMatches( + err, PyTuple_GET_ITEM(exc, i))) + { + return 1; + } + } + return 0; + } + /* err might be an instance, so check its class. */ + if (PyExceptionInstance_Check(err)) + err = PyExceptionInstance_Class(err); + + if (PyExceptionClass_Check(err) && PyExceptionClass_Check(exc)) { + int res = 0; + PyObject *exception, *value, *tb; + PyErr_Fetch(&exception, &value, &tb); + /* PyObject_IsSubclass() can recurse and therefore is + not safe (see test_bad_getattr in test.pickletester). */ + res = PyType_IsSubtype((PyTypeObject *)err, (PyTypeObject *)exc); + /* This function must not fail, so print the error here */ + if (res == -1) { + PyErr_WriteUnraisable(err); + res = 0; + } + PyErr_Restore(exception, value, tb); + return res; + } + + return err == exc; } int PyErr_ExceptionMatches(PyObject *exc) { - return PyErr_GivenExceptionMatches(PyErr_Occurred(), exc); + return PyErr_GivenExceptionMatches(PyErr_Occurred(), exc); } @@ -191,128 +191,128 @@ PyErr_ExceptionMatches(PyObject *exc) eval_code2(), do_raise(), and PyErr_Print() XXX: should PyErr_NormalizeException() also call - PyException_SetTraceback() with the resulting value and tb? + PyException_SetTraceback() with the resulting value and tb? */ void PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb) { - PyObject *type = *exc; - PyObject *value = *val; - PyObject *inclass = NULL; - PyObject *initial_tb = NULL; - PyThreadState *tstate = NULL; - - if (type == NULL) { - /* There was no exception, so nothing to do. */ - return; - } - - /* If PyErr_SetNone() was used, the value will have been actually - set to NULL. - */ - if (!value) { - value = Py_None; - Py_INCREF(value); - } - - if (PyExceptionInstance_Check(value)) - inclass = PyExceptionInstance_Class(value); - - /* Normalize the exception so that if the type is a class, the - value will be an instance. - */ - if (PyExceptionClass_Check(type)) { - /* if the value was not an instance, or is not an instance - whose class is (or is derived from) type, then use the - value as an argument to instantiation of the type - class. - */ - if (!inclass || !PyObject_IsSubclass(inclass, type)) { - PyObject *args, *res; - - if (value == Py_None) - args = PyTuple_New(0); - else if (PyTuple_Check(value)) { - Py_INCREF(value); - args = value; - } - else - args = PyTuple_Pack(1, value); - - if (args == NULL) - goto finally; - res = PyEval_CallObject(type, args); - Py_DECREF(args); - if (res == NULL) - goto finally; - Py_DECREF(value); - value = res; - } - /* if the class of the instance doesn't exactly match the - class of the type, believe the instance - */ - else if (inclass != type) { - Py_DECREF(type); - type = inclass; - Py_INCREF(type); - } - } - *exc = type; - *val = value; - return; + PyObject *type = *exc; + PyObject *value = *val; + PyObject *inclass = NULL; + PyObject *initial_tb = NULL; + PyThreadState *tstate = NULL; + + if (type == NULL) { + /* There was no exception, so nothing to do. */ + return; + } + + /* If PyErr_SetNone() was used, the value will have been actually + set to NULL. + */ + if (!value) { + value = Py_None; + Py_INCREF(value); + } + + if (PyExceptionInstance_Check(value)) + inclass = PyExceptionInstance_Class(value); + + /* Normalize the exception so that if the type is a class, the + value will be an instance. + */ + if (PyExceptionClass_Check(type)) { + /* if the value was not an instance, or is not an instance + whose class is (or is derived from) type, then use the + value as an argument to instantiation of the type + class. + */ + if (!inclass || !PyObject_IsSubclass(inclass, type)) { + PyObject *args, *res; + + if (value == Py_None) + args = PyTuple_New(0); + else if (PyTuple_Check(value)) { + Py_INCREF(value); + args = value; + } + else + args = PyTuple_Pack(1, value); + + if (args == NULL) + goto finally; + res = PyEval_CallObject(type, args); + Py_DECREF(args); + if (res == NULL) + goto finally; + Py_DECREF(value); + value = res; + } + /* if the class of the instance doesn't exactly match the + class of the type, believe the instance + */ + else if (inclass != type) { + Py_DECREF(type); + type = inclass; + Py_INCREF(type); + } + } + *exc = type; + *val = value; + return; finally: - Py_DECREF(type); - Py_DECREF(value); - /* If the new exception doesn't set a traceback and the old - exception had a traceback, use the old traceback for the - new exception. It's better than nothing. - */ - initial_tb = *tb; - PyErr_Fetch(exc, val, tb); - if (initial_tb != NULL) { - if (*tb == NULL) - *tb = initial_tb; - else - Py_DECREF(initial_tb); - } - /* normalize recursively */ - tstate = PyThreadState_GET(); - if (++tstate->recursion_depth > Py_GetRecursionLimit()) { - --tstate->recursion_depth; - /* throw away the old exception... */ - Py_DECREF(*exc); - Py_DECREF(*val); - /* ... and use the recursion error instead */ - *exc = PyExc_RuntimeError; - *val = PyExc_RecursionErrorInst; - Py_INCREF(*exc); - Py_INCREF(*val); - /* just keeping the old traceback */ - return; - } - PyErr_NormalizeException(exc, val, tb); - --tstate->recursion_depth; + Py_DECREF(type); + Py_DECREF(value); + /* If the new exception doesn't set a traceback and the old + exception had a traceback, use the old traceback for the + new exception. It's better than nothing. + */ + initial_tb = *tb; + PyErr_Fetch(exc, val, tb); + if (initial_tb != NULL) { + if (*tb == NULL) + *tb = initial_tb; + else + Py_DECREF(initial_tb); + } + /* normalize recursively */ + tstate = PyThreadState_GET(); + if (++tstate->recursion_depth > Py_GetRecursionLimit()) { + --tstate->recursion_depth; + /* throw away the old exception... */ + Py_DECREF(*exc); + Py_DECREF(*val); + /* ... and use the recursion error instead */ + *exc = PyExc_RuntimeError; + *val = PyExc_RecursionErrorInst; + Py_INCREF(*exc); + Py_INCREF(*val); + /* just keeping the old traceback */ + return; + } + PyErr_NormalizeException(exc, val, tb); + --tstate->recursion_depth; } void PyErr_Fetch(PyObject **p_type, PyObject **p_value, PyObject **p_traceback) { - PyThreadState *tstate = PyThreadState_GET(); + PyThreadState *tstate = PyThreadState_GET(); - *p_type = tstate->curexc_type; - *p_value = tstate->curexc_value; - *p_traceback = tstate->curexc_traceback; + *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; + tstate->curexc_type = NULL; + tstate->curexc_value = NULL; + tstate->curexc_traceback = NULL; } void PyErr_Clear(void) { - PyErr_Restore(NULL, NULL, NULL); + PyErr_Restore(NULL, NULL, NULL); } /* Convenience functions to set a type error exception and return 0 */ @@ -320,284 +320,284 @@ PyErr_Clear(void) int PyErr_BadArgument(void) { - PyErr_SetString(PyExc_TypeError, - "bad argument type for built-in operation"); - return 0; + 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) - { - /* Clear the previous traceback, otherwise it will be appended - * to the current one. - * - * The following statement is not likely to raise any error; - * if it does, we simply discard it. - */ - PyException_SetTraceback(PyExc_MemoryErrorInst, Py_None); - - 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; + if (PyErr_ExceptionMatches(PyExc_MemoryError)) + /* already current */ + return NULL; + + /* raise the pre-allocated instance if it still exists */ + if (PyExc_MemoryErrorInst) + { + /* Clear the previous traceback, otherwise it will be appended + * to the current one. + * + * The following statement is not likely to raise any error; + * if it does, we simply discard it. + */ + PyException_SetTraceback(PyExc_MemoryErrorInst, Py_None); + + 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 *message; - PyObject *v; - int i = errno; + PyObject *message; + PyObject *v; + int i = errno; #ifndef MS_WINDOWS - char *s; + char *s; #else - WCHAR *s_buf = NULL; + WCHAR *s_buf = NULL; #endif /* Unix/Windows */ #ifdef EINTR - if (i == EINTR && PyErr_CheckSignals()) - return NULL; + if (i == EINTR && PyErr_CheckSignals()) + return NULL; #endif #ifndef MS_WINDOWS - if (i == 0) - s = "Error"; /* Sometimes errno didn't get set */ - else - s = strerror(i); - message = PyUnicode_DecodeUTF8(s, strlen(s), "ignore"); + if (i == 0) + s = "Error"; /* Sometimes errno didn't get set */ + else + s = strerror(i); + message = PyUnicode_DecodeUTF8(s, strlen(s), "ignore"); #else - if (i == 0) - message = PyUnicode_FromString("Error"); /* Sometimes errno didn't get set */ - 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) { - message = PyUnicode_FromString(_sys_errlist[i]); - } - else { - int len = FormatMessageW( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, /* no message source */ - i, - MAKELANGID(LANG_NEUTRAL, - SUBLANG_DEFAULT), - /* Default language */ - (LPWSTR) &s_buf, - 0, /* size not used */ - NULL); /* no args */ - if (len==0) { - /* Only ever seen this in out-of-mem - situations */ - s_buf = NULL; - message = PyUnicode_FromFormat("Windows Error 0x%X", i); - } else { - /* remove trailing cr/lf and dots */ - while (len > 0 && (s_buf[len-1] <= L' ' || s_buf[len-1] == L'.')) - s_buf[--len] = L'\0'; - message = PyUnicode_FromUnicode(s_buf, len); - } - } - } + if (i == 0) + message = PyUnicode_FromString("Error"); /* Sometimes errno didn't get set */ + 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) { + message = PyUnicode_FromString(_sys_errlist[i]); + } + else { + int len = FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, /* no message source */ + i, + MAKELANGID(LANG_NEUTRAL, + SUBLANG_DEFAULT), + /* Default language */ + (LPWSTR) &s_buf, + 0, /* size not used */ + NULL); /* no args */ + if (len==0) { + /* Only ever seen this in out-of-mem + situations */ + s_buf = NULL; + message = PyUnicode_FromFormat("Windows Error 0x%X", i); + } else { + /* remove trailing cr/lf and dots */ + while (len > 0 && (s_buf[len-1] <= L' ' || s_buf[len-1] == L'.')) + s_buf[--len] = L'\0'; + message = PyUnicode_FromUnicode(s_buf, len); + } + } + } #endif /* Unix/Windows */ - if (message == NULL) - { + if (message == NULL) + { #ifdef MS_WINDOWS - LocalFree(s_buf); + LocalFree(s_buf); #endif - return NULL; - } - - if (filenameObject != NULL) - v = Py_BuildValue("(iOO)", i, message, filenameObject); - else - v = Py_BuildValue("(iO)", i, message); - Py_DECREF(message); - - if (v != NULL) { - PyErr_SetObject(exc, v); - Py_DECREF(v); - } + return NULL; + } + + if (filenameObject != NULL) + v = Py_BuildValue("(iOO)", i, message, filenameObject); + else + v = Py_BuildValue("(iO)", i, message); + Py_DECREF(message); + + if (v != NULL) { + PyErr_SetObject(exc, v); + Py_DECREF(v); + } #ifdef MS_WINDOWS - LocalFree(s_buf); + LocalFree(s_buf); #endif - return NULL; + return NULL; } PyObject * PyErr_SetFromErrnoWithFilename(PyObject *exc, const char *filename) { - PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL; - PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name); - Py_XDECREF(name); - return result; + PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL; + PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name); + Py_XDECREF(name); + return result; } #ifdef MS_WINDOWS PyObject * PyErr_SetFromErrnoWithUnicodeFilename(PyObject *exc, const Py_UNICODE *filename) { - PyObject *name = filename ? - PyUnicode_FromUnicode(filename, wcslen(filename)) : - NULL; - PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name); - Py_XDECREF(name); - return result; + PyObject *name = filename ? + PyUnicode_FromUnicode(filename, wcslen(filename)) : + NULL; + PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name); + Py_XDECREF(name); + return result; } #endif /* MS_WINDOWS */ PyObject * PyErr_SetFromErrno(PyObject *exc) { - return PyErr_SetFromErrnoWithFilenameObject(exc, NULL); + return PyErr_SetFromErrnoWithFilenameObject(exc, NULL); } #ifdef MS_WINDOWS /* Windows specific error code handling */ PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject( - PyObject *exc, - int ierr, - PyObject *filenameObject) + PyObject *exc, + int ierr, + PyObject *filenameObject) { - int len; - WCHAR *s_buf = NULL; /* Free via LocalFree */ - PyObject *message; - PyObject *v; - DWORD err = (DWORD)ierr; - if (err==0) err = GetLastError(); - len = FormatMessageW( - /* 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 */ - (LPWSTR) &s_buf, - 0, /* size not used */ - NULL); /* no args */ - if (len==0) { - /* Only seen this in out of mem situations */ - message = PyUnicode_FromFormat("Windows Error 0x%X", err); - s_buf = NULL; - } else { - /* remove trailing cr/lf and dots */ - while (len > 0 && (s_buf[len-1] <= L' ' || s_buf[len-1] == L'.')) - s_buf[--len] = L'\0'; - message = PyUnicode_FromUnicode(s_buf, len); - } - - if (message == NULL) - { - LocalFree(s_buf); - return NULL; - } - - if (filenameObject != NULL) - v = Py_BuildValue("(iOO)", err, message, filenameObject); - else - v = Py_BuildValue("(iO)", err, message); - Py_DECREF(message); - - if (v != NULL) { - PyErr_SetObject(exc, v); - Py_DECREF(v); - } - LocalFree(s_buf); - return NULL; + int len; + WCHAR *s_buf = NULL; /* Free via LocalFree */ + PyObject *message; + PyObject *v; + DWORD err = (DWORD)ierr; + if (err==0) err = GetLastError(); + len = FormatMessageW( + /* 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 */ + (LPWSTR) &s_buf, + 0, /* size not used */ + NULL); /* no args */ + if (len==0) { + /* Only seen this in out of mem situations */ + message = PyUnicode_FromFormat("Windows Error 0x%X", err); + s_buf = NULL; + } else { + /* remove trailing cr/lf and dots */ + while (len > 0 && (s_buf[len-1] <= L' ' || s_buf[len-1] == L'.')) + s_buf[--len] = L'\0'; + message = PyUnicode_FromUnicode(s_buf, len); + } + + if (message == NULL) + { + LocalFree(s_buf); + return NULL; + } + + if (filenameObject != NULL) + v = Py_BuildValue("(iOO)", err, message, filenameObject); + else + v = Py_BuildValue("(iO)", err, message); + Py_DECREF(message); + + 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 *exc, + int ierr, + const char *filename) { - PyObject *name = filename ? PyUnicode_FromString(filename) : NULL; - PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc, - ierr, - name); - Py_XDECREF(name); - return ret; + PyObject *name = filename ? PyUnicode_FromString(filename) : NULL; + PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc, + ierr, + name); + Py_XDECREF(name); + return ret; } PyObject *PyErr_SetExcFromWindowsErrWithUnicodeFilename( - PyObject *exc, - int ierr, - const Py_UNICODE *filename) + PyObject *exc, + int ierr, + const Py_UNICODE *filename) { - PyObject *name = filename ? - PyUnicode_FromUnicode(filename, wcslen(filename)) : - NULL; - PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc, - ierr, - name); - Py_XDECREF(name); - return ret; + PyObject *name = filename ? + PyUnicode_FromUnicode(filename, wcslen(filename)) : + NULL; + PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc, + ierr, + name); + Py_XDECREF(name); + return ret; } PyObject *PyErr_SetExcFromWindowsErr(PyObject *exc, int ierr) { - return PyErr_SetExcFromWindowsErrWithFilename(exc, ierr, NULL); + return PyErr_SetExcFromWindowsErrWithFilename(exc, ierr, NULL); } PyObject *PyErr_SetFromWindowsErr(int ierr) { - return PyErr_SetExcFromWindowsErrWithFilename(PyExc_WindowsError, - ierr, NULL); + return PyErr_SetExcFromWindowsErrWithFilename(PyExc_WindowsError, + ierr, NULL); } PyObject *PyErr_SetFromWindowsErrWithFilename( - int ierr, - const char *filename) + int ierr, + const char *filename) { - PyObject *name = filename ? PyUnicode_FromString(filename) : NULL; - PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject( - PyExc_WindowsError, - ierr, name); - Py_XDECREF(name); - return result; + PyObject *name = filename ? PyUnicode_FromString(filename) : NULL; + PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject( + PyExc_WindowsError, + ierr, name); + Py_XDECREF(name); + return result; } PyObject *PyErr_SetFromWindowsErrWithUnicodeFilename( - int ierr, - const Py_UNICODE *filename) + 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; + PyObject *name = filename ? + PyUnicode_FromUnicode(filename, wcslen(filename)) : + NULL; + PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject( + PyExc_WindowsError, + ierr, name); + Py_XDECREF(name); + return result; } #endif /* MS_WINDOWS */ void _PyErr_BadInternalCall(const char *filename, int lineno) { - PyErr_Format(PyExc_SystemError, - "%s:%d: bad argument to internal function", - filename, 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 @@ -606,8 +606,8 @@ _PyErr_BadInternalCall(const char *filename, int lineno) void PyErr_BadInternalCall(void) { - PyErr_Format(PyExc_SystemError, - "bad argument to internal function"); + PyErr_Format(PyExc_SystemError, + "bad argument to internal function"); } #define PyErr_BadInternalCall() _PyErr_BadInternalCall(__FILE__, __LINE__) @@ -616,20 +616,20 @@ PyErr_BadInternalCall(void) PyObject * PyErr_Format(PyObject *exception, const char *format, ...) { - va_list vargs; - PyObject* string; + va_list vargs; + PyObject* string; #ifdef HAVE_STDARG_PROTOTYPES - va_start(vargs, format); + va_start(vargs, format); #else - va_start(vargs); + va_start(vargs); #endif - string = PyUnicode_FromFormatV(format, vargs); - PyErr_SetObject(exception, string); - Py_XDECREF(string); - va_end(vargs); - return NULL; + string = PyUnicode_FromFormatV(format, vargs); + PyErr_SetObject(exception, string); + Py_XDECREF(string); + va_end(vargs); + return NULL; } @@ -637,85 +637,85 @@ PyErr_Format(PyObject *exception, const char *format, ...) PyObject * PyErr_NewException(const char *name, PyObject *base, PyObject *dict) { - const 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 = PyUnicode_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, "UOO", - dot+1, bases, dict); + const 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 = PyUnicode_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, "UOO", + dot+1, bases, dict); failure: - Py_XDECREF(bases); - Py_XDECREF(mydict); - Py_XDECREF(classname); - Py_XDECREF(modulename); - return result; + Py_XDECREF(bases); + Py_XDECREF(mydict); + Py_XDECREF(classname); + Py_XDECREF(modulename); + return result; } /* Create an exception with docstring */ PyObject * PyErr_NewExceptionWithDoc(const char *name, const char *doc, - PyObject *base, PyObject *dict) + PyObject *base, PyObject *dict) { - int result; - PyObject *ret = NULL; - PyObject *mydict = NULL; /* points to the dict only if we create it */ - PyObject *docobj; - - if (dict == NULL) { - dict = mydict = PyDict_New(); - if (dict == NULL) { - return NULL; - } - } - - if (doc != NULL) { - docobj = PyUnicode_FromString(doc); - if (docobj == NULL) - goto failure; - result = PyDict_SetItemString(dict, "__doc__", docobj); - Py_DECREF(docobj); - if (result < 0) - goto failure; - } - - ret = PyErr_NewException(name, base, dict); + int result; + PyObject *ret = NULL; + PyObject *mydict = NULL; /* points to the dict only if we create it */ + PyObject *docobj; + + if (dict == NULL) { + dict = mydict = PyDict_New(); + if (dict == NULL) { + return NULL; + } + } + + if (doc != NULL) { + docobj = PyUnicode_FromString(doc); + if (docobj == NULL) + goto failure; + result = PyDict_SetItemString(dict, "__doc__", docobj); + Py_DECREF(docobj); + if (result < 0) + goto failure; + } + + ret = PyErr_NewException(name, base, dict); failure: - Py_XDECREF(mydict); - return ret; + Py_XDECREF(mydict); + return ret; } @@ -724,52 +724,52 @@ PyErr_NewExceptionWithDoc(const char *name, const char *doc, void PyErr_WriteUnraisable(PyObject *obj) { - PyObject *f, *t, *v, *tb; - PyErr_Fetch(&t, &v, &tb); - f = PySys_GetObject("stderr"); - if (f != NULL && f != Py_None) { - PyFile_WriteString("Exception ", f); - if (t) { - PyObject* moduleName; - char* className; - assert(PyExceptionClass_Check(t)); - className = PyExceptionClass_Name(t); - if (className != NULL) { - char *dot = strrchr(className, '.'); - if (dot != NULL) - className = dot+1; - } - - moduleName = PyObject_GetAttrString(t, "__module__"); - if (moduleName == NULL) - PyFile_WriteString("", f); - else { - char* modstr = _PyUnicode_AsString(moduleName); - if (modstr && - strcmp(modstr, "builtins") != 0) - { - PyFile_WriteString(modstr, f); - PyFile_WriteString(".", f); - } - } - if (className == NULL) - PyFile_WriteString("", 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); + PyObject *f, *t, *v, *tb; + PyErr_Fetch(&t, &v, &tb); + f = PySys_GetObject("stderr"); + if (f != NULL && f != Py_None) { + PyFile_WriteString("Exception ", f); + if (t) { + PyObject* moduleName; + char* className; + assert(PyExceptionClass_Check(t)); + className = PyExceptionClass_Name(t); + if (className != NULL) { + char *dot = strrchr(className, '.'); + if (dot != NULL) + className = dot+1; + } + + moduleName = PyObject_GetAttrString(t, "__module__"); + if (moduleName == NULL) + PyFile_WriteString("", f); + else { + char* modstr = _PyUnicode_AsString(moduleName); + if (modstr && + strcmp(modstr, "builtins") != 0) + { + PyFile_WriteString(modstr, f); + PyFile_WriteString(".", f); + } + } + if (className == NULL) + PyFile_WriteString("", 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); @@ -782,59 +782,59 @@ extern PyObject *PyModule_GetWarningsModule(void); 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 = PyLong_FromLong(lineno); - if (tmp == NULL) - PyErr_Clear(); - else { - if (PyObject_SetAttrString(v, "lineno", tmp)) - PyErr_Clear(); - Py_DECREF(tmp); - } - if (filename != NULL) { - tmp = PyUnicode_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); + 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 = PyLong_FromLong(lineno); + if (tmp == NULL) + PyErr_Clear(); + else { + if (PyObject_SetAttrString(v, "lineno", tmp)) + PyErr_Clear(); + Py_DECREF(tmp); + } + if (filename != NULL) { + tmp = PyUnicode_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); } /* Attempt to load the line of text that the exception refers to. If it @@ -846,41 +846,41 @@ PyErr_SyntaxLocation(const char *filename, int lineno) 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; - PyObject *res; - while (*p == ' ' || *p == '\t' || *p == '\014') - p++; - res = PyUnicode_FromString(p); - if (res == NULL) - PyErr_Clear(); - return res; - } - return NULL; + 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; + PyObject *res; + while (*p == ' ' || *p == '\t' || *p == '\014') + p++; + res = PyUnicode_FromString(p); + if (res == NULL) + PyErr_Clear(); + return res; + } + return NULL; } #ifdef __cplusplus diff --git a/Python/frozen.c b/Python/frozen.c index 1e40d7df3c..57d8257ed5 100644 --- a/Python/frozen.c +++ b/Python/frozen.c @@ -12,25 +12,25 @@ the appropriate bytes from M___main__.c. */ static unsigned char M___hello__[] = { - 99,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, - 0,64,0,0,0,115,10,0,0,0,100,1,0,90,1,0, - 100,0,0,83,40,2,0,0,0,78,84,40,2,0,0,0, - 117,4,0,0,0,84,114,117,101,117,11,0,0,0,105,110, - 105,116,105,97,108,105,122,101,100,40,0,0,0,0,40,0, - 0,0,0,40,0,0,0,0,117,7,0,0,0,102,108,97, - 103,46,112,121,117,8,0,0,0,60,109,111,100,117,108,101, - 62,1,0,0,0,115,0,0,0,0, + 99,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, + 0,64,0,0,0,115,10,0,0,0,100,1,0,90,1,0, + 100,0,0,83,40,2,0,0,0,78,84,40,2,0,0,0, + 117,4,0,0,0,84,114,117,101,117,11,0,0,0,105,110, + 105,116,105,97,108,105,122,101,100,40,0,0,0,0,40,0, + 0,0,0,40,0,0,0,0,117,7,0,0,0,102,108,97, + 103,46,112,121,117,8,0,0,0,60,109,111,100,117,108,101, + 62,1,0,0,0,115,0,0,0,0, }; #define SIZE (int)sizeof(M___hello__) static struct _frozen _PyImport_FrozenModules[] = { - /* Test module */ - {"__hello__", M___hello__, SIZE}, - /* Test package (negative size indicates package-ness) */ - {"__phello__", M___hello__, -SIZE}, - {"__phello__.spam", M___hello__, SIZE}, - {0, 0, 0} /* sentinel */ + /* Test module */ + {"__hello__", M___hello__, SIZE}, + /* Test package (negative size indicates package-ness) */ + {"__phello__", M___hello__, -SIZE}, + {"__phello__.spam", M___hello__, SIZE}, + {0, 0, 0} /* sentinel */ }; /* Embedding apps may change this pointer to point to their favorite diff --git a/Python/frozenmain.c b/Python/frozenmain.c index b14c391bf9..f08caf23b9 100644 --- a/Python/frozenmain.c +++ b/Python/frozenmain.c @@ -15,96 +15,96 @@ extern int PyInitFrozenExtensions(void); int Py_FrozenMain(int argc, char **argv) { - char *p; - int i, n, sts; - int inspect = 0; - int unbuffered = 0; - char *oldloc; - wchar_t **argv_copy = PyMem_Malloc(sizeof(wchar_t*)*argc); - /* We need a second copies, as Python might modify the first one. */ - wchar_t **argv_copy2 = PyMem_Malloc(sizeof(wchar_t*)*argc); - - 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); - } - - if (!argv_copy) { - fprintf(stderr, "out of memory\n"); - return 1; - } - - oldloc = setlocale(LC_ALL, NULL); - setlocale(LC_ALL, ""); - for (i = 0; i < argc; i++) { + char *p; + int i, n, sts; + int inspect = 0; + int unbuffered = 0; + char *oldloc; + wchar_t **argv_copy = PyMem_Malloc(sizeof(wchar_t*)*argc); + /* We need a second copies, as Python might modify the first one. */ + wchar_t **argv_copy2 = PyMem_Malloc(sizeof(wchar_t*)*argc); + + Py_FrozenFlag = 1; /* Suppress errors from getpath.c */ + + if ((p = Py_GETENV("PYTHONINSPECT")) && *p != '\0') + inspect = 1; + if ((p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0') + unbuffered = 1; + + if (unbuffered) { + setbuf(stdin, (char *)NULL); + setbuf(stdout, (char *)NULL); + setbuf(stderr, (char *)NULL); + } + + if (!argv_copy) { + fprintf(stderr, "out of memory\n"); + return 1; + } + + oldloc = setlocale(LC_ALL, NULL); + setlocale(LC_ALL, ""); + for (i = 0; i < argc; i++) { #ifdef HAVE_BROKEN_MBSTOWCS - size_t argsize = strlen(argv[i]); + size_t argsize = strlen(argv[i]); #else - size_t argsize = mbstowcs(NULL, argv[i], 0); + size_t argsize = mbstowcs(NULL, argv[i], 0); #endif - size_t count; - if (argsize == (size_t)-1) { - fprintf(stderr, "Could not convert argument %d to string\n", i); - return 1; - } - argv_copy[i] = PyMem_Malloc((argsize+1)*sizeof(wchar_t)); - argv_copy2[i] = argv_copy[i]; - if (!argv_copy[i]) { - fprintf(stderr, "out of memory\n"); - return 1; - } - count = mbstowcs(argv_copy[i], argv[i], argsize+1); - if (count == (size_t)-1) { - fprintf(stderr, "Could not convert argument %d to string\n", i); - return 1; - } - } - setlocale(LC_ALL, oldloc); + size_t count; + if (argsize == (size_t)-1) { + fprintf(stderr, "Could not convert argument %d to string\n", i); + return 1; + } + argv_copy[i] = PyMem_Malloc((argsize+1)*sizeof(wchar_t)); + argv_copy2[i] = argv_copy[i]; + if (!argv_copy[i]) { + fprintf(stderr, "out of memory\n"); + return 1; + } + count = mbstowcs(argv_copy[i], argv[i], argsize+1); + if (count == (size_t)-1) { + fprintf(stderr, "Could not convert argument %d to string\n", i); + return 1; + } + } + setlocale(LC_ALL, oldloc); #ifdef MS_WINDOWS - PyInitFrozenExtensions(); + PyInitFrozenExtensions(); #endif /* MS_WINDOWS */ - Py_SetProgramName(argv_copy[0]); - Py_Initialize(); + Py_SetProgramName(argv_copy[0]); + Py_Initialize(); #ifdef MS_WINDOWS - PyWinFreeze_ExeInit(); + PyWinFreeze_ExeInit(); #endif - if (Py_VerboseFlag) - fprintf(stderr, "Python %s\n%s\n", - Py_GetVersion(), Py_GetCopyright()); + if (Py_VerboseFlag) + fprintf(stderr, "Python %s\n%s\n", + Py_GetVersion(), Py_GetCopyright()); - PySys_SetArgv(argc, argv_copy); + PySys_SetArgv(argc, argv_copy); - n = PyImport_ImportFrozenModule("__main__"); - if (n == 0) - Py_FatalError("__main__ not frozen"); - if (n < 0) { - PyErr_Print(); - sts = 1; - } - else - sts = 0; + n = PyImport_ImportFrozenModule("__main__"); + if (n == 0) + Py_FatalError("__main__ not frozen"); + if (n < 0) { + PyErr_Print(); + sts = 1; + } + else + sts = 0; - if (inspect && isatty((int)fileno(stdin))) - sts = PyRun_AnyFile(stdin, "") != 0; + if (inspect && isatty((int)fileno(stdin))) + sts = PyRun_AnyFile(stdin, "") != 0; #ifdef MS_WINDOWS - PyWinFreeze_ExeTerm(); + PyWinFreeze_ExeTerm(); #endif - Py_Finalize(); - for (i = 0; i < argc; i++) { - PyMem_Free(argv_copy2[i]); - } - PyMem_Free(argv_copy); - PyMem_Free(argv_copy2); - return sts; + Py_Finalize(); + for (i = 0; i < argc; i++) { + PyMem_Free(argv_copy2[i]); + } + PyMem_Free(argv_copy); + PyMem_Free(argv_copy2); + return sts; } diff --git a/Python/future.c b/Python/future.c index 4178541585..515dcd9dc6 100644 --- a/Python/future.c +++ b/Python/future.c @@ -14,131 +14,131 @@ static int future_check_features(PyFutureFeatures *ff, stmt_ty s, const char *filename) { - int i; - asdl_seq *names; - - assert(s->kind == ImportFrom_kind); - - names = s->v.ImportFrom.names; - for (i = 0; i < asdl_seq_LEN(names); i++) { - alias_ty name = (alias_ty)asdl_seq_GET(names, i); - const char *feature = _PyUnicode_AsString(name->name); - if (!feature) - return 0; - if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) { - continue; - } else if (strcmp(feature, FUTURE_GENERATORS) == 0) { - continue; - } else if (strcmp(feature, FUTURE_DIVISION) == 0) { - continue; - } else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) { - continue; - } else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) { - continue; - } else if (strcmp(feature, FUTURE_PRINT_FUNCTION) == 0) { - continue; - } else if (strcmp(feature, FUTURE_UNICODE_LITERALS) == 0) { - continue; - } else if (strcmp(feature, FUTURE_BARRY_AS_BDFL) == 0) { - ff->ff_features |= CO_FUTURE_BARRY_AS_BDFL; - } else if (strcmp(feature, "braces") == 0) { - PyErr_SetString(PyExc_SyntaxError, - "not a chance"); - PyErr_SyntaxLocation(filename, s->lineno); - return 0; - } else { - PyErr_Format(PyExc_SyntaxError, - UNDEFINED_FUTURE_FEATURE, feature); - PyErr_SyntaxLocation(filename, s->lineno); - return 0; - } - } - return 1; + int i; + asdl_seq *names; + + assert(s->kind == ImportFrom_kind); + + names = s->v.ImportFrom.names; + for (i = 0; i < asdl_seq_LEN(names); i++) { + alias_ty name = (alias_ty)asdl_seq_GET(names, i); + const char *feature = _PyUnicode_AsString(name->name); + if (!feature) + return 0; + if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) { + continue; + } else if (strcmp(feature, FUTURE_GENERATORS) == 0) { + continue; + } else if (strcmp(feature, FUTURE_DIVISION) == 0) { + continue; + } else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) { + continue; + } else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) { + continue; + } else if (strcmp(feature, FUTURE_PRINT_FUNCTION) == 0) { + continue; + } else if (strcmp(feature, FUTURE_UNICODE_LITERALS) == 0) { + continue; + } else if (strcmp(feature, FUTURE_BARRY_AS_BDFL) == 0) { + ff->ff_features |= CO_FUTURE_BARRY_AS_BDFL; + } else if (strcmp(feature, "braces") == 0) { + PyErr_SetString(PyExc_SyntaxError, + "not a chance"); + PyErr_SyntaxLocation(filename, s->lineno); + return 0; + } else { + PyErr_Format(PyExc_SyntaxError, + UNDEFINED_FUTURE_FEATURE, feature); + PyErr_SyntaxLocation(filename, s->lineno); + return 0; + } + } + return 1; } static int future_parse(PyFutureFeatures *ff, mod_ty mod, const char *filename) { - int i, found_docstring = 0, done = 0, prev_line = 0; - - static PyObject *future; - if (!future) { - future = PyUnicode_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 handle here: A series of imports - joined by semi-colons, where the first import is a future - statement but some subsequent import has the future form - but is preceded by a regular import. - */ - - - for (i = 0; i < asdl_seq_LEN(mod->v.Module.body); i++) { - stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i); - - if (done && s->lineno > prev_line) - return 1; - prev_line = s->lineno; - - /* The tests below will return from this function unless it is - still possible to find a future statement. The only things - that can precede a future statement are another future - statement and a doc string. - */ - - if (s->kind == ImportFrom_kind) { - 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; + int i, found_docstring = 0, done = 0, prev_line = 0; + + static PyObject *future; + if (!future) { + future = PyUnicode_InternFromString("__future__"); + if (!future) + return 0; + } + + if (!(mod->kind == Module_kind || mod->kind == Interactive_kind)) + return 1; + + /* A subsequent pass will detect future imports that don't + appear at the beginning of the file. There's one case, + however, that is easier to handle here: A series of imports + joined by semi-colons, where the first import is a future + statement but some subsequent import has the future form + but is preceded by a regular import. + */ + + + for (i = 0; i < asdl_seq_LEN(mod->v.Module.body); i++) { + stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i); + + if (done && s->lineno > prev_line) + return 1; + prev_line = s->lineno; + + /* The tests below will return from this function unless it is + still possible to find a future statement. The only things + that can precede a future statement are another future + statement and a doc string. + */ + + if (s->kind == ImportFrom_kind) { + 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; + 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/Python/getargs.c b/Python/getargs.c index 69f5018c4c..4fa2b5bffb 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -14,9 +14,9 @@ int PyArg_ParseTuple(PyObject *, const char *, ...); int PyArg_VaParse(PyObject *, const char *, va_list); int PyArg_ParseTupleAndKeywords(PyObject *, PyObject *, - const char *, char **, ...); + const char *, char **, ...); int PyArg_VaParseTupleAndKeywords(PyObject *, PyObject *, - const char *, char **, va_list); + const char *, char **, va_list); #ifdef HAVE_DECLSPEC_DLL /* Export functions */ @@ -40,100 +40,100 @@ 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 **); + int *, char *, size_t, int, PyObject **); static char *convertsimple(PyObject *, const char **, va_list *, int, char *, - size_t, PyObject **); + size_t, PyObject **); static Py_ssize_t convertbuffer(PyObject *, void **p, char **); static int getbuffer(PyObject *, Py_buffer *, char**); static int vgetargskeywords(PyObject *, PyObject *, - const char *, char **, va_list *, int); + 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; + int retval; + va_list va; - va_start(va, format); - retval = vgetargs1(args, format, &va, FLAG_COMPAT); - va_end(va); - return retval; + 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; + int retval; + va_list va; - va_start(va, format); - retval = vgetargs1(args, format, &va, FLAG_COMPAT|FLAG_SIZE_T); - va_end(va); - return retval; + 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; + int retval; + va_list va; - va_start(va, format); - retval = vgetargs1(args, format, &va, 0); - va_end(va); - return retval; + 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; + int retval; + va_list va; - va_start(va, format); - retval = vgetargs1(args, format, &va, FLAG_SIZE_T); - va_end(va); - return retval; + 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; + va_list lva; #ifdef VA_LIST_IS_ARRAY - memcpy(lva, va, sizeof(va_list)); + memcpy(lva, va, sizeof(va_list)); #else #ifdef __va_copy - __va_copy(lva, va); + __va_copy(lva, va); #else - lva = va; + lva = va; #endif #endif - return vgetargs1(args, format, &lva, 0); + return vgetargs1(args, format, &lva, 0); } int _PyArg_VaParse_SizeT(PyObject *args, char *format, va_list va) { - va_list lva; + va_list lva; #ifdef VA_LIST_IS_ARRAY - memcpy(lva, va, sizeof(va_list)); + memcpy(lva, va, sizeof(va_list)); #else #ifdef __va_copy - __va_copy(lva, va); + __va_copy(lva, va); #else - lva = va; + lva = va; #endif #endif - return vgetargs1(args, format, &lva, FLAG_SIZE_T); + return vgetargs1(args, format, &lva, FLAG_SIZE_T); } @@ -146,261 +146,261 @@ _PyArg_VaParse_SizeT(PyObject *args, char *format, va_list va) static void cleanup_ptr(PyObject *self) { - void *ptr = PyCapsule_GetPointer(self, GETARGS_CAPSULE_NAME_CLEANUP_PTR); - if (ptr) { - PyMem_FREE(ptr); - } + void *ptr = PyCapsule_GetPointer(self, GETARGS_CAPSULE_NAME_CLEANUP_PTR); + if (ptr) { + PyMem_FREE(ptr); + } } static void cleanup_buffer(PyObject *self) { - Py_buffer *ptr = (Py_buffer *)PyCapsule_GetPointer(self, GETARGS_CAPSULE_NAME_CLEANUP_BUFFER); - if (ptr) { - PyBuffer_Release(ptr); - } + Py_buffer *ptr = (Py_buffer *)PyCapsule_GetPointer(self, GETARGS_CAPSULE_NAME_CLEANUP_BUFFER); + if (ptr) { + PyBuffer_Release(ptr); + } } static int addcleanup(void *ptr, PyObject **freelist, PyCapsule_Destructor destr) { - PyObject *cobj; - const char *name; - - if (!*freelist) { - *freelist = PyList_New(0); - if (!*freelist) { - destr(ptr); - return -1; - } - } - - if (destr == cleanup_ptr) { - name = GETARGS_CAPSULE_NAME_CLEANUP_PTR; - } else if (destr == cleanup_buffer) { - name = GETARGS_CAPSULE_NAME_CLEANUP_BUFFER; - } else { - return -1; - } - cobj = PyCapsule_New(ptr, name, destr); - if (!cobj) { - destr(ptr); - return -1; - } - if (PyList_Append(*freelist, cobj)) { - Py_DECREF(cobj); - return -1; - } + PyObject *cobj; + const char *name; + + if (!*freelist) { + *freelist = PyList_New(0); + if (!*freelist) { + destr(ptr); + return -1; + } + } + + if (destr == cleanup_ptr) { + name = GETARGS_CAPSULE_NAME_CLEANUP_PTR; + } else if (destr == cleanup_buffer) { + name = GETARGS_CAPSULE_NAME_CLEANUP_BUFFER; + } else { + return -1; + } + cobj = PyCapsule_New(ptr, name, destr); + if (!cobj) { + destr(ptr); + return -1; + } + if (PyList_Append(*freelist, cobj)) { Py_DECREF(cobj); - return 0; + return -1; + } + Py_DECREF(cobj); + return 0; } static void cleanup_convert(PyObject *self) { - typedef int (*destr_t)(PyObject *, void *); - destr_t destr = (destr_t)PyCapsule_GetContext(self); - void *ptr = PyCapsule_GetPointer(self, - GETARGS_CAPSULE_NAME_CLEANUP_CONVERT); - if (ptr && destr) - destr(NULL, ptr); + typedef int (*destr_t)(PyObject *, void *); + destr_t destr = (destr_t)PyCapsule_GetContext(self); + void *ptr = PyCapsule_GetPointer(self, + GETARGS_CAPSULE_NAME_CLEANUP_CONVERT); + if (ptr && destr) + destr(NULL, ptr); } static int addcleanup_convert(void *ptr, PyObject **freelist, int (*destr)(PyObject*,void*)) { - PyObject *cobj; - if (!*freelist) { - *freelist = PyList_New(0); - if (!*freelist) { - destr(NULL, ptr); - return -1; - } - } - cobj = PyCapsule_New(ptr, GETARGS_CAPSULE_NAME_CLEANUP_CONVERT, - cleanup_convert); - if (!cobj) { - destr(NULL, ptr); - return -1; - } - if (PyCapsule_SetContext(cobj, destr) == -1) { - /* This really should not happen. */ - Py_FatalError("capsule refused setting of context."); - } - if (PyList_Append(*freelist, cobj)) { - Py_DECREF(cobj); /* This will also call destr. */ - return -1; - } - Py_DECREF(cobj); - return 0; + PyObject *cobj; + if (!*freelist) { + *freelist = PyList_New(0); + if (!*freelist) { + destr(NULL, ptr); + return -1; + } + } + cobj = PyCapsule_New(ptr, GETARGS_CAPSULE_NAME_CLEANUP_CONVERT, + cleanup_convert); + if (!cobj) { + destr(NULL, ptr); + return -1; + } + if (PyCapsule_SetContext(cobj, destr) == -1) { + /* This really should not happen. */ + Py_FatalError("capsule refused setting of context."); + } + if (PyList_Append(*freelist, cobj)) { + Py_DECREF(cobj); /* This will also call destr. */ + return -1; + } + Py_DECREF(cobj); + return 0; } static int cleanreturn(int retval, PyObject *freelist) { - if (freelist && retval != 0) { - /* We were successful, reset the destructors so that they - don't get called. */ - Py_ssize_t len = PyList_GET_SIZE(freelist), i; - for (i = 0; i < len; i++) - PyCapsule_SetDestructor(PyList_GET_ITEM(freelist, i), NULL); - } - Py_XDECREF(freelist); - return retval; + if (freelist && retval != 0) { + /* We were successful, reset the destructors so that they + don't get called. */ + Py_ssize_t len = PyList_GET_SIZE(freelist), i; + for (i = 0; i < len; i++) + PyCapsule_SetDestructor(PyList_GET_ITEM(freelist, i), NULL); + } + Py_XDECREF(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, msg); - 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); + 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, msg); + 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); } @@ -409,37 +409,37 @@ 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); + 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); } @@ -455,9 +455,9 @@ seterror(int iarg, const char *msg, int *levels, const char *fname, *p_va is undefined, *levels is a 0-terminated list of item numbers, *msgbuf contains an error message, whose format is: - "must be , not ", where: - is the name of the expected type, and - is the name of the actual type, + "must be , not ", where: + is the name of the expected type, and + is the name of the actual type, and msgbuf is returned. */ @@ -466,72 +466,72 @@ 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) || PyBytes_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; + 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) || PyBytes_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; } @@ -541,43 +541,43 @@ 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; + 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) + _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; + 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)" @@ -587,12 +587,12 @@ converterr(const char *expected, PyObject *arg, char *msgbuf, size_t bufsize) static int float_argument_warning(PyObject *arg) { - if (PyFloat_Check(arg) && - PyErr_Warn(PyExc_DeprecationWarning, - "integer argument expected, got float" )) - return 1; - else - return 0; + if (PyFloat_Check(arg) && + PyErr_Warn(PyExc_DeprecationWarning, + "integer argument expected, got float" )) + return 1; + else + return 0; } /* Explicitly check for float arguments when integers are expected. @@ -600,13 +600,13 @@ float_argument_warning(PyObject *arg) static int float_argument_error(PyObject *arg) { - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - return 1; - } - else - return 0; + if (PyFloat_Check(arg)) { + PyErr_SetString(PyExc_TypeError, + "integer argument expected, got float" ); + return 1; + } + else + return 0; } /* Convert a non-tuple argument. Return NULL if conversion went OK, @@ -622,837 +622,837 @@ 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*); + /* 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++; - PyObject *uarg; - - 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", arg, msgbuf, bufsize); - ival = PyLong_AsLong(arg); - if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); - else if (ival < 0) { - PyErr_SetString(PyExc_OverflowError, - "unsigned byte integer is less than minimum"); - return converterr("integer", arg, msgbuf, bufsize); - } - else if (ival > UCHAR_MAX) { - PyErr_SetString(PyExc_OverflowError, - "unsigned byte integer is greater than maximum"); - return converterr("integer", 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", arg, msgbuf, bufsize); - ival = PyLong_AsUnsignedLongMask(arg); - if (ival == -1 && PyErr_Occurred()) - return converterr("integer", 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", arg, msgbuf, bufsize); - ival = PyLong_AsLong(arg); - if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); - else if (ival < SHRT_MIN) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is less than minimum"); - return converterr("integer", arg, msgbuf, bufsize); - } - else if (ival > SHRT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is greater than maximum"); - return converterr("integer", 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", arg, msgbuf, bufsize); - ival = PyLong_AsUnsignedLongMask(arg); - if (ival == -1 && PyErr_Occurred()) - return converterr("integer", 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", arg, msgbuf, bufsize); - ival = PyLong_AsLong(arg); - if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); - else if (ival > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "signed integer is greater than maximum"); - return converterr("integer", arg, msgbuf, bufsize); - } - else if (ival < INT_MIN) { - PyErr_SetString(PyExc_OverflowError, - "signed integer is less than minimum"); - return converterr("integer", 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", arg, msgbuf, bufsize); - ival = (unsigned int)PyLong_AsUnsignedLongMask(arg); - if (ival == (unsigned int)-1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); - else - *p = ival; - break; - } - - case 'n': /* Py_ssize_t */ - { - PyObject *iobj; - Py_ssize_t *p = va_arg(*p_va, Py_ssize_t *); - Py_ssize_t ival = -1; - if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); - iobj = PyNumber_Index(arg); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); - *p = ival; - break; - } - case 'l': {/* long int */ - long *p = va_arg(*p_va, long *); - long ival; - if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); - ival = PyLong_AsLong(arg); - if (ival == -1 && PyErr_Occurred()) - return converterr("integer", 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 (PyLong_Check(arg)) - ival = PyLong_AsUnsignedLongMask(arg); - else - return converterr("integer", arg, msgbuf, bufsize); - *p = ival; - break; - } + const char *format = *p_format; + char c = *format++; + PyObject *uarg; + + 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", arg, msgbuf, bufsize); + ival = PyLong_AsLong(arg); + if (ival == -1 && PyErr_Occurred()) + return converterr("integer", arg, msgbuf, bufsize); + else if (ival < 0) { + PyErr_SetString(PyExc_OverflowError, + "unsigned byte integer is less than minimum"); + return converterr("integer", arg, msgbuf, bufsize); + } + else if (ival > UCHAR_MAX) { + PyErr_SetString(PyExc_OverflowError, + "unsigned byte integer is greater than maximum"); + return converterr("integer", 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", arg, msgbuf, bufsize); + ival = PyLong_AsUnsignedLongMask(arg); + if (ival == -1 && PyErr_Occurred()) + return converterr("integer", 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", arg, msgbuf, bufsize); + ival = PyLong_AsLong(arg); + if (ival == -1 && PyErr_Occurred()) + return converterr("integer", arg, msgbuf, bufsize); + else if (ival < SHRT_MIN) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is less than minimum"); + return converterr("integer", arg, msgbuf, bufsize); + } + else if (ival > SHRT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is greater than maximum"); + return converterr("integer", 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", arg, msgbuf, bufsize); + ival = PyLong_AsUnsignedLongMask(arg); + if (ival == -1 && PyErr_Occurred()) + return converterr("integer", 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", arg, msgbuf, bufsize); + ival = PyLong_AsLong(arg); + if (ival == -1 && PyErr_Occurred()) + return converterr("integer", arg, msgbuf, bufsize); + else if (ival > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "signed integer is greater than maximum"); + return converterr("integer", arg, msgbuf, bufsize); + } + else if (ival < INT_MIN) { + PyErr_SetString(PyExc_OverflowError, + "signed integer is less than minimum"); + return converterr("integer", 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", arg, msgbuf, bufsize); + ival = (unsigned int)PyLong_AsUnsignedLongMask(arg); + if (ival == (unsigned int)-1 && PyErr_Occurred()) + return converterr("integer", arg, msgbuf, bufsize); + else + *p = ival; + break; + } + + case 'n': /* Py_ssize_t */ + { + PyObject *iobj; + Py_ssize_t *p = va_arg(*p_va, Py_ssize_t *); + Py_ssize_t ival = -1; + if (float_argument_error(arg)) + return converterr("integer", arg, msgbuf, bufsize); + iobj = PyNumber_Index(arg); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) + return converterr("integer", arg, msgbuf, bufsize); + *p = ival; + break; + } + case 'l': {/* long int */ + long *p = va_arg(*p_va, long *); + long ival; + if (float_argument_error(arg)) + return converterr("integer", arg, msgbuf, bufsize); + ival = PyLong_AsLong(arg); + if (ival == -1 && PyErr_Occurred()) + return converterr("integer", 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 (PyLong_Check(arg)) + ival = PyLong_AsUnsignedLongMask(arg); + else + return converterr("integer", 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; - if (float_argument_warning(arg)) - return converterr("long", arg, msgbuf, bufsize); - ival = PyLong_AsLongLong(arg); - if (ival == (PY_LONG_LONG)-1 && PyErr_Occurred() ) { - return converterr("long", 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 (PyLong_Check(arg)) - ival = PyLong_AsUnsignedLongLongMask(arg); - else - return converterr("integer", arg, msgbuf, bufsize); - *p = ival; - break; - } + case 'L': {/* PY_LONG_LONG */ + PY_LONG_LONG *p = va_arg( *p_va, PY_LONG_LONG * ); + PY_LONG_LONG ival; + if (float_argument_warning(arg)) + return converterr("long", arg, msgbuf, bufsize); + ival = PyLong_AsLongLong(arg); + if (ival == (PY_LONG_LONG)-1 && PyErr_Occurred() ) { + return converterr("long", 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 (PyLong_Check(arg)) + ival = PyLong_AsUnsignedLongLongMask(arg); + else + return converterr("integer", 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", 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", arg, msgbuf, bufsize); - else - *p = dval; - break; - } - - 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", arg, msgbuf, bufsize); - else - *p = cval; - break; - } - - case 'c': {/* char */ - char *p = va_arg(*p_va, char *); - if (PyBytes_Check(arg) && PyBytes_Size(arg) == 1) - *p = PyBytes_AS_STRING(arg)[0]; - else - return converterr("a byte string of length 1", arg, msgbuf, bufsize); - break; - } - - case 'C': {/* unicode char */ - int *p = va_arg(*p_va, int *); - if (PyUnicode_Check(arg) && - PyUnicode_GET_SIZE(arg) == 1) - *p = PyUnicode_AS_UNICODE(arg)[0]; - else - return converterr("a unicode character", arg, msgbuf, bufsize); - break; - } - - /* XXX WAAAAH! 's', 'y', 'z', 'u', 'Z', 'e', 'w', 't' codes all - need to be cleaned up! */ - - case 's': {/* text string */ - if (*format == '*') { - Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *); - - if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - PyBuffer_FillInfo(p, arg, - PyBytes_AS_STRING(uarg), PyBytes_GET_SIZE(uarg), - 1, 0); - } - else { /* any buffer-like object */ - char *buf; - if (getbuffer(arg, p, &buf) < 0) - return converterr(buf, arg, msgbuf, bufsize); - } - if (addcleanup(p, freelist, cleanup_buffer)) { - return converterr( - "(cleanup problem)", - arg, msgbuf, bufsize); - } - format++; - } else if (*format == '#') { - void **p = (void **)va_arg(*p_va, char **); - FETCH_SIZE; - - if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - *p = PyBytes_AS_STRING(uarg); - STORE_SIZE(PyBytes_GET_SIZE(uarg)); - } - else { /* any buffer-like object */ - /* XXX Really? */ - 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 (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - *p = PyBytes_AS_STRING(uarg); - } - else - return converterr("string", arg, msgbuf, bufsize); - if ((Py_ssize_t) strlen(*p) != PyBytes_GET_SIZE(uarg)) - return converterr("string without null bytes", - arg, msgbuf, bufsize); - } - break; - } - - case 'y': {/* any buffer-like object, but not PyUnicode */ - void **p = (void **)va_arg(*p_va, char **); - char *buf; - Py_ssize_t count; - if (*format == '*') { - if (getbuffer(arg, (Py_buffer*)p, &buf) < 0) - return converterr(buf, arg, msgbuf, bufsize); - format++; - if (addcleanup(p, freelist, cleanup_buffer)) { - return converterr( - "(cleanup problem)", - arg, msgbuf, bufsize); - } - break; - } - count = convertbuffer(arg, p, &buf); - if (count < 0) - return converterr(buf, arg, msgbuf, bufsize); - else if (*format == '#') { - FETCH_SIZE; - STORE_SIZE(count); - format++; - } - break; - } - - case 'z': {/* like 's' or 's#', but None is okay, stored as NULL */ - if (*format == '*') { - Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *); - - if (arg == Py_None) - PyBuffer_FillInfo(p, NULL, NULL, 0, 1, 0); - else if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - PyBuffer_FillInfo(p, arg, - PyBytes_AS_STRING(uarg), PyBytes_GET_SIZE(uarg), - 1, 0); - } - else { /* any buffer-like object */ - char *buf; - if (getbuffer(arg, p, &buf) < 0) - return converterr(buf, arg, msgbuf, bufsize); - } - if (addcleanup(p, freelist, cleanup_buffer)) { - return converterr( - "(cleanup problem)", - arg, msgbuf, bufsize); - } - format++; - } else 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 (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - *p = PyBytes_AS_STRING(uarg); - STORE_SIZE(PyBytes_GET_SIZE(uarg)); - } - else { /* any buffer-like object */ - /* XXX Really? */ - 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 **); - uarg = NULL; - - if (arg == Py_None) - *p = 0; - else if (PyBytes_Check(arg)) { - /* Enable null byte check below */ - uarg = arg; - *p = PyBytes_AS_STRING(arg); - } - else if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - *p = PyBytes_AS_STRING(uarg); - } - else - return converterr("string or None", - arg, msgbuf, bufsize); - if (*format == '#') { - FETCH_SIZE; - assert(0); /* XXX redundant with if-case */ - if (arg == Py_None) { - STORE_SIZE(0); - } - else { - STORE_SIZE(PyBytes_Size(arg)); - } - format++; - } - else if (*p != NULL && uarg != NULL && - (Py_ssize_t) strlen(*p) != PyBytes_GET_SIZE(uarg)) - return converterr( - "string without null bytes or None", - arg, msgbuf, bufsize); - } - break; - } - - case 'Z': {/* unicode, may be NULL (None) */ - if (*format == '#') { /* any buffer-like object */ - Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); - FETCH_SIZE; - - if (arg == Py_None) { - *p = 0; - STORE_SIZE(0); - } - else if (PyUnicode_Check(arg)) { - *p = PyUnicode_AS_UNICODE(arg); - STORE_SIZE(PyUnicode_GET_SIZE(arg)); - } - format++; - } else { - Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); - - if (arg == Py_None) - *p = 0; - else if (PyUnicode_Check(arg)) - *p = PyUnicode_AS_UNICODE(arg); - else - return converterr("string or None", - arg, msgbuf, bufsize); - } - break; - } - - case 'e': {/* encoded string */ - char **buffer; - const char *encoding; - PyObject *s; - int recode_strings; - Py_ssize_t size; - const char *ptr; - - /* Get 'e' parameter: the encoding name */ - encoding = (const char *)va_arg(*p_va, const char *); - if (encoding == NULL) - encoding = PyUnicode_GetDefaultEncoding(); - - /* 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 && - (PyBytes_Check(arg) || PyByteArray_Check(arg))) { - s = arg; - Py_INCREF(s); - if (PyObject_AsCharBuffer(s, &ptr, &size) < 0) - return converterr("(AsCharBuffer failed)", - arg, msgbuf, bufsize); - } - else { - 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 (!PyBytes_Check(s)) { - Py_DECREF(s); - return converterr( - "(encoder failed to return bytes)", - arg, msgbuf, bufsize); - } - size = PyBytes_GET_SIZE(s); - ptr = PyBytes_AS_STRING(s); - if (ptr == NULL) - ptr = ""; - } - - /* 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, cleanup_ptr)) { - 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, ptr, 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(ptr) != 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, cleanup_ptr)) { - Py_DECREF(s); - return converterr("(cleanup problem)", - arg, msgbuf, bufsize); - } - memcpy(*buffer, ptr, size+1); - } - Py_DECREF(s); - break; - } - - case 'u': {/* raw unicode buffer (Py_UNICODE *) */ - Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); - if (!PyUnicode_Check(arg)) - return converterr("str", arg, msgbuf, bufsize); - *p = PyUnicode_AS_UNICODE(arg); - if (*format == '#') { /* store pointer and size */ - FETCH_SIZE; - STORE_SIZE(PyUnicode_GET_SIZE(arg)); - format++; - } - break; - } - - case 'S': { /* PyBytes object */ - PyObject **p = va_arg(*p_va, PyObject **); - if (PyBytes_Check(arg)) - *p = arg; - else - return converterr("bytes", arg, msgbuf, bufsize); - break; - } - - case 'Y': { /* PyByteArray object */ - PyObject **p = va_arg(*p_va, PyObject **); - if (PyByteArray_Check(arg)) - *p = arg; - else - return converterr("buffer", arg, msgbuf, bufsize); - break; - } - - case 'U': { /* PyUnicode object */ - PyObject **p = va_arg(*p_va, PyObject **); - if (PyUnicode_Check(arg)) - *p = arg; - else - return converterr("str", arg, msgbuf, bufsize); - break; - } - - 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 *); - int res; - format++; - if (! (res = (*convert)(arg, addr))) - return converterr("(unspecified)", - arg, msgbuf, bufsize); - if (res == Py_CLEANUP_SUPPORTED && - addcleanup_convert(addr, freelist, convert) == -1) - return converterr("(cleanup problem)", - 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; - Py_ssize_t count; - int temp=-1; - Py_buffer view; - - if (pb && pb->bf_releasebuffer && *format != '*') - /* Buffer must be released, yet caller does not use - the Py_buffer protocol. */ - return converterr("pinned buffer", arg, msgbuf, bufsize); - - - if (pb && pb->bf_getbuffer && *format == '*') { - /* Caller is interested in Py_buffer, and the object - supports it directly. */ - format++; - if (PyObject_GetBuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) { - PyErr_Clear(); - return converterr("read-write buffer", arg, msgbuf, bufsize); - } - if (addcleanup(p, freelist, cleanup_buffer)) { - return converterr( - "(cleanup problem)", - arg, msgbuf, bufsize); - } - if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) - return converterr("contiguous buffer", arg, msgbuf, bufsize); - break; - } - - /* Here we have processed w*, only w and w# remain. */ - if (pb == NULL || - pb->bf_getbuffer == NULL || - ((temp = PyObject_GetBuffer(arg, &view, - PyBUF_SIMPLE)) != 0) || - view.readonly == 1) { - if (temp==0) { - PyBuffer_Release(&view); - } - return converterr("single-segment read-write buffer", - arg, msgbuf, bufsize); + case 'f': {/* float */ + float *p = va_arg(*p_va, float *); + double dval = PyFloat_AsDouble(arg); + if (PyErr_Occurred()) + return converterr("float", 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", arg, msgbuf, bufsize); + else + *p = dval; + break; + } + + 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", arg, msgbuf, bufsize); + else + *p = cval; + break; + } + + case 'c': {/* char */ + char *p = va_arg(*p_va, char *); + if (PyBytes_Check(arg) && PyBytes_Size(arg) == 1) + *p = PyBytes_AS_STRING(arg)[0]; + else + return converterr("a byte string of length 1", arg, msgbuf, bufsize); + break; + } + + case 'C': {/* unicode char */ + int *p = va_arg(*p_va, int *); + if (PyUnicode_Check(arg) && + PyUnicode_GET_SIZE(arg) == 1) + *p = PyUnicode_AS_UNICODE(arg)[0]; + else + return converterr("a unicode character", arg, msgbuf, bufsize); + break; + } + + /* XXX WAAAAH! 's', 'y', 'z', 'u', 'Z', 'e', 'w', 't' codes all + need to be cleaned up! */ + + case 's': {/* text string */ + if (*format == '*') { + Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *); + + if (PyUnicode_Check(arg)) { + uarg = UNICODE_DEFAULT_ENCODING(arg); + if (uarg == NULL) + return converterr(CONV_UNICODE, + arg, msgbuf, bufsize); + PyBuffer_FillInfo(p, arg, + PyBytes_AS_STRING(uarg), PyBytes_GET_SIZE(uarg), + 1, 0); + } + else { /* any buffer-like object */ + char *buf; + if (getbuffer(arg, p, &buf) < 0) + return converterr(buf, arg, msgbuf, bufsize); + } + if (addcleanup(p, freelist, cleanup_buffer)) { + return converterr( + "(cleanup problem)", + arg, msgbuf, bufsize); + } + format++; + } else if (*format == '#') { + void **p = (void **)va_arg(*p_va, char **); + FETCH_SIZE; + + if (PyUnicode_Check(arg)) { + uarg = UNICODE_DEFAULT_ENCODING(arg); + if (uarg == NULL) + return converterr(CONV_UNICODE, + arg, msgbuf, bufsize); + *p = PyBytes_AS_STRING(uarg); + STORE_SIZE(PyBytes_GET_SIZE(uarg)); + } + else { /* any buffer-like object */ + /* XXX Really? */ + 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 (PyUnicode_Check(arg)) { + uarg = UNICODE_DEFAULT_ENCODING(arg); + if (uarg == NULL) + return converterr(CONV_UNICODE, + arg, msgbuf, bufsize); + *p = PyBytes_AS_STRING(uarg); + } + else + return converterr("string", arg, msgbuf, bufsize); + if ((Py_ssize_t) strlen(*p) != PyBytes_GET_SIZE(uarg)) + return converterr("string without null bytes", + arg, msgbuf, bufsize); + } + break; + } + + case 'y': {/* any buffer-like object, but not PyUnicode */ + void **p = (void **)va_arg(*p_va, char **); + char *buf; + Py_ssize_t count; + if (*format == '*') { + if (getbuffer(arg, (Py_buffer*)p, &buf) < 0) + return converterr(buf, arg, msgbuf, bufsize); + format++; + if (addcleanup(p, freelist, cleanup_buffer)) { + return converterr( + "(cleanup problem)", + arg, msgbuf, bufsize); + } + break; + } + count = convertbuffer(arg, p, &buf); + if (count < 0) + return converterr(buf, arg, msgbuf, bufsize); + else if (*format == '#') { + FETCH_SIZE; + STORE_SIZE(count); + format++; + } + break; + } + + case 'z': {/* like 's' or 's#', but None is okay, stored as NULL */ + if (*format == '*') { + Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *); + + if (arg == Py_None) + PyBuffer_FillInfo(p, NULL, NULL, 0, 1, 0); + else if (PyUnicode_Check(arg)) { + uarg = UNICODE_DEFAULT_ENCODING(arg); + if (uarg == NULL) + return converterr(CONV_UNICODE, + arg, msgbuf, bufsize); + PyBuffer_FillInfo(p, arg, + PyBytes_AS_STRING(uarg), PyBytes_GET_SIZE(uarg), + 1, 0); + } + else { /* any buffer-like object */ + char *buf; + if (getbuffer(arg, p, &buf) < 0) + return converterr(buf, arg, msgbuf, bufsize); + } + if (addcleanup(p, freelist, cleanup_buffer)) { + return converterr( + "(cleanup problem)", + arg, msgbuf, bufsize); + } + format++; + } else 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 (PyUnicode_Check(arg)) { + uarg = UNICODE_DEFAULT_ENCODING(arg); + if (uarg == NULL) + return converterr(CONV_UNICODE, + arg, msgbuf, bufsize); + *p = PyBytes_AS_STRING(uarg); + STORE_SIZE(PyBytes_GET_SIZE(uarg)); + } + else { /* any buffer-like object */ + /* XXX Really? */ + 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 **); + uarg = NULL; + + if (arg == Py_None) + *p = 0; + else if (PyBytes_Check(arg)) { + /* Enable null byte check below */ + uarg = arg; + *p = PyBytes_AS_STRING(arg); + } + else if (PyUnicode_Check(arg)) { + uarg = UNICODE_DEFAULT_ENCODING(arg); + if (uarg == NULL) + return converterr(CONV_UNICODE, + arg, msgbuf, bufsize); + *p = PyBytes_AS_STRING(uarg); + } + else + return converterr("string or None", + arg, msgbuf, bufsize); + if (*format == '#') { + FETCH_SIZE; + assert(0); /* XXX redundant with if-case */ + if (arg == Py_None) { + STORE_SIZE(0); + } + else { + STORE_SIZE(PyBytes_Size(arg)); + } + format++; + } + else if (*p != NULL && uarg != NULL && + (Py_ssize_t) strlen(*p) != PyBytes_GET_SIZE(uarg)) + return converterr( + "string without null bytes or None", + arg, msgbuf, bufsize); + } + break; + } + + case 'Z': {/* unicode, may be NULL (None) */ + if (*format == '#') { /* any buffer-like object */ + Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); + FETCH_SIZE; + + if (arg == Py_None) { + *p = 0; + STORE_SIZE(0); + } + else if (PyUnicode_Check(arg)) { + *p = PyUnicode_AS_UNICODE(arg); + STORE_SIZE(PyUnicode_GET_SIZE(arg)); + } + format++; + } else { + Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); + + if (arg == Py_None) + *p = 0; + else if (PyUnicode_Check(arg)) + *p = PyUnicode_AS_UNICODE(arg); + else + return converterr("string or None", + arg, msgbuf, bufsize); + } + break; + } + + case 'e': {/* encoded string */ + char **buffer; + const char *encoding; + PyObject *s; + int recode_strings; + Py_ssize_t size; + const char *ptr; + + /* Get 'e' parameter: the encoding name */ + encoding = (const char *)va_arg(*p_va, const char *); + if (encoding == NULL) + encoding = PyUnicode_GetDefaultEncoding(); + + /* 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 && + (PyBytes_Check(arg) || PyByteArray_Check(arg))) { + s = arg; + Py_INCREF(s); + if (PyObject_AsCharBuffer(s, &ptr, &size) < 0) + return converterr("(AsCharBuffer failed)", + arg, msgbuf, bufsize); + } + else { + 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 (!PyBytes_Check(s)) { + Py_DECREF(s); + return converterr( + "(encoder failed to return bytes)", + arg, msgbuf, bufsize); + } + size = PyBytes_GET_SIZE(s); + ptr = PyBytes_AS_STRING(s); + if (ptr == NULL) + ptr = ""; + } + + /* 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, cleanup_ptr)) { + 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, ptr, 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(ptr) != 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, cleanup_ptr)) { + Py_DECREF(s); + return converterr("(cleanup problem)", + arg, msgbuf, bufsize); + } + memcpy(*buffer, ptr, size+1); + } + Py_DECREF(s); + break; + } + + case 'u': {/* raw unicode buffer (Py_UNICODE *) */ + Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); + if (!PyUnicode_Check(arg)) + return converterr("str", arg, msgbuf, bufsize); + *p = PyUnicode_AS_UNICODE(arg); + if (*format == '#') { /* store pointer and size */ + FETCH_SIZE; + STORE_SIZE(PyUnicode_GET_SIZE(arg)); + format++; + } + break; + } + + case 'S': { /* PyBytes object */ + PyObject **p = va_arg(*p_va, PyObject **); + if (PyBytes_Check(arg)) + *p = arg; + else + return converterr("bytes", arg, msgbuf, bufsize); + break; + } + + case 'Y': { /* PyByteArray object */ + PyObject **p = va_arg(*p_va, PyObject **); + if (PyByteArray_Check(arg)) + *p = arg; + else + return converterr("buffer", arg, msgbuf, bufsize); + break; + } + + case 'U': { /* PyUnicode object */ + PyObject **p = va_arg(*p_va, PyObject **); + if (PyUnicode_Check(arg)) + *p = arg; + else + return converterr("str", arg, msgbuf, bufsize); + break; + } + + 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 *); + int res; + format++; + if (! (res = (*convert)(arg, addr))) + return converterr("(unspecified)", + arg, msgbuf, bufsize); + if (res == Py_CLEANUP_SUPPORTED && + addcleanup_convert(addr, freelist, convert) == -1) + return converterr("(cleanup problem)", + 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; + Py_ssize_t count; + int temp=-1; + Py_buffer view; - if ((count = view.len) < 0) - return converterr("(unspecified)", arg, msgbuf, bufsize); - *p = view.buf; - if (*format == '#') { - FETCH_SIZE; - STORE_SIZE(count); - format++; - } - break; - } - - /*TEO: This can be eliminated --- here only for backward - compatibility */ - case 't': { /* 8-bit character buffer, read-only access */ - char **p = va_arg(*p_va, char **); - PyBufferProcs *pb = arg->ob_type->tp_as_buffer; - Py_ssize_t count; - Py_buffer view; - - if (*format++ != '#') - return converterr( - "invalid use of 't' format character", - arg, msgbuf, bufsize); - if (pb == NULL || pb->bf_getbuffer == NULL) - return converterr( - "bytes or read-only character buffer", - arg, msgbuf, bufsize); - - if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) != 0) - return converterr("string or single-segment read-only buffer", - arg, msgbuf, bufsize); - - count = view.len; - *p = view.buf; - if (pb->bf_releasebuffer) - return converterr( - "string or pinned buffer", - arg, msgbuf, bufsize); - - PyBuffer_Release(&view); - - if (count < 0) - return converterr("(unspecified)", arg, msgbuf, bufsize); - { - FETCH_SIZE; - STORE_SIZE(count); - } - break; - } - - default: - return converterr("impossible", arg, msgbuf, bufsize); - - } - - *p_format = format; - return NULL; + if (pb && pb->bf_releasebuffer && *format != '*') + /* Buffer must be released, yet caller does not use + the Py_buffer protocol. */ + return converterr("pinned buffer", arg, msgbuf, bufsize); + + + if (pb && pb->bf_getbuffer && *format == '*') { + /* Caller is interested in Py_buffer, and the object + supports it directly. */ + format++; + if (PyObject_GetBuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) { + PyErr_Clear(); + return converterr("read-write buffer", arg, msgbuf, bufsize); + } + if (addcleanup(p, freelist, cleanup_buffer)) { + return converterr( + "(cleanup problem)", + arg, msgbuf, bufsize); + } + if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) + return converterr("contiguous buffer", arg, msgbuf, bufsize); + break; + } + + /* Here we have processed w*, only w and w# remain. */ + if (pb == NULL || + pb->bf_getbuffer == NULL || + ((temp = PyObject_GetBuffer(arg, &view, + PyBUF_SIMPLE)) != 0) || + view.readonly == 1) { + if (temp==0) { + PyBuffer_Release(&view); + } + return converterr("single-segment read-write buffer", + arg, msgbuf, bufsize); + } + + if ((count = view.len) < 0) + return converterr("(unspecified)", arg, msgbuf, bufsize); + *p = view.buf; + if (*format == '#') { + FETCH_SIZE; + STORE_SIZE(count); + format++; + } + break; + } + + /*TEO: This can be eliminated --- here only for backward + compatibility */ + case 't': { /* 8-bit character buffer, read-only access */ + char **p = va_arg(*p_va, char **); + PyBufferProcs *pb = arg->ob_type->tp_as_buffer; + Py_ssize_t count; + Py_buffer view; + + if (*format++ != '#') + return converterr( + "invalid use of 't' format character", + arg, msgbuf, bufsize); + if (pb == NULL || pb->bf_getbuffer == NULL) + return converterr( + "bytes or read-only character buffer", + arg, msgbuf, bufsize); + + if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) != 0) + return converterr("string or single-segment read-only buffer", + arg, msgbuf, bufsize); + + count = view.len; + *p = view.buf; + if (pb->bf_releasebuffer) + return converterr( + "string or pinned buffer", + arg, msgbuf, bufsize); + + PyBuffer_Release(&view); + + if (count < 0) + return converterr("(unspecified)", arg, msgbuf, bufsize); + { + FETCH_SIZE; + STORE_SIZE(count); + } + break; + } + + default: + return converterr("impossible", 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; - Py_buffer view; - - *errmsg = NULL; - *p = NULL; - if (pb == NULL || - pb->bf_getbuffer == NULL || - pb->bf_releasebuffer != NULL) { - *errmsg = "bytes or read-only buffer"; - return -1; - } - - if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) != 0) { - *errmsg = "bytes or single-segment read-only buffer"; - return -1; - } - count = view.len; - *p = view.buf; - PyBuffer_Release(&view); - return count; + PyBufferProcs *pb = arg->ob_type->tp_as_buffer; + Py_ssize_t count; + Py_buffer view; + + *errmsg = NULL; + *p = NULL; + if (pb == NULL || + pb->bf_getbuffer == NULL || + pb->bf_releasebuffer != NULL) { + *errmsg = "bytes or read-only buffer"; + return -1; + } + + if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) != 0) { + *errmsg = "bytes or single-segment read-only buffer"; + return -1; + } + count = view.len; + *p = view.buf; + PyBuffer_Release(&view); + return count; } /* XXX for 3.x, getbuffer and convertbuffer can probably @@ -1460,32 +1460,32 @@ convertbuffer(PyObject *arg, void **p, char **errmsg) static int getbuffer(PyObject *arg, Py_buffer *view, char **errmsg) { - void *buf; - Py_ssize_t count; - PyBufferProcs *pb = arg->ob_type->tp_as_buffer; - if (pb == NULL) { - *errmsg = "bytes or buffer"; - return -1; - } - if (pb->bf_getbuffer) { - if (PyObject_GetBuffer(arg, view, 0) < 0) { - *errmsg = "convertible to a buffer"; - return -1; - } - if (!PyBuffer_IsContiguous(view, 'C')) { - *errmsg = "contiguous buffer"; - return -1; - } - return 0; - } - - count = convertbuffer(arg, &buf, errmsg); - if (count < 0) { - *errmsg = "convertible to a buffer"; - return count; - } - PyBuffer_FillInfo(view, NULL, buf, count, 1, 0); - return 0; + void *buf; + Py_ssize_t count; + PyBufferProcs *pb = arg->ob_type->tp_as_buffer; + if (pb == NULL) { + *errmsg = "bytes or buffer"; + return -1; + } + if (pb->bf_getbuffer) { + if (PyObject_GetBuffer(arg, view, 0) < 0) { + *errmsg = "convertible to a buffer"; + return -1; + } + if (!PyBuffer_IsContiguous(view, 'C')) { + *errmsg = "contiguous buffer"; + return -1; + } + return 0; + } + + count = convertbuffer(arg, &buf, errmsg); + if (count < 0) { + *errmsg = "convertible to a buffer"; + return count; + } + PyBuffer_FillInfo(view, NULL, buf, count, 1, 0); + return 0; } /* Support for keyword arguments donated by @@ -1494,51 +1494,51 @@ getbuffer(PyObject *arg, Py_buffer *view, char **errmsg) /* Return false (0) for error, else true. */ int PyArg_ParseTupleAndKeywords(PyObject *args, - PyObject *keywords, - const char *format, - char **kwlist, ...) + 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 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, ...) + 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 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; } @@ -1548,422 +1548,422 @@ PyArg_VaParseTupleAndKeywords(PyObject *args, 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; - } + 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)); + memcpy(lva, va, sizeof(va_list)); #else #ifdef __va_copy - __va_copy(lva, va); + __va_copy(lva, va); #else - lva = va; + lva = va; #endif #endif - retval = vgetargskeywords(args, keywords, format, kwlist, &lva, 0); - return retval; + 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) + 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; - } + 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)); + memcpy(lva, va, sizeof(va_list)); #else #ifdef __va_copy - __va_copy(lva, va); + __va_copy(lva, va); #else - lva = va; + lva = va; #endif #endif - retval = vgetargskeywords(args, keywords, format, - kwlist, &lva, FLAG_SIZE_T); - return retval; + retval = vgetargskeywords(args, keywords, format, + kwlist, &lva, FLAG_SIZE_T); + return retval; } int PyArg_ValidateKeywordArguments(PyObject *kwargs) { - if (!PyDict_CheckExact(kwargs)) { - PyErr_BadInternalCall(); - return 0; - } - if (!_PyDict_HasOnlyStringKeys(kwargs)) { - PyErr_SetString(PyExc_TypeError, - "keyword arguments must be strings"); - return 0; - } - return 1; + if (!PyDict_CheckExact(kwargs)) { + PyErr_BadInternalCall(); + return 0; + } + if (!_PyDict_HasOnlyStringKeys(kwargs)) { + PyErr_SetString(PyExc_TypeError, + "keyword arguments must be strings"); + return 0; + } + return 1; } #define IS_END_OF_FORMAT(c) (c == '\0' || c == ';' || c == ':') static int vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, - char **kwlist, va_list *p_va, int flags) + char **kwlist, va_list *p_va, int flags) { - char msgbuf[512]; - int levels[32]; - const char *fname, *msg, *custom_msg, *keyword; - int min = INT_MAX; - int i, len, nargs, nkeywords; - PyObject *freelist = NULL, *current_arg; - - assert(args != NULL && PyTuple_Check(args)); - assert(keywords == NULL || PyDict_Check(keywords)); - assert(format != NULL); - assert(kwlist != NULL); - assert(p_va != NULL); - - /* grab the function name or custom error msg first (mutually exclusive) */ - fname = strchr(format, ':'); - if (fname) { - fname++; - custom_msg = NULL; - } - else { - custom_msg = strchr(format,';'); - if (custom_msg) - custom_msg++; - } - - /* scan kwlist and get greatest possible nbr of args */ - for (len=0; kwlist[len]; len++) - continue; - - nargs = PyTuple_GET_SIZE(args); - nkeywords = (keywords == NULL) ? 0 : PyDict_Size(keywords); - if (nargs + nkeywords > len) { - PyErr_Format(PyExc_TypeError, "%s%s takes at most %d " - "argument%s (%d given)", - (fname == NULL) ? "function" : fname, - (fname == NULL) ? "" : "()", - len, - (len == 1) ? "" : "s", - nargs + nkeywords); - return 0; - } - - /* convert tuple args and keyword args in same loop, using kwlist to drive process */ - for (i = 0; i < len; i++) { - keyword = kwlist[i]; - if (*format == '|') { - min = i; - format++; - } - if (IS_END_OF_FORMAT(*format)) { - PyErr_Format(PyExc_RuntimeError, - "More keyword list entries (%d) than " - "format specifiers (%d)", len, i); - return cleanreturn(0, freelist); - } - current_arg = NULL; - if (nkeywords) { - current_arg = PyDict_GetItemString(keywords, keyword); - } - if (current_arg) { - --nkeywords; - if (i < nargs) { - /* arg present in tuple and in dict */ - PyErr_Format(PyExc_TypeError, - "Argument given by name ('%s') " - "and position (%d)", - keyword, i+1); - return cleanreturn(0, freelist); - } - } - else if (nkeywords && PyErr_Occurred()) - return cleanreturn(0, freelist); - else if (i < nargs) - current_arg = PyTuple_GET_ITEM(args, i); - - if (current_arg) { - msg = convertitem(current_arg, &format, p_va, flags, - levels, msgbuf, sizeof(msgbuf), &freelist); - if (msg) { - seterror(i+1, msg, levels, fname, custom_msg); - return cleanreturn(0, freelist); - } - continue; - } - - if (i < min) { - PyErr_Format(PyExc_TypeError, "Required argument " - "'%s' (pos %d) not found", - keyword, i+1); - return cleanreturn(0, freelist); - } - /* current code reports success when all required args - * fulfilled and no keyword args left, with no further - * validation. XXX Maybe skip this in debug build ? - */ - if (!nkeywords) - return cleanreturn(1, freelist); - - /* We are into optional args, skip thru to any remaining - * keyword args */ - msg = skipitem(&format, p_va, flags); - if (msg) { - PyErr_Format(PyExc_RuntimeError, "%s: '%s'", msg, - format); - return cleanreturn(0, freelist); - } - } - - if (!IS_END_OF_FORMAT(*format) && *format != '|') { - PyErr_Format(PyExc_RuntimeError, - "more argument specifiers than keyword list entries " - "(remaining format:'%s')", format); - 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 (!PyUnicode_Check(key)) { - PyErr_SetString(PyExc_TypeError, - "keywords must be strings"); - return cleanreturn(0, freelist); - } - ks = _PyUnicode_AsString(key); - for (i = 0; i < len; 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); + char msgbuf[512]; + int levels[32]; + const char *fname, *msg, *custom_msg, *keyword; + int min = INT_MAX; + int i, len, nargs, nkeywords; + PyObject *freelist = NULL, *current_arg; + + assert(args != NULL && PyTuple_Check(args)); + assert(keywords == NULL || PyDict_Check(keywords)); + assert(format != NULL); + assert(kwlist != NULL); + assert(p_va != NULL); + + /* grab the function name or custom error msg first (mutually exclusive) */ + fname = strchr(format, ':'); + if (fname) { + fname++; + custom_msg = NULL; + } + else { + custom_msg = strchr(format,';'); + if (custom_msg) + custom_msg++; + } + + /* scan kwlist and get greatest possible nbr of args */ + for (len=0; kwlist[len]; len++) + continue; + + nargs = PyTuple_GET_SIZE(args); + nkeywords = (keywords == NULL) ? 0 : PyDict_Size(keywords); + if (nargs + nkeywords > len) { + PyErr_Format(PyExc_TypeError, "%s%s takes at most %d " + "argument%s (%d given)", + (fname == NULL) ? "function" : fname, + (fname == NULL) ? "" : "()", + len, + (len == 1) ? "" : "s", + nargs + nkeywords); + return 0; + } + + /* convert tuple args and keyword args in same loop, using kwlist to drive process */ + for (i = 0; i < len; i++) { + keyword = kwlist[i]; + if (*format == '|') { + min = i; + format++; + } + if (IS_END_OF_FORMAT(*format)) { + PyErr_Format(PyExc_RuntimeError, + "More keyword list entries (%d) than " + "format specifiers (%d)", len, i); + return cleanreturn(0, freelist); + } + current_arg = NULL; + if (nkeywords) { + current_arg = PyDict_GetItemString(keywords, keyword); + } + if (current_arg) { + --nkeywords; + if (i < nargs) { + /* arg present in tuple and in dict */ + PyErr_Format(PyExc_TypeError, + "Argument given by name ('%s') " + "and position (%d)", + keyword, i+1); + return cleanreturn(0, freelist); + } + } + else if (nkeywords && PyErr_Occurred()) + return cleanreturn(0, freelist); + else if (i < nargs) + current_arg = PyTuple_GET_ITEM(args, i); + + if (current_arg) { + msg = convertitem(current_arg, &format, p_va, flags, + levels, msgbuf, sizeof(msgbuf), &freelist); + if (msg) { + seterror(i+1, msg, levels, fname, custom_msg); + return cleanreturn(0, freelist); + } + continue; + } + + if (i < min) { + PyErr_Format(PyExc_TypeError, "Required argument " + "'%s' (pos %d) not found", + keyword, i+1); + return cleanreturn(0, freelist); + } + /* current code reports success when all required args + * fulfilled and no keyword args left, with no further + * validation. XXX Maybe skip this in debug build ? + */ + if (!nkeywords) + return cleanreturn(1, freelist); + + /* We are into optional args, skip thru to any remaining + * keyword args */ + msg = skipitem(&format, p_va, flags); + if (msg) { + PyErr_Format(PyExc_RuntimeError, "%s: '%s'", msg, + format); + return cleanreturn(0, freelist); + } + } + + if (!IS_END_OF_FORMAT(*format) && *format != '|') { + PyErr_Format(PyExc_RuntimeError, + "more argument specifiers than keyword list entries " + "(remaining format:'%s')", format); + 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 (!PyUnicode_Check(key)) { + PyErr_SetString(PyExc_TypeError, + "keywords must be strings"); + return cleanreturn(0, freelist); + } + ks = _PyUnicode_AsString(key); + for (i = 0; i < len; 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 */ + 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 */ + case 'L': /* PY_LONG_LONG */ + case 'K': /* PY_LONG_LONG sized bitfield */ #endif - case 'f': /* float */ - case 'd': /* double */ - case 'D': /* complex double */ - case 'c': /* char */ - case 'C': /* unicode 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 */ - case 'y': /* bytes */ - case 'u': /* unicode string */ - 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++; - } else if ((c == 's' || c == 'z' || c == 'y') && *format == '*') { - format++; - } - break; - } - - /* object codes */ - - case 'S': /* string object */ - case 'Y': /* string object */ - case 'U': /* unicode string object */ - { - (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 **); - } - 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; - } - - case '(': /* bypass tuple, not handled at all previously */ - { - char *msg; - for (;;) { - if (*format==')') - break; - if (IS_END_OF_FORMAT(*format)) - return "Unmatched left paren in format " - "string"; - msg = skipitem(&format, p_va, flags); - if (msg) - return msg; - } - format++; - break; - } - - case ')': - return "Unmatched right paren in format string"; - - default: + case 'f': /* float */ + case 'd': /* double */ + case 'D': /* complex double */ + case 'c': /* char */ + case 'C': /* unicode 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 */ + case 'y': /* bytes */ + case 'u': /* unicode string */ + 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++; + } else if ((c == 's' || c == 'z' || c == 'y') && *format == '*') { + format++; + } + break; + } + + /* object codes */ + + case 'S': /* string object */ + case 'Y': /* string object */ + case 'U': /* unicode string object */ + { + (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 **); + } + 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; + } + + case '(': /* bypass tuple, not handled at all previously */ + { + char *msg; + for (;;) { + if (*format==')') + break; + if (IS_END_OF_FORMAT(*format)) + return "Unmatched left paren in format " + "string"; + msg = skipitem(&format, p_va, flags); + if (msg) + return msg; + } + format++; + break; + } + + case ')': + return "Unmatched right paren in format string"; + + default: err: - return "impossible"; + return "impossible"; - } + } - *p_format = format; - return NULL; + *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; + Py_ssize_t i, l; + PyObject **o; + va_list vargs; #ifdef HAVE_STDARG_PROTOTYPES - va_start(vargs, max); + va_start(vargs, max); #else - va_start(vargs); + 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; + 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; } @@ -1975,18 +1975,18 @@ PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t m 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; + 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 }; diff --git a/Python/getcwd.c b/Python/getcwd.c index 967d484b35..4bedbd1f75 100644 --- a/Python/getcwd.c +++ b/Python/getcwd.c @@ -26,24 +26,24 @@ extern char *getwd(char *); char * getcwd(char *buf, int size) { - char localbuf[MAXPATHLEN+1]; - char *ret; - - if (size <= 0) { - errno = EINVAL; - return NULL; - } - ret = getwd(localbuf); - if (ret != NULL && strlen(localbuf) >= (size_t)size) { - errno = ERANGE; - return NULL; - } - if (ret == NULL) { - errno = EACCES; /* Most likely error */ - return NULL; - } - strncpy(buf, localbuf, size); - return buf; + char localbuf[MAXPATHLEN+1]; + char *ret; + + if (size <= 0) { + errno = EINVAL; + return NULL; + } + ret = getwd(localbuf); + if (ret != NULL && strlen(localbuf) >= (size_t)size) { + errno = ERANGE; + return NULL; + } + if (ret == NULL) { + errno = EACCES; /* Most likely error */ + return NULL; + } + strncpy(buf, localbuf, size); + return buf; } #else /* !HAVE_GETWD */ @@ -57,27 +57,27 @@ getcwd(char *buf, int size) char * getcwd(char *buf, int size) { - FILE *fp; - char *p; - int sts; - if (size <= 0) { - errno = EINVAL; - return NULL; - } - if ((fp = popen(PWD_CMD, "r")) == NULL) - return NULL; - if (fgets(buf, size, fp) == NULL || (sts = pclose(fp)) != 0) { - errno = EACCES; /* Most likely error */ - return NULL; - } - for (p = buf; *p != '\n'; p++) { - if (*p == '\0') { - errno = ERANGE; - return NULL; - } - } - *p = '\0'; - return buf; + FILE *fp; + char *p; + int sts; + if (size <= 0) { + errno = EINVAL; + return NULL; + } + if ((fp = popen(PWD_CMD, "r")) == NULL) + return NULL; + if (fgets(buf, size, fp) == NULL || (sts = pclose(fp)) != 0) { + errno = EACCES; /* Most likely error */ + return NULL; + } + for (p = buf; *p != '\n'; p++) { + if (*p == '\0') { + errno = ERANGE; + return NULL; + } + } + *p = '\0'; + return buf; } #endif /* !HAVE_GETWD */ diff --git a/Python/getopt.c b/Python/getopt.c index da9341f404..5147320af2 100644 --- a/Python/getopt.c +++ b/Python/getopt.c @@ -7,8 +7,8 @@ * * All Rights Reserved * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose and without fee is hereby granted, + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice, this permission notice and * the following disclaimer notice appear unmodified in all copies. * @@ -43,84 +43,84 @@ wchar_t *_PyOS_optarg = NULL; /* optional argument */ int _PyOS_GetOpt(int argc, wchar_t **argv, wchar_t *optstring) { - static wchar_t *opt_ptr = L""; - wchar_t *ptr; - wchar_t option; + static wchar_t *opt_ptr = L""; + wchar_t *ptr; + wchar_t option; - if (*opt_ptr == '\0') { + if (*opt_ptr == '\0') { - if (_PyOS_optind >= argc) - return -1; + if (_PyOS_optind >= argc) + return -1; #ifdef MS_WINDOWS - else if (wcscmp(argv[_PyOS_optind], L"/?") == 0) { - ++_PyOS_optind; - return 'h'; - } + else if (wcscmp(argv[_PyOS_optind], L"/?") == 0) { + ++_PyOS_optind; + return 'h'; + } #endif - else if (argv[_PyOS_optind][0] != L'-' || - argv[_PyOS_optind][1] == L'\0' /* lone dash */ ) - return -1; - - else if (wcscmp(argv[_PyOS_optind], L"--") == 0) { - ++_PyOS_optind; - return -1; - } - - else if (wcscmp(argv[_PyOS_optind], L"--help") == 0) { - ++_PyOS_optind; - return 'h'; - } - - else if (wcscmp(argv[_PyOS_optind], L"--version") == 0) { - ++_PyOS_optind; - return 'V'; - } - - - opt_ptr = &argv[_PyOS_optind++][1]; - } - - if ( (option = *opt_ptr++) == L'\0') - return -1; - - if (option == 'J') { - fprintf(stderr, "-J is reserved for Jython\n"); - return '_'; - } - - if (option == 'X') { - fprintf(stderr, - "-X is reserved for implementation-specific arguments\n"); - return '_'; - } - - if ((ptr = wcschr(optstring, option)) == NULL) { - if (_PyOS_opterr) - fprintf(stderr, "Unknown option: -%c\n", (char)option); - - return '_'; - } - - if (*(ptr + 1) == L':') { - if (*opt_ptr != L'\0') { - _PyOS_optarg = opt_ptr; - opt_ptr = L""; - } - - else { - if (_PyOS_optind >= argc) { - if (_PyOS_opterr) - fprintf(stderr, - "Argument expected for the -%c option\n", (char)option); - return '_'; - } - - _PyOS_optarg = argv[_PyOS_optind++]; - } - } - - return option; + else if (argv[_PyOS_optind][0] != L'-' || + argv[_PyOS_optind][1] == L'\0' /* lone dash */ ) + return -1; + + else if (wcscmp(argv[_PyOS_optind], L"--") == 0) { + ++_PyOS_optind; + return -1; + } + + else if (wcscmp(argv[_PyOS_optind], L"--help") == 0) { + ++_PyOS_optind; + return 'h'; + } + + else if (wcscmp(argv[_PyOS_optind], L"--version") == 0) { + ++_PyOS_optind; + return 'V'; + } + + + opt_ptr = &argv[_PyOS_optind++][1]; + } + + if ( (option = *opt_ptr++) == L'\0') + return -1; + + if (option == 'J') { + fprintf(stderr, "-J is reserved for Jython\n"); + return '_'; + } + + if (option == 'X') { + fprintf(stderr, + "-X is reserved for implementation-specific arguments\n"); + return '_'; + } + + if ((ptr = wcschr(optstring, option)) == NULL) { + if (_PyOS_opterr) + fprintf(stderr, "Unknown option: -%c\n", (char)option); + + return '_'; + } + + if (*(ptr + 1) == L':') { + if (*opt_ptr != L'\0') { + _PyOS_optarg = opt_ptr; + opt_ptr = L""; + } + + else { + if (_PyOS_optind >= argc) { + if (_PyOS_opterr) + fprintf(stderr, + "Argument expected for the -%c option\n", (char)option); + return '_'; + } + + _PyOS_optarg = argv[_PyOS_optind++]; + } + } + + return option; } #ifdef __cplusplus diff --git a/Python/import.c b/Python/import.c index 1cddcb0658..923888d5df 100644 --- a/Python/import.c +++ b/Python/import.c @@ -76,31 +76,31 @@ typedef unsigned short mode_t; 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) + storing constants that should have been removed) Python 2.5c2: 62131 (fix wrong code: for x, in ... in listcomp/genexp) Python 2.6a0: 62151 (peephole optimizations and STORE_MAP opcode) Python 2.6a1: 62161 (WITH_CLEANUP optimization) Python 3000: 3000 - 3010 (removed UNARY_CONVERT) - 3020 (added BUILD_SET) - 3030 (added keyword-only parameters) - 3040 (added signature annotations) - 3050 (print becomes a function) - 3060 (PEP 3115 metaclass syntax) - 3061 (string literals become unicode) - 3071 (PEP 3109 raise changes) - 3081 (PEP 3137 make __file__ and __name__ unicode) - 3091 (kill str8 interning) - 3101 (merge from 2.6a0, see 62151) - 3103 (__file__ points to source file) + 3010 (removed UNARY_CONVERT) + 3020 (added BUILD_SET) + 3030 (added keyword-only parameters) + 3040 (added signature annotations) + 3050 (print becomes a function) + 3060 (PEP 3115 metaclass syntax) + 3061 (string literals become unicode) + 3071 (PEP 3109 raise changes) + 3081 (PEP 3137 make __file__ and __name__ unicode) + 3091 (kill str8 interning) + 3101 (merge from 2.6a0, see 62151) + 3103 (__file__ points to source file) Python 3.0a4: 3111 (WITH_CLEANUP optimization). Python 3.0a5: 3131 (lexical exception stacking, including POP_EXCEPT) Python 3.1a0: 3141 (optimize list, set and dict comprehensions: - change LIST_APPEND and SET_ADD, add MAP_ADD) + change LIST_APPEND and SET_ADD, add MAP_ADD) Python 3.1a0: 3151 (optimize conditional branches: - introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE) + introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE) Python 3.2a0: 3160 (add SETUP_WITH) - tag: cpython-32 + tag: cpython-32 */ /* If you change MAGIC, you must change TAG and you must insert the old value @@ -128,12 +128,12 @@ struct _inittab *PyImport_Inittab = _PyImport_Inittab; struct filedescr * _PyImport_Filetab = NULL; static const struct filedescr _PyImport_StandardFiletab[] = { - {".py", "U", PY_SOURCE}, + {".py", "U", PY_SOURCE}, #ifdef MS_WINDOWS - {".pyw", "U", PY_SOURCE}, + {".pyw", "U", PY_SOURCE}, #endif - {".pyc", "rb", PY_COMPILED}, - {0, 0} + {".pyc", "rb", PY_COMPILED}, + {0, 0} }; @@ -142,119 +142,119 @@ static const struct filedescr _PyImport_StandardFiletab[] = { void _PyImport_Init(void) { - const struct filedescr *scan; - struct filedescr *filetab; - int countD = 0; - int countS = 0; + const struct filedescr *scan; + struct filedescr *filetab; + int countD = 0; + int countS = 0; - /* prepare _PyImport_Filetab: copy entries from - _PyImport_DynLoadFiletab and _PyImport_StandardFiletab. - */ + /* prepare _PyImport_Filetab: copy entries from + _PyImport_DynLoadFiletab and _PyImport_StandardFiletab. + */ #ifdef HAVE_DYNAMIC_LOADING - for (scan = _PyImport_DynLoadFiletab; scan->suffix != NULL; ++scan) - ++countD; + for (scan = _PyImport_DynLoadFiletab; scan->suffix != NULL; ++scan) + ++countD; #endif - 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."); + 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."); #ifdef HAVE_DYNAMIC_LOADING - memcpy(filetab, _PyImport_DynLoadFiletab, - countD * sizeof(struct filedescr)); + memcpy(filetab, _PyImport_DynLoadFiletab, + countD * sizeof(struct filedescr)); #endif - memcpy(filetab + countD, _PyImport_StandardFiletab, - countS * sizeof(struct filedescr)); - filetab[countD + countS].suffix = NULL; + memcpy(filetab + countD, _PyImport_StandardFiletab, + countS * sizeof(struct filedescr)); + filetab[countD + countS].suffix = NULL; - _PyImport_Filetab = filetab; + _PyImport_Filetab = filetab; - if (Py_OptimizeFlag) { - /* Replace ".pyc" with ".pyo" in _PyImport_Filetab */ - for (; filetab->suffix != NULL; filetab++) { - if (strcmp(filetab->suffix, ".pyc") == 0) - filetab->suffix = ".pyo"; - } - } + if (Py_OptimizeFlag) { + /* Replace ".pyc" with ".pyo" in _PyImport_Filetab */ + for (; filetab->suffix != NULL; filetab++) { + if (strcmp(filetab->suffix, ".pyc") == 0) + filetab->suffix = ".pyo"; + } + } } 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(&PyNullImporter_Type) < 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) { + PyObject *v, *path_hooks = NULL, *zimpimport; + int err = 0; + + /* adding sys.path_hooks and sys.path_importer_cache, setting up + zipimport */ + if (PyType_Ready(&PyNullImporter_Type) < 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); + 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; + Py_XDECREF(extensions); + extensions = NULL; + PyMem_DEL(_PyImport_Filetab); + _PyImport_Filetab = NULL; } @@ -273,42 +273,42 @@ static int import_lock_level = 0; void _PyImport_AcquireLock(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; + 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; } int _PyImport_ReleaseLock(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; + 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 @@ -319,10 +319,10 @@ _PyImport_ReleaseLock(void) void _PyImport_ReInitLock(void) { - if (import_lock != NULL) - import_lock = PyThread_allocate_lock(); - import_lock_thread = -1; - import_lock_level = 0; + if (import_lock != NULL) + import_lock = PyThread_allocate_lock(); + import_lock_thread = -1; + import_lock_level = 0; } #endif @@ -331,9 +331,9 @@ static PyObject * imp_lock_held(PyObject *self, PyObject *noargs) { #ifdef WITH_THREAD - return PyBool_FromLong(import_lock_thread != -1); + return PyBool_FromLong(import_lock_thread != -1); #else - return PyBool_FromLong(0); + return PyBool_FromLong(0); #endif } @@ -341,32 +341,32 @@ static PyObject * imp_acquire_lock(PyObject *self, PyObject *noargs) { #ifdef WITH_THREAD - _PyImport_AcquireLock(); + _PyImport_AcquireLock(); #endif - Py_INCREF(Py_None); - return Py_None; + Py_INCREF(Py_None); + return Py_None; } static PyObject * imp_release_lock(PyObject *self, PyObject *noargs) { #ifdef WITH_THREAD - if (_PyImport_ReleaseLock() < 0) { - PyErr_SetString(PyExc_RuntimeError, - "not holding the import lock"); - return NULL; - } + if (_PyImport_ReleaseLock() < 0) { + PyErr_SetString(PyExc_RuntimeError, + "not holding the import lock"); + return NULL; + } #endif - Py_INCREF(Py_None); - return Py_None; + Py_INCREF(Py_None); + return Py_None; } static void imp_modules_reloading_clear(void) { - PyInterpreterState *interp = PyThreadState_Get()->interp; - if (interp->modules_reloading != NULL) - PyDict_Clear(interp->modules_reloading); + PyInterpreterState *interp = PyThreadState_Get()->interp; + if (interp->modules_reloading != NULL) + PyDict_Clear(interp->modules_reloading); } /* Helper for sys */ @@ -374,28 +374,28 @@ imp_modules_reloading_clear(void) PyObject * PyImport_GetModuleDict(void) { - PyInterpreterState *interp = PyThreadState_GET()->interp; - if (interp->modules == NULL) - Py_FatalError("PyImport_GetModuleDict: no module dictionary!"); - return interp->modules; + 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", - "last_type", "last_value", "last_traceback", - "path_hooks", "path_importer_cache", "meta_path", - /* misc stuff */ - "flags", "float_info", - NULL + "path", "argv", "ps1", "ps2", + "last_type", "last_value", "last_traceback", + "path_hooks", "path_importer_cache", "meta_path", + /* misc stuff */ + "flags", "float_info", + NULL }; static char* sys_files[] = { - "stdin", "__stdin__", - "stdout", "__stdout__", - "stderr", "__stderr__", - NULL + "stdin", "__stdin__", + "stdout", "__stdout__", + "stderr", "__stderr__", + NULL }; @@ -404,132 +404,132 @@ static char* sys_files[] = { 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, "builtins"); - if (value != NULL && PyModule_Check(value)) { - dict = PyModule_GetDict(value); - if (Py_VerboseFlag) - PySys_WriteStderr("# clear builtins._\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 "builtins" 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 "builtins" - 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 builtins and sys) and delete them */ - do { - ndone = 0; - pos = 0; - while (PyDict_Next(modules, &pos, &key, &value)) { - if (value->ob_refcnt != 1) - continue; - if (PyUnicode_Check(key) && PyModule_Check(value)) { - name = _PyUnicode_AsString(key); - if (strcmp(name, "builtins") == 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 builtins and sys) */ - pos = 0; - while (PyDict_Next(modules, &pos, &key, &value)) { - if (PyUnicode_Check(key) && PyModule_Check(value)) { - name = _PyUnicode_AsString(key); - if (strcmp(name, "builtins") == 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 builtins (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, "builtins"); - if (value != NULL && PyModule_Check(value)) { - if (Py_VerboseFlag) - PySys_WriteStderr("# cleanup builtins\n"); - _PyModule_Clear(value); - PyDict_SetItemString(modules, "builtins", Py_None); - } - - /* Finally, clear and delete the modules directory */ - PyDict_Clear(modules); - interp->modules = NULL; - Py_DECREF(modules); - Py_CLEAR(interp->modules_reloading); + 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, "builtins"); + if (value != NULL && PyModule_Check(value)) { + dict = PyModule_GetDict(value); + if (Py_VerboseFlag) + PySys_WriteStderr("# clear builtins._\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 "builtins" 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 "builtins" + 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 builtins and sys) and delete them */ + do { + ndone = 0; + pos = 0; + while (PyDict_Next(modules, &pos, &key, &value)) { + if (value->ob_refcnt != 1) + continue; + if (PyUnicode_Check(key) && PyModule_Check(value)) { + name = _PyUnicode_AsString(key); + if (strcmp(name, "builtins") == 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 builtins and sys) */ + pos = 0; + while (PyDict_Next(modules, &pos, &key, &value)) { + if (PyUnicode_Check(key) && PyModule_Check(value)) { + name = _PyUnicode_AsString(key); + if (strcmp(name, "builtins") == 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 builtins (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, "builtins"); + if (value != NULL && PyModule_Check(value)) { + if (Py_VerboseFlag) + PySys_WriteStderr("# cleanup builtins\n"); + _PyModule_Clear(value); + PyDict_SetItemString(modules, "builtins", Py_None); + } + + /* Finally, clear and delete the modules directory */ + PyDict_Clear(modules); + interp->modules = NULL; + Py_DECREF(modules); + Py_CLEAR(interp->modules_reloading); } @@ -538,14 +538,14 @@ PyImport_Cleanup(void) long PyImport_GetMagicNumber(void) { - return pyc_magic; + return pyc_magic; } const char * PyImport_GetMagicTag(void) { - return pyc_tag; + return pyc_tag; } /* Magic for extension modules (built-in as well as dynamically @@ -567,89 +567,89 @@ PyImport_GetMagicTag(void) int _PyImport_FixupExtension(PyObject *mod, char *name, char *filename) { - PyObject *modules, *dict; - struct PyModuleDef *def; - if (extensions == NULL) { - extensions = PyDict_New(); - if (extensions == NULL) - return -1; - } - if (mod == NULL || !PyModule_Check(mod)) { - PyErr_BadInternalCall(); - return -1; - } - def = PyModule_GetDef(mod); - if (!def) { - PyErr_BadInternalCall(); - return -1; - } - modules = PyImport_GetModuleDict(); - if (PyDict_SetItemString(modules, name, mod) < 0) - return -1; - if (_PyState_AddModule(mod, def) < 0) { - PyDict_DelItemString(modules, name); - return -1; - } - if (def->m_size == -1) { - if (def->m_base.m_copy) { - /* Somebody already imported the module, - likely under a different name. - XXX this should really not happen. */ - Py_DECREF(def->m_base.m_copy); - def->m_base.m_copy = NULL; - } - dict = PyModule_GetDict(mod); - if (dict == NULL) - return -1; - def->m_base.m_copy = PyDict_Copy(dict); - if (def->m_base.m_copy == NULL) - return -1; - } - PyDict_SetItemString(extensions, filename, (PyObject*)def); - return 0; + PyObject *modules, *dict; + struct PyModuleDef *def; + if (extensions == NULL) { + extensions = PyDict_New(); + if (extensions == NULL) + return -1; + } + if (mod == NULL || !PyModule_Check(mod)) { + PyErr_BadInternalCall(); + return -1; + } + def = PyModule_GetDef(mod); + if (!def) { + PyErr_BadInternalCall(); + return -1; + } + modules = PyImport_GetModuleDict(); + if (PyDict_SetItemString(modules, name, mod) < 0) + return -1; + if (_PyState_AddModule(mod, def) < 0) { + PyDict_DelItemString(modules, name); + return -1; + } + if (def->m_size == -1) { + if (def->m_base.m_copy) { + /* Somebody already imported the module, + likely under a different name. + XXX this should really not happen. */ + Py_DECREF(def->m_base.m_copy); + def->m_base.m_copy = NULL; + } + dict = PyModule_GetDict(mod); + if (dict == NULL) + return -1; + def->m_base.m_copy = PyDict_Copy(dict); + if (def->m_base.m_copy == NULL) + return -1; + } + PyDict_SetItemString(extensions, filename, (PyObject*)def); + return 0; } PyObject * _PyImport_FindExtension(char *name, char *filename) { - PyObject *mod, *mdict; - PyModuleDef* def; - if (extensions == NULL) - return NULL; - def = (PyModuleDef*)PyDict_GetItemString(extensions, filename); - if (def == NULL) - return NULL; - if (def->m_size == -1) { - /* Module does not support repeated initialization */ - if (def->m_base.m_copy == 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, def->m_base.m_copy)) - return NULL; - } - else { - if (def->m_base.m_init == NULL) - return NULL; - mod = def->m_base.m_init(); - if (mod == NULL) - return NULL; - PyDict_SetItemString(PyImport_GetModuleDict(), name, mod); - Py_DECREF(mod); - } - if (_PyState_AddModule(mod, def) < 0) { - PyDict_DelItemString(PyImport_GetModuleDict(), name); - Py_DECREF(mod); - return NULL; - } - if (Py_VerboseFlag) - PySys_WriteStderr("import %s # previously loaded (%s)\n", - name, filename); - return mod; + PyObject *mod, *mdict; + PyModuleDef* def; + if (extensions == NULL) + return NULL; + def = (PyModuleDef*)PyDict_GetItemString(extensions, filename); + if (def == NULL) + return NULL; + if (def->m_size == -1) { + /* Module does not support repeated initialization */ + if (def->m_base.m_copy == 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, def->m_base.m_copy)) + return NULL; + } + else { + if (def->m_base.m_init == NULL) + return NULL; + mod = def->m_base.m_init(); + if (mod == NULL) + return NULL; + PyDict_SetItemString(PyImport_GetModuleDict(), name, mod); + Py_DECREF(mod); + } + if (_PyState_AddModule(mod, def) < 0) { + PyDict_DelItemString(PyImport_GetModuleDict(), name); + Py_DECREF(mod); + return NULL; + } + if (Py_VerboseFlag) + PySys_WriteStderr("import %s # previously loaded (%s)\n", + name, filename); + return mod; } @@ -663,40 +663,40 @@ _PyImport_FindExtension(char *name, char *filename) PyObject * PyImport_AddModule(const char *name) { - PyObject *modules = PyImport_GetModuleDict(); - PyObject *m; + 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! */ + 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; + return m; } /* Remove name from sys.modules, if it's there. */ static void remove_module(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"); + 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"); } static PyObject * get_sourcefile(char *file); static char *make_source_pathname(char *pathname, char *buf); static char *make_compiled_pathname(char *pathname, char *buf, size_t buflen, - int debug); + int debug); /* Execute a code object in a module and return the module object * WITH INCREMENTED REFERENCE COUNT. If an error occurs, name is @@ -711,83 +711,83 @@ static char *make_compiled_pathname(char *pathname, char *buf, size_t buflen, PyObject * PyImport_ExecCodeModule(char *name, PyObject *co) { - return PyImport_ExecCodeModuleWithPathnames( - name, co, (char *)NULL, (char *)NULL); + return PyImport_ExecCodeModuleWithPathnames( + name, co, (char *)NULL, (char *)NULL); } PyObject * PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname) { - return PyImport_ExecCodeModuleWithPathnames( - name, co, pathname, (char *)NULL); + return PyImport_ExecCodeModuleWithPathnames( + name, co, pathname, (char *)NULL); } PyObject * PyImport_ExecCodeModuleWithPathnames(char *name, PyObject *co, char *pathname, - char *cpathname) -{ - 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 = get_sourcefile(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); - - /* Remember the pyc path name as the __cached__ attribute. */ - if (cpathname == NULL) { - v = Py_None; - Py_INCREF(v); - } - else if ((v = PyUnicode_FromString(cpathname)) == NULL) { - PyErr_Clear(); /* Not important enough to report */ - v = Py_None; - Py_INCREF(v); - } - if (PyDict_SetItemString(d, "__cached__", 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; + char *cpathname) +{ + 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 = get_sourcefile(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); + + /* Remember the pyc path name as the __cached__ attribute. */ + if (cpathname == NULL) { + v = Py_None; + Py_INCREF(v); + } + else if ((v = PyUnicode_FromString(cpathname)) == NULL) { + PyErr_Clear(); /* Not important enough to report */ + v = Py_None; + Py_INCREF(v); + } + if (PyDict_SetItemString(d, "__cached__", 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: - remove_module(name); - return NULL; + remove_module(name); + return NULL; } @@ -797,18 +797,18 @@ PyImport_ExecCodeModuleWithPathnames(char *name, PyObject *co, char *pathname, static char * rightmost_sep(char *s) { - char *found, c; - for (found = NULL; (c = *s); s++) { - if (c == SEP + char *found, c; + for (found = NULL; (c = *s); s++) { + if (c == SEP #ifdef ALTSEP - || c == ALTSEP + || c == ALTSEP #endif - ) - { - found = s; - } - } - return found; + ) + { + found = s; + } + } + return found; } @@ -820,104 +820,104 @@ rightmost_sep(char *s) static char * make_compiled_pathname(char *pathname, char *buf, size_t buflen, int debug) { - /* foo.py -> __pycache__/foo..pyc */ - size_t len = strlen(pathname); - size_t i, save; - char *pos; - int sep = SEP; - - /* Sanity check that the buffer has roughly enough space to hold what - will eventually be the full path to the compiled file. The 5 extra - bytes include the slash afer __pycache__, the two extra dots, the - extra trailing character ('c' or 'o') and null. This isn't exact - because the contents of the buffer can affect how many actual - characters of the string get into the buffer. We'll do a final - sanity check before writing the extension to ensure we do not - overflow the buffer. - */ - if (len + strlen(CACHEDIR) + strlen(pyc_tag) + 5 > buflen) - return NULL; - - /* Find the last path separator and copy everything from the start of - the source string up to and including the separator. - */ - if ((pos = rightmost_sep(pathname)) == NULL) { - i = 0; - } - else { - sep = *pos; - i = pos - pathname + 1; - strncpy(buf, pathname, i); - } - - save = i; - buf[i++] = '\0'; - /* Add __pycache__/ */ - strcat(buf, CACHEDIR); - i += strlen(CACHEDIR) - 1; - buf[i++] = sep; - buf[i++] = '\0'; - /* Add the base filename, but remove the .py or .pyw extension, since - the tag name must go before the extension. - */ - strcat(buf, pathname + save); - if ((pos = strrchr(buf, '.')) != NULL) - *++pos = '\0'; - strcat(buf, pyc_tag); - /* The length test above assumes that we're only adding one character - to the end of what would normally be the extension. What if there - is no extension, or the string ends in '.' or '.p', and otherwise - fills the buffer? By appending 4 more characters onto the string - here, we could overrun the buffer. - - As a simple example, let's say buflen=32 and the input string is - 'xxx.py'. strlen() would be 6 and the test above would yield: - - (6 + 11 + 10 + 5 == 32) > 32 - - which is false and so the name mangling would continue. This would - be fine because we'd end up with this string in buf: - - __pycache__/xxx.cpython-32.pyc\0 - - strlen(of that) == 30 + the nul fits inside a 32 character buffer. - We can even handle an input string of say 'xxxxx' above because - that's (5 + 11 + 10 + 5 == 31) > 32 which is also false. Name - mangling that yields: - - __pycache__/xxxxxcpython-32.pyc\0 - - which is 32 characters including the nul, and thus fits in the - buffer. However, an input string of 'xxxxxx' would yield a result - string of: - - __pycache__/xxxxxxcpython-32.pyc\0 - - which is 33 characters long (including the nul), thus overflowing - the buffer, even though the first test would fail, i.e.: the input - string is also 6 characters long, so 32 > 32 is false. - - The reason the first test fails but we still overflow the buffer is - that the test above only expects to add one extra character to be - added to the extension, and here we're adding three (pyc). We - don't add the first dot, so that reclaims one of expected - positions, leaving us overflowing by 1 byte (3 extra - 1 reclaimed - dot - 1 expected extra == 1 overflowed). - - The best we can do is ensure that we still have enough room in the - target buffer before we write the extension. Because it's always - only the extension that can cause the overflow, and never the other - path bytes we've written, it's sufficient to just do one more test - here. Still, the assertion that follows can't hurt. - */ + /* foo.py -> __pycache__/foo..pyc */ + size_t len = strlen(pathname); + size_t i, save; + char *pos; + int sep = SEP; + + /* Sanity check that the buffer has roughly enough space to hold what + will eventually be the full path to the compiled file. The 5 extra + bytes include the slash afer __pycache__, the two extra dots, the + extra trailing character ('c' or 'o') and null. This isn't exact + because the contents of the buffer can affect how many actual + characters of the string get into the buffer. We'll do a final + sanity check before writing the extension to ensure we do not + overflow the buffer. + */ + if (len + strlen(CACHEDIR) + strlen(pyc_tag) + 5 > buflen) + return NULL; + + /* Find the last path separator and copy everything from the start of + the source string up to and including the separator. + */ + if ((pos = rightmost_sep(pathname)) == NULL) { + i = 0; + } + else { + sep = *pos; + i = pos - pathname + 1; + strncpy(buf, pathname, i); + } + + save = i; + buf[i++] = '\0'; + /* Add __pycache__/ */ + strcat(buf, CACHEDIR); + i += strlen(CACHEDIR) - 1; + buf[i++] = sep; + buf[i++] = '\0'; + /* Add the base filename, but remove the .py or .pyw extension, since + the tag name must go before the extension. + */ + strcat(buf, pathname + save); + if ((pos = strrchr(buf, '.')) != NULL) + *++pos = '\0'; + strcat(buf, pyc_tag); + /* The length test above assumes that we're only adding one character + to the end of what would normally be the extension. What if there + is no extension, or the string ends in '.' or '.p', and otherwise + fills the buffer? By appending 4 more characters onto the string + here, we could overrun the buffer. + + As a simple example, let's say buflen=32 and the input string is + 'xxx.py'. strlen() would be 6 and the test above would yield: + + (6 + 11 + 10 + 5 == 32) > 32 + + which is false and so the name mangling would continue. This would + be fine because we'd end up with this string in buf: + + __pycache__/xxx.cpython-32.pyc\0 + + strlen(of that) == 30 + the nul fits inside a 32 character buffer. + We can even handle an input string of say 'xxxxx' above because + that's (5 + 11 + 10 + 5 == 31) > 32 which is also false. Name + mangling that yields: + + __pycache__/xxxxxcpython-32.pyc\0 + + which is 32 characters including the nul, and thus fits in the + buffer. However, an input string of 'xxxxxx' would yield a result + string of: + + __pycache__/xxxxxxcpython-32.pyc\0 + + which is 33 characters long (including the nul), thus overflowing + the buffer, even though the first test would fail, i.e.: the input + string is also 6 characters long, so 32 > 32 is false. + + The reason the first test fails but we still overflow the buffer is + that the test above only expects to add one extra character to be + added to the extension, and here we're adding three (pyc). We + don't add the first dot, so that reclaims one of expected + positions, leaving us overflowing by 1 byte (3 extra - 1 reclaimed + dot - 1 expected extra == 1 overflowed). + + The best we can do is ensure that we still have enough room in the + target buffer before we write the extension. Because it's always + only the extension that can cause the overflow, and never the other + path bytes we've written, it's sufficient to just do one more test + here. Still, the assertion that follows can't hurt. + */ #if 0 - printf("strlen(buf): %d; buflen: %d\n", (int)strlen(buf), (int)buflen); + printf("strlen(buf): %d; buflen: %d\n", (int)strlen(buf), (int)buflen); #endif - if (strlen(buf) + 5 > buflen) - return NULL; - strcat(buf, debug ? ".pyc" : ".pyo"); - assert(strlen(buf) < buflen); - return buf; + if (strlen(buf) + 5 > buflen) + return NULL; + strcat(buf, debug ? ".pyc" : ".pyo"); + assert(strlen(buf) < buflen); + return buf; } @@ -926,52 +926,52 @@ make_compiled_pathname(char *pathname, char *buf, size_t buflen, int debug) for any file existence, however, if the pyc file name does not match PEP 3147 style, NULL is returned. buf must be at least as big as pathname; the resulting path will always be shorter. */ - + static char * make_source_pathname(char *pathname, char *buf) { - /* __pycache__/foo..pyc -> foo.py */ - size_t i, j; - char *left, *right, *dot0, *dot1, sep; - - /* Look back two slashes from the end. In between these two slashes - must be the string __pycache__ or this is not a PEP 3147 style - path. It's possible for there to be only one slash. - */ - if ((right = rightmost_sep(pathname)) == NULL) - return NULL; - sep = *right; - *right = '\0'; - left = rightmost_sep(pathname); - *right = sep; - if (left == NULL) - left = pathname; - else - left++; - if (right-left != strlen(CACHEDIR) || - strncmp(left, CACHEDIR, right-left) != 0) - return NULL; - - /* Now verify that the path component to the right of the last slash - has two dots in it. - */ - if ((dot0 = strchr(right + 1, '.')) == NULL) - return NULL; - if ((dot1 = strchr(dot0 + 1, '.')) == NULL) - return NULL; - /* Too many dots? */ - if (strchr(dot1 + 1, '.') != NULL) - return NULL; - - /* This is a PEP 3147 path. Start by copying everything from the - start of pathname up to and including the leftmost slash. Then - copy the file's basename, removing the magic tag and adding a .py - suffix. - */ - strncpy(buf, pathname, (i=left-pathname)); - strncpy(buf+i, right+1, (j=dot0-right)); - strcpy(buf+i+j, "py"); - return buf; + /* __pycache__/foo..pyc -> foo.py */ + size_t i, j; + char *left, *right, *dot0, *dot1, sep; + + /* Look back two slashes from the end. In between these two slashes + must be the string __pycache__ or this is not a PEP 3147 style + path. It's possible for there to be only one slash. + */ + if ((right = rightmost_sep(pathname)) == NULL) + return NULL; + sep = *right; + *right = '\0'; + left = rightmost_sep(pathname); + *right = sep; + if (left == NULL) + left = pathname; + else + left++; + if (right-left != strlen(CACHEDIR) || + strncmp(left, CACHEDIR, right-left) != 0) + return NULL; + + /* Now verify that the path component to the right of the last slash + has two dots in it. + */ + if ((dot0 = strchr(right + 1, '.')) == NULL) + return NULL; + if ((dot1 = strchr(dot0 + 1, '.')) == NULL) + return NULL; + /* Too many dots? */ + if (strchr(dot1 + 1, '.') != NULL) + return NULL; + + /* This is a PEP 3147 path. Start by copying everything from the + start of pathname up to and including the leftmost slash. Then + copy the file's basename, removing the magic tag and adding a .py + suffix. + */ + strncpy(buf, pathname, (i=left-pathname)); + strncpy(buf+i, right+1, (j=dot0-right)); + strcpy(buf+i+j, "py"); + return buf; } /* Given a pathname for a Python source file, its time of last @@ -984,30 +984,30 @@ make_source_pathname(char *pathname, char *buf) static FILE * check_compiled_module(char *pathname, time_t mtime, char *cpathname) { - FILE *fp; - long magic; - long pyc_mtime; - - fp = fopen(cpathname, "rb"); - if (fp == NULL) - return NULL; - magic = PyMarshal_ReadLongFromFile(fp); - if (magic != pyc_magic) { - if (Py_VerboseFlag) - PySys_WriteStderr("# %s has bad magic\n", cpathname); - fclose(fp); - return NULL; - } - pyc_mtime = PyMarshal_ReadLongFromFile(fp); - if (pyc_mtime != mtime) { - if (Py_VerboseFlag) - PySys_WriteStderr("# %s has bad mtime\n", cpathname); - fclose(fp); - return NULL; - } - if (Py_VerboseFlag) - PySys_WriteStderr("# %s matches %s\n", cpathname, pathname); - return fp; + FILE *fp; + long magic; + long pyc_mtime; + + fp = fopen(cpathname, "rb"); + if (fp == NULL) + return NULL; + magic = PyMarshal_ReadLongFromFile(fp); + if (magic != pyc_magic) { + if (Py_VerboseFlag) + PySys_WriteStderr("# %s has bad magic\n", cpathname); + fclose(fp); + return NULL; + } + pyc_mtime = PyMarshal_ReadLongFromFile(fp); + if (pyc_mtime != mtime) { + if (Py_VerboseFlag) + PySys_WriteStderr("# %s has bad mtime\n", cpathname); + fclose(fp); + return NULL; + } + if (Py_VerboseFlag) + PySys_WriteStderr("# %s matches %s\n", cpathname, pathname); + return fp; } @@ -1016,18 +1016,18 @@ check_compiled_module(char *pathname, time_t mtime, char *cpathname) static PyCodeObject * read_compiled_module(char *cpathname, FILE *fp) { - PyObject *co; + 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; + 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; } @@ -1037,28 +1037,28 @@ read_compiled_module(char *cpathname, FILE *fp) 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_ExecCodeModuleWithPathnames( - name, (PyObject *)co, cpathname, cpathname); - Py_DECREF(co); - - return m; + 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_ExecCodeModuleWithPathnames( + name, (PyObject *)co, cpathname, cpathname); + Py_DECREF(co); + + return m; } /* Parse a source file and return the corresponding code object */ @@ -1066,22 +1066,22 @@ load_compiled_module(char *name, char *cpathname, FILE *fp) static PyCodeObject * parse_source_module(const char *pathname, FILE *fp) { - PyCodeObject *co = NULL; - mod_ty mod; - PyCompilerFlags flags; - PyArena *arena = PyArena_New(); - if (arena == NULL) - return NULL; + PyCodeObject *co = NULL; + mod_ty mod; + PyCompilerFlags flags; + PyArena *arena = PyArena_New(); + if (arena == NULL) + return NULL; - flags.cf_flags = 0; - mod = PyParser_ASTFromFile(fp, pathname, NULL, - Py_file_input, 0, 0, &flags, - NULL, arena); - if (mod) { - co = PyAST_Compile(mod, pathname, NULL, arena); - } - PyArena_Free(arena); - return co; + flags.cf_flags = 0; + mod = PyParser_ASTFromFile(fp, pathname, NULL, + Py_file_input, 0, 0, &flags, + NULL, arena); + if (mod) { + co = PyAST_Compile(mod, pathname, NULL, arena); + } + PyArena_Free(arena); + return co; } @@ -1091,30 +1091,30 @@ static FILE * open_exclusive(char *filename, mode_t mode) { #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 + /* 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 */ + |O_BINARY /* necessary for Windows */ #endif #ifdef __VMS - , mode, "ctxt=bin", "shr=nil" + , mode, "ctxt=bin", "shr=nil" #else - , mode + , mode #endif - ); - if (fd < 0) - return NULL; - return fdopen(fd, "wb"); + ); + 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"); + /* Best we can do -- on Windows this can't happen anyway */ + return fopen(filename, "wb"); #endif } @@ -1127,116 +1127,116 @@ open_exclusive(char *filename, mode_t mode) static void write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat) { - FILE *fp; - char *dirpath; - time_t mtime = srcstat->st_mtime; + FILE *fp; + char *dirpath; + time_t mtime = srcstat->st_mtime; #ifdef MS_WINDOWS /* since Windows uses different permissions */ - mode_t mode = srcstat->st_mode & ~S_IEXEC; - mode_t dirmode = srcstat->st_mode | S_IEXEC; /* XXX Is this correct - for Windows? - 2010-04-07 BAW */ + mode_t mode = srcstat->st_mode & ~S_IEXEC; + mode_t dirmode = srcstat->st_mode | S_IEXEC; /* XXX Is this correct + for Windows? + 2010-04-07 BAW */ #else - mode_t mode = srcstat->st_mode & ~S_IXUSR & ~S_IXGRP & ~S_IXOTH; - mode_t dirmode = (srcstat->st_mode | - S_IXUSR | S_IXGRP | S_IXOTH | - S_IWUSR | S_IWGRP | S_IWOTH); + mode_t mode = srcstat->st_mode & ~S_IXUSR & ~S_IXGRP & ~S_IXOTH; + mode_t dirmode = (srcstat->st_mode | + S_IXUSR | S_IXGRP | S_IXOTH | + S_IWUSR | S_IWGRP | S_IWOTH); #endif - int saved; - - /* Ensure that the __pycache__ directory exists. */ - dirpath = rightmost_sep(cpathname); - if (dirpath == NULL) { - if (Py_VerboseFlag) - PySys_WriteStderr( - "# no %s path found %s\n", - CACHEDIR, cpathname); - return; - } - saved = *dirpath; - *dirpath = '\0'; - /* XXX call os.mkdir() or maybe CreateDirectoryA() on Windows? */ - if (mkdir(cpathname, dirmode) < 0 && errno != EEXIST) { - *dirpath = saved; - if (Py_VerboseFlag) - PySys_WriteStderr( - "# cannot create cache dir %s\n", cpathname); - return; - } - *dirpath = saved; - - fp = open_exclusive(cpathname, mode); - if (fp == NULL) { - if (Py_VerboseFlag) - PySys_WriteStderr( - "# can't create %s\n", cpathname); - return; - } - PyMarshal_WriteLongToFile(pyc_magic, fp, Py_MARSHAL_VERSION); - /* First write a 0 for mtime */ - PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION); - PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION); - if (fflush(fp) != 0 || ferror(fp)) { - if (Py_VerboseFlag) - PySys_WriteStderr("# can't write %s\n", cpathname); - /* Don't keep partial file */ - fclose(fp); - (void) unlink(cpathname); - return; - } - /* Now write the true mtime */ - fseek(fp, 4L, 0); - assert(mtime < LONG_MAX); - PyMarshal_WriteLongToFile((long)mtime, fp, Py_MARSHAL_VERSION); - fflush(fp); - fclose(fp); - if (Py_VerboseFlag) - PySys_WriteStderr("# wrote %s\n", cpathname); + int saved; + + /* Ensure that the __pycache__ directory exists. */ + dirpath = rightmost_sep(cpathname); + if (dirpath == NULL) { + if (Py_VerboseFlag) + PySys_WriteStderr( + "# no %s path found %s\n", + CACHEDIR, cpathname); + return; + } + saved = *dirpath; + *dirpath = '\0'; + /* XXX call os.mkdir() or maybe CreateDirectoryA() on Windows? */ + if (mkdir(cpathname, dirmode) < 0 && errno != EEXIST) { + *dirpath = saved; + if (Py_VerboseFlag) + PySys_WriteStderr( + "# cannot create cache dir %s\n", cpathname); + return; + } + *dirpath = saved; + + fp = open_exclusive(cpathname, mode); + if (fp == NULL) { + if (Py_VerboseFlag) + PySys_WriteStderr( + "# can't create %s\n", cpathname); + return; + } + PyMarshal_WriteLongToFile(pyc_magic, fp, Py_MARSHAL_VERSION); + /* First write a 0 for mtime */ + PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION); + PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION); + if (fflush(fp) != 0 || ferror(fp)) { + if (Py_VerboseFlag) + PySys_WriteStderr("# can't write %s\n", cpathname); + /* Don't keep partial file */ + fclose(fp); + (void) unlink(cpathname); + return; + } + /* Now write the true mtime */ + fseek(fp, 4L, 0); + assert(mtime < LONG_MAX); + PyMarshal_WriteLongToFile((long)mtime, fp, Py_MARSHAL_VERSION); + fflush(fp); + fclose(fp); + if (Py_VerboseFlag) + PySys_WriteStderr("# wrote %s\n", cpathname); } static void update_code_filenames(PyCodeObject *co, PyObject *oldname, PyObject *newname) { - PyObject *constants, *tmp; - Py_ssize_t i, n; + PyObject *constants, *tmp; + Py_ssize_t i, n; - if (PyUnicode_Compare(co->co_filename, oldname)) - return; + if (PyUnicode_Compare(co->co_filename, oldname)) + return; - tmp = co->co_filename; - co->co_filename = newname; - Py_INCREF(co->co_filename); - Py_DECREF(tmp); + tmp = co->co_filename; + co->co_filename = newname; + Py_INCREF(co->co_filename); + Py_DECREF(tmp); - constants = co->co_consts; - n = PyTuple_GET_SIZE(constants); - for (i = 0; i < n; i++) { - tmp = PyTuple_GET_ITEM(constants, i); - if (PyCode_Check(tmp)) - update_code_filenames((PyCodeObject *)tmp, - oldname, newname); - } + constants = co->co_consts; + n = PyTuple_GET_SIZE(constants); + for (i = 0; i < n; i++) { + tmp = PyTuple_GET_ITEM(constants, i); + if (PyCode_Check(tmp)) + update_code_filenames((PyCodeObject *)tmp, + oldname, newname); + } } static int update_compiled_module(PyCodeObject *co, char *pathname) { - PyObject *oldname, *newname; + PyObject *oldname, *newname; - newname = PyUnicode_DecodeFSDefault(pathname); - if (newname == NULL) - return -1; + newname = PyUnicode_DecodeFSDefault(pathname); + if (newname == NULL) + return -1; - if (!PyUnicode_Compare(co->co_filename, newname)) { - Py_DECREF(newname); - return 0; - } + if (!PyUnicode_Compare(co->co_filename, newname)) { + Py_DECREF(newname); + return 0; + } - oldname = co->co_filename; - Py_INCREF(oldname); - update_code_filenames(co, oldname, newname); - Py_DECREF(oldname); - Py_DECREF(newname); - return 1; + oldname = co->co_filename; + Py_INCREF(oldname); + update_code_filenames(co, oldname, newname); + Py_DECREF(oldname); + Py_DECREF(newname); + return 1; } /* Load a source module from a given file and return its module @@ -1246,63 +1246,63 @@ update_compiled_module(PyCodeObject *co, char *pathname) static PyObject * load_source_module(char *name, char *pathname, FILE *fp) { - struct stat st; - FILE *fpc; - char buf[MAXPATHLEN+1]; - char *cpathname; - PyCodeObject *co; - PyObject *m; - - if (fstat(fileno(fp), &st) != 0) { - PyErr_Format(PyExc_RuntimeError, - "unable to get file status from '%s'", - pathname); - return NULL; - } + struct stat st; + FILE *fpc; + char buf[MAXPATHLEN+1]; + char *cpathname; + PyCodeObject *co; + PyObject *m; + + if (fstat(fileno(fp), &st) != 0) { + PyErr_Format(PyExc_RuntimeError, + "unable to get file status 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 (st.st_mtime >> 32) { - PyErr_SetString(PyExc_OverflowError, - "modification time overflows a 4 byte field"); - return NULL; - } + /* 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 (st.st_mtime >> 32) { + PyErr_SetString(PyExc_OverflowError, + "modification time overflows a 4 byte field"); + return NULL; + } #endif - cpathname = make_compiled_pathname( - pathname, buf, (size_t)MAXPATHLEN + 1, !Py_OptimizeFlag); - if (cpathname != NULL && - (fpc = check_compiled_module(pathname, st.st_mtime, cpathname))) { - co = read_compiled_module(cpathname, fpc); - fclose(fpc); - if (co == NULL) - return NULL; - if (update_compiled_module(co, pathname) < 0) - return NULL; - if (Py_VerboseFlag) - PySys_WriteStderr("import %s # precompiled from %s\n", - name, cpathname); - pathname = cpathname; - } - else { - co = parse_source_module(pathname, fp); - if (co == NULL) - return NULL; - if (Py_VerboseFlag) - PySys_WriteStderr("import %s # from %s\n", - name, pathname); - if (cpathname) { - PyObject *ro = PySys_GetObject("dont_write_bytecode"); - if (ro == NULL || !PyObject_IsTrue(ro)) - write_compiled_module(co, cpathname, &st); - } - } - m = PyImport_ExecCodeModuleWithPathnames( - name, (PyObject *)co, pathname, cpathname); - Py_DECREF(co); - - return m; + cpathname = make_compiled_pathname( + pathname, buf, (size_t)MAXPATHLEN + 1, !Py_OptimizeFlag); + if (cpathname != NULL && + (fpc = check_compiled_module(pathname, st.st_mtime, cpathname))) { + co = read_compiled_module(cpathname, fpc); + fclose(fpc); + if (co == NULL) + return NULL; + if (update_compiled_module(co, pathname) < 0) + return NULL; + if (Py_VerboseFlag) + PySys_WriteStderr("import %s # precompiled from %s\n", + name, cpathname); + pathname = cpathname; + } + else { + co = parse_source_module(pathname, fp); + if (co == NULL) + return NULL; + if (Py_VerboseFlag) + PySys_WriteStderr("import %s # from %s\n", + name, pathname); + if (cpathname) { + PyObject *ro = PySys_GetObject("dont_write_bytecode"); + if (ro == NULL || !PyObject_IsTrue(ro)) + write_compiled_module(co, cpathname, &st); + } + } + m = PyImport_ExecCodeModuleWithPathnames( + name, (PyObject *)co, pathname, cpathname); + Py_DECREF(co); + + return m; } /* Get source file -> unicode or None @@ -1311,44 +1311,44 @@ load_source_module(char *name, char *pathname, FILE *fp) static PyObject * get_sourcefile(char *file) { - char py[MAXPATHLEN + 1]; - Py_ssize_t len; - PyObject *u; - struct stat statbuf; - - if (!file || !*file) { - Py_RETURN_NONE; - } - - len = strlen(file); - /* match '*.py?' */ - if (len > MAXPATHLEN || PyOS_strnicmp(&file[len-4], ".py", 3) != 0) { - return PyUnicode_DecodeFSDefault(file); - } - - /* Start by trying to turn PEP 3147 path into source path. If that - * fails, just chop off the trailing character, i.e. legacy pyc path - * to py. - */ - if (make_source_pathname(file, py) == NULL) { - strncpy(py, file, len-1); - py[len-1] = '\0'; - } - - if (stat(py, &statbuf) == 0 && - S_ISREG(statbuf.st_mode)) { - u = PyUnicode_DecodeFSDefault(py); - } - else { - u = PyUnicode_DecodeFSDefault(file); - } - return u; + char py[MAXPATHLEN + 1]; + Py_ssize_t len; + PyObject *u; + struct stat statbuf; + + if (!file || !*file) { + Py_RETURN_NONE; + } + + len = strlen(file); + /* match '*.py?' */ + if (len > MAXPATHLEN || PyOS_strnicmp(&file[len-4], ".py", 3) != 0) { + return PyUnicode_DecodeFSDefault(file); + } + + /* Start by trying to turn PEP 3147 path into source path. If that + * fails, just chop off the trailing character, i.e. legacy pyc path + * to py. + */ + if (make_source_pathname(file, py) == NULL) { + strncpy(py, file, len-1); + py[len-1] = '\0'; + } + + if (stat(py, &statbuf) == 0 && + S_ISREG(statbuf.st_mode)) { + u = PyUnicode_DecodeFSDefault(py); + } + else { + u = PyUnicode_DecodeFSDefault(file); + } + return u; } /* Forward */ static PyObject *load_module(char *, FILE *, char *, int, PyObject *); static struct filedescr *find_module(char *, char *, PyObject *, - char *, size_t, FILE **, PyObject **); + char *, size_t, FILE **, PyObject **); static struct _frozen * find_frozen(char *); /* Load a package and return its module object WITH INCREMENTED @@ -1357,54 +1357,54 @@ static struct _frozen * find_frozen(char *); 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 = get_sourcefile(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; + 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 = get_sourcefile(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; + m = NULL; cleanup: - Py_XDECREF(path); - Py_XDECREF(file); - return m; + Py_XDECREF(path); + Py_XDECREF(file); + return m; } @@ -1413,16 +1413,16 @@ load_package(char *name, char *pathname) 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; + 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; } @@ -1436,72 +1436,72 @@ is_builtin(char *name) 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 *)&PyNullImporter_Type, 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; + 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 *)&PyNullImporter_Type, 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; } PyAPI_FUNC(PyObject *) PyImport_GetImporter(PyObject *path) { - PyObject *importer=NULL, *path_importer_cache=NULL, *path_hooks=NULL; + PyObject *importer=NULL, *path_importer_cache=NULL, *path_hooks=NULL; - if ((path_importer_cache = PySys_GetObject("path_importer_cache"))) { - if ((path_hooks = PySys_GetObject("path_hooks"))) { - importer = get_path_importer(path_importer_cache, - path_hooks, path); - } - } - Py_XINCREF(importer); /* get_path_importer returns a borrowed reference */ - return importer; + if ((path_importer_cache = PySys_GetObject("path_importer_cache"))) { + if ((path_hooks = PySys_GetObject("path_hooks"))) { + importer = get_path_importer(path_importer_cache, + path_hooks, path); + } + } + Py_XINCREF(importer); /* get_path_importer returns a borrowed reference */ + return importer; } /* Search the path (default sys.path) for a module. Return the @@ -1510,7 +1510,7 @@ PyImport_GetImporter(PyObject *path) { #ifdef MS_COREDLL extern FILE *PyWin_FindRegisteredModule(const char *, struct filedescr **, - char *, Py_ssize_t); + char *, Py_ssize_t); #endif static int case_ok(char *, Py_ssize_t, Py_ssize_t, char *); @@ -1519,276 +1519,276 @@ 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; - struct stat statbuf; - 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]; + 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; + struct stat statbuf; + 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; + 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 (find_frozen(fullname) != NULL) { - strcpy(buf, fullname); - return &fd_frozen; - } - - if (path == NULL) { - if (is_builtin(name)) { - strcpy(buf, name); - return &fd_builtin; - } + 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 (find_frozen(fullname) != NULL) { + strcpy(buf, fullname); + return &fd_frozen; + } + + if (path == NULL) { + if (is_builtin(name)) { + strcpy(buf, name); + return &fd_builtin; + } #ifdef MS_COREDLL - fp = PyWin_FindRegisteredModule(name, &fdp, buf, buflen); - if (fp != NULL) { - *p_fp = fp; - return fdp; - } + 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 *v = PyList_GetItem(path, i); - PyObject *origv = v; - const char *base; - Py_ssize_t size; - if (!v) - return NULL; - if (PyUnicode_Check(v)) { - v = PyUnicode_AsEncodedString(v, - Py_FileSystemDefaultEncoding, NULL); - if (v == NULL) - return NULL; - } - else if (!PyBytes_Check(v)) - continue; - else - Py_INCREF(v); - - base = PyBytes_AS_STRING(v); - size = PyBytes_GET_SIZE(v); - len = size; - if (len + 2 + namelen + MAXSUFFIXSIZE >= buflen) { - Py_DECREF(v); - continue; /* Too long */ - } - strcpy(buf, base); - Py_DECREF(v); - - if (strlen(buf) != len) { - continue; /* v contains '\0' */ - } - - /* sys.path_hooks import hook */ - if (p_loader != NULL) { - PyObject *importer; - - importer = get_path_importer(path_importer_cache, - path_hooks, origv); - if (importer == NULL) { - return NULL; - } - /* Note: importer is a borrowed reference */ - if (importer != Py_None) { - PyObject *loader; - loader = PyObject_CallMethod(importer, - "find_module", - "s", fullname); - 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 + 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 *v = PyList_GetItem(path, i); + PyObject *origv = v; + const char *base; + Py_ssize_t size; + if (!v) + return NULL; + if (PyUnicode_Check(v)) { + v = PyUnicode_AsEncodedString(v, + Py_FileSystemDefaultEncoding, NULL); + if (v == NULL) + return NULL; + } + else if (!PyBytes_Check(v)) + continue; + else + Py_INCREF(v); + + base = PyBytes_AS_STRING(v); + size = PyBytes_GET_SIZE(v); + len = size; + if (len + 2 + namelen + MAXSUFFIXSIZE >= buflen) { + Py_DECREF(v); + continue; /* Too long */ + } + strcpy(buf, base); + Py_DECREF(v); + + if (strlen(buf) != len) { + continue; /* v contains '\0' */ + } + + /* sys.path_hooks import hook */ + if (p_loader != NULL) { + PyObject *importer; + + importer = get_path_importer(path_importer_cache, + path_hooks, origv); + if (importer == NULL) { + return NULL; + } + /* Note: importer is a borrowed reference */ + if (importer != Py_None) { + PyObject *loader; + loader = PyObject_CallMethod(importer, + "find_module", + "s", fullname); + 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 + && buf[len-1] != ALTSEP #endif - ) - buf[len++] = SEP; - strcpy(buf+len, name); - len += namelen; + ) + 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 */ + /* 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 */ - return &fd_package; - } - else { - char warnstr[MAXPATHLEN+80]; - sprintf(warnstr, "Not importing directory " - "'%.*s': missing __init__.py", - MAXPATHLEN, buf); - if (PyErr_WarnEx(PyExc_ImportWarning, - warnstr, 1)) { - return NULL; - } - } - } + 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 */ + return &fd_package; + } + else { + char warnstr[MAXPATHLEN+80]; + sprintf(warnstr, "Not importing directory " + "'%.*s': missing __init__.py", + MAXPATHLEN, buf); + if (PyErr_WarnEx(PyExc_ImportWarning, + warnstr, 1)) { + return NULL; + } + } + } #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; + /* 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++) { + for (fdp = _PyImport_Filetab; fdp->suffix != NULL; fdp++) { #if defined(PYOS_OS2) && defined(HAVE_DYNAMIC_LOADING) - /* 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'; - } - } + /* 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; - } - } + 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; + /* 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; - } + /* don't need/want the module name snapshot anymore */ + if (saved_buf) + { + free(saved_buf); + saved_buf = NULL; + } #endif - if (fp != NULL) - break; - } - if (fp == NULL) { - PyErr_Format(PyExc_ImportError, - "No module named %.200s", name); - return NULL; - } - *p_fp = fp; - return fdp; + 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 @@ -1796,15 +1796,15 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, */ struct filedescr * _PyImport_FindModule(const char *name, PyObject *path, char *buf, - size_t buflen, FILE **p_fp, PyObject **p_loader) + size_t buflen, FILE **p_fp, PyObject **p_loader) { - return find_module((char *) name, (char *) name, path, - buf, buflen, p_fp, 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; + return fd->type == PY_SOURCE || fd->type == PY_COMPILED; } /* case_ok(char* buf, Py_ssize_t len, Py_ssize_t namelen, char* name) @@ -1860,103 +1860,103 @@ case_ok(char *buf, Py_ssize_t len, Py_ssize_t namelen, char *name) /* 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; + 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; + struct ffblk ffblk; + int done; - if (Py_GETENV("PYTHONCASEOK") != NULL) - return 1; + 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; + 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 = + 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; + dp->d_namlen; #else - strlen(dp->d_name); + 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 */ + if (thislen >= namelen && + strcmp(dp->d_name, nameWithExt) == 0) { + (void)closedir(dirp); + return 1; /* Found */ + } + } + (void)closedir(dirp); + } + return 0 ; /* Not found */ /* OS/2 */ #elif defined(PYOS_OS2) - HDIR hdir = 1; - ULONG srchcnt = 1; - FILEFINDBUF3 ffbuf; - APIRET rc; - - if (Py_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; + HDIR hdir = 1; + ULONG srchcnt = 1; + FILEFINDBUF3 ffbuf; + APIRET rc; + + if (Py_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; + return 1; #endif } @@ -1967,46 +1967,46 @@ case_ok(char *buf, Py_ssize_t len, Py_ssize_t namelen, char *name) 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 -----| + 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; + 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; } #endif /* HAVE_STAT */ @@ -2020,93 +2020,93 @@ static int init_builtin(char *); /* Forward */ static PyObject * load_module(char *name, FILE *fp, char *pathname, int type, PyObject *loader) { - PyObject *modules; - PyObject *m; - int err; + 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; - } - } + /* 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) { + switch (type) { - case PY_SOURCE: - m = load_source_module(name, pathname, fp); - break; + case PY_SOURCE: + m = load_source_module(name, pathname, fp); + break; - case PY_COMPILED: - m = load_compiled_module(name, pathname, fp); - break; + case PY_COMPILED: + m = load_compiled_module(name, pathname, fp); + break; #ifdef HAVE_DYNAMIC_LOADING - case C_EXTENSION: - m = _PyImport_LoadDynamicModule(name, pathname, fp); - break; + case C_EXTENSION: + m = _PyImport_LoadDynamicModule(name, pathname, fp); + break; #endif - case PKG_DIRECTORY: - m = load_package(name, pathname); - break; - - case C_BUILTIN: - case PY_FROZEN: - if (pathname != NULL && pathname[0] != '\0') - name = pathname; - 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; + case PKG_DIRECTORY: + m = load_package(name, pathname); + break; + + case C_BUILTIN: + case PY_FROZEN: + if (pathname != NULL && pathname[0] != '\0') + name = pathname; + 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; } @@ -2117,34 +2117,34 @@ load_module(char *name, FILE *fp, char *pathname, int type, PyObject *loader) 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++) { - PyObject *mod; - 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); - mod = (*p->initfunc)(); - if (mod == 0) - return -1; - if (_PyImport_FixupExtension(mod, name, name) < 0) - return -1; - /* FixupExtension has put the module into sys.modules, - so we can release our own reference. */ - Py_DECREF(mod); - return 1; - } - } - return 0; + struct _inittab *p; + + if (_PyImport_FindExtension(name, name) != NULL) + return 1; + + for (p = PyImport_Inittab; p->name != NULL; p++) { + PyObject *mod; + 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); + mod = (*p->initfunc)(); + if (mod == 0) + return -1; + if (_PyImport_FixupExtension(mod, name, name) < 0) + return -1; + /* FixupExtension has put the module into sys.modules, + so we can release our own reference. */ + Py_DECREF(mod); + return 1; + } + } + return 0; } @@ -2153,63 +2153,63 @@ init_builtin(char *name) static struct _frozen * find_frozen(char *name) { - struct _frozen *p; + struct _frozen *p; - if (!name) - return NULL; + if (!name) + return NULL; - for (p = PyImport_FrozenModules; ; p++) { - if (p->name == NULL) - return NULL; - if (strcmp(p->name, name) == 0) - break; - } - return 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); + 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); } static PyObject * is_frozen_package(char *name) { - struct _frozen *p = find_frozen(name); - int size; + 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 == NULL) { + PyErr_Format(PyExc_ImportError, + "No such frozen object named %.200s", + name); + return NULL; + } - size = p->size; + size = p->size; - if (size < 0) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; + if (size < 0) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; } @@ -2221,67 +2221,67 @@ is_frozen_package(char *name) 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, *l; - int err; - m = PyImport_AddModule(name); - if (m == NULL) - goto err_return; - d = PyModule_GetDict(m); - s = PyUnicode_InternFromString(name); - if (s == NULL) - goto err_return; - l = PyList_New(1); - if (l == NULL) { - Py_DECREF(s); - goto err_return; - } - PyList_SET_ITEM(l, 0, s); - err = PyDict_SetItemString(d, "__path__", l); - Py_DECREF(l); - if (err != 0) - goto err_return; - } - m = PyImport_ExecCodeModuleEx(name, co, ""); - if (m == NULL) - goto err_return; - Py_DECREF(co); - Py_DECREF(m); - return 1; + 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, *l; + int err; + m = PyImport_AddModule(name); + if (m == NULL) + goto err_return; + d = PyModule_GetDict(m); + s = PyUnicode_InternFromString(name); + if (s == NULL) + goto err_return; + l = PyList_New(1); + if (l == NULL) { + Py_DECREF(s); + goto err_return; + } + PyList_SET_ITEM(l, 0, s); + err = PyDict_SetItemString(d, "__path__", l); + Py_DECREF(l); + if (err != 0) + goto err_return; + } + m = PyImport_ExecCodeModuleEx(name, co, ""); + if (m == NULL) + goto err_return; + Py_DECREF(co); + Py_DECREF(m); + return 1; err_return: - Py_DECREF(co); - return -1; + Py_DECREF(co); + return -1; } @@ -2291,15 +2291,15 @@ err_return: PyObject * PyImport_ImportModule(const char *name) { - PyObject *pname; - PyObject *result; + PyObject *pname; + PyObject *result; - pname = PyUnicode_FromString(name); - if (pname == NULL) - return NULL; - result = PyImport_Import(pname); - Py_DECREF(pname); - return result; + pname = PyUnicode_FromString(name); + if (pname == NULL) + return NULL; + result = PyImport_Import(pname); + Py_DECREF(pname); + return result; } /* Import a module without blocking @@ -2314,137 +2314,137 @@ PyImport_ImportModule(const char *name) PyObject * PyImport_ImportModuleNoBlock(const char *name) { - PyObject *result; - PyObject *modules; - long me; - - /* Try to get the module from sys.modules[name] */ - modules = PyImport_GetModuleDict(); - if (modules == NULL) - return NULL; - - result = PyDict_GetItemString(modules, name); - if (result != NULL) { - Py_INCREF(result); - return result; - } - else { - PyErr_Clear(); - } + PyObject *result; + PyObject *modules; + long me; + + /* Try to get the module from sys.modules[name] */ + modules = PyImport_GetModuleDict(); + if (modules == NULL) + return NULL; + + result = PyDict_GetItemString(modules, name); + if (result != NULL) { + Py_INCREF(result); + return result; + } + else { + PyErr_Clear(); + } #ifdef WITH_THREAD - /* check the import lock - * me might be -1 but I ignore the error here, the lock function - * takes care of the problem */ - me = PyThread_get_thread_ident(); - if (import_lock_thread == -1 || import_lock_thread == me) { - /* no thread or me is holding the lock */ - return PyImport_ImportModule(name); - } - else { - PyErr_Format(PyExc_ImportError, - "Failed to import %.200s because the import lock" - "is held by another thread.", - name); - return NULL; - } + /* check the import lock + * me might be -1 but I ignore the error here, the lock function + * takes care of the problem */ + me = PyThread_get_thread_ident(); + if (import_lock_thread == -1 || import_lock_thread == me) { + /* no thread or me is holding the lock */ + return PyImport_ImportModule(name); + } + else { + PyErr_Format(PyExc_ImportError, + "Failed to import %.200s because the import lock" + "is held by another thread.", + name); + return NULL; + } #else - return PyImport_ImportModule(name); + return PyImport_ImportModule(name); #endif } /* Forward declarations for helper routines */ static PyObject *get_parent(PyObject *globals, char *buf, - Py_ssize_t *p_buflen, int level); + 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); + 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); + 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) + PyObject *fromlist, int level) { - char buf[MAXPATHLEN+1]; - Py_ssize_t buflen = 0; - PyObject *parent, *head, *next, *tail; + char buf[MAXPATHLEN+1]; + Py_ssize_t buflen = 0; + PyObject *parent, *head, *next, *tail; - if (strchr(name, '/') != NULL + if (strchr(name, '/') != NULL #ifdef MS_WINDOWS - || strchr(name, '\\') != NULL + || strchr(name, '\\') != NULL #endif - ) { - PyErr_SetString(PyExc_ImportError, - "Import by filename is not supported."); - return NULL; - } - - 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; + ) { + PyErr_SetString(PyExc_ImportError, + "Import by filename is not supported."); + return NULL; + } + + 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; } PyObject * PyImport_ImportModuleLevel(char *name, PyObject *globals, PyObject *locals, - PyObject *fromlist, int level) + PyObject *fromlist, int level) { - PyObject *result; - _PyImport_AcquireLock(); - result = import_module_level(name, globals, locals, fromlist, level); - if (_PyImport_ReleaseLock() < 0) { - Py_XDECREF(result); - PyErr_SetString(PyExc_RuntimeError, - "not holding the import lock"); - return NULL; - } - return result; + PyObject *result; + _PyImport_AcquireLock(); + result = import_module_level(name, globals, locals, fromlist, level); + if (_PyImport_ReleaseLock() < 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 @@ -2461,420 +2461,420 @@ PyImport_ImportModuleLevel(char *name, PyObject *globals, PyObject *locals, static PyObject * get_parent(PyObject *globals, char *buf, Py_ssize_t *p_buflen, int level) { - static PyObject *namestr = NULL; - static PyObject *pathstr = NULL; - static PyObject *pkgstr = NULL; - PyObject *pkgname, *modname, *modpath, *modules, *parent; - int orig_level = level; - - if (globals == NULL || !PyDict_Check(globals) || !level) - return Py_None; - - if (namestr == NULL) { - namestr = PyUnicode_InternFromString("__name__"); - if (namestr == NULL) - return NULL; - } - if (pathstr == NULL) { - pathstr = PyUnicode_InternFromString("__path__"); - if (pathstr == NULL) - return NULL; - } - if (pkgstr == NULL) { - pkgstr = PyUnicode_InternFromString("__package__"); - if (pkgstr == NULL) - return NULL; - } - - *buf = '\0'; - *p_buflen = 0; - pkgname = PyDict_GetItem(globals, pkgstr); - - if ((pkgname != NULL) && (pkgname != Py_None)) { - /* __package__ is set, so use it */ - char *pkgname_str; - Py_ssize_t len; - - if (!PyUnicode_Check(pkgname)) { - PyErr_SetString(PyExc_ValueError, - "__package__ set to non-string"); - return NULL; - } - pkgname_str = _PyUnicode_AsStringAndSize(pkgname, &len); - if (len == 0) { - if (level > 0) { - PyErr_SetString(PyExc_ValueError, - "Attempted relative import in non-package"); - return NULL; - } - return Py_None; - } - if (len > MAXPATHLEN) { - PyErr_SetString(PyExc_ValueError, - "Package name too long"); - return NULL; - } - strcpy(buf, pkgname_str); - } else { - /* __package__ not set, so figure it out and set it */ - modname = PyDict_GetItem(globals, namestr); - if (modname == NULL || !PyUnicode_Check(modname)) - return Py_None; - - modpath = PyDict_GetItem(globals, pathstr); - if (modpath != NULL) { - /* __path__ is set, so modname is already the package name */ - char *modname_str; - Py_ssize_t len; - int error; - - modname_str = _PyUnicode_AsStringAndSize(modname, &len); - if (len > MAXPATHLEN) { - PyErr_SetString(PyExc_ValueError, - "Module name too long"); - return NULL; - } - strcpy(buf, modname_str); - error = PyDict_SetItem(globals, pkgstr, modname); - if (error) { - PyErr_SetString(PyExc_ValueError, - "Could not set __package__"); - return NULL; - } - } else { - /* Normal module, so work out the package name if any */ - char *start = _PyUnicode_AsString(modname); - char *lastdot = strrchr(start, '.'); - size_t len; - int error; - if (lastdot == NULL && level > 0) { - PyErr_SetString(PyExc_ValueError, - "Attempted relative import in non-package"); - return NULL; - } - if (lastdot == NULL) { - error = PyDict_SetItem(globals, pkgstr, Py_None); - if (error) { - PyErr_SetString(PyExc_ValueError, - "Could not set __package__"); - return 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'; - pkgname = PyUnicode_FromString(buf); - if (pkgname == NULL) { - return NULL; - } - error = PyDict_SetItem(globals, pkgstr, pkgname); - Py_DECREF(pkgname); - if (error) { - PyErr_SetString(PyExc_ValueError, - "Could not set __package__"); - return NULL; - } - } - } - 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) { - if (orig_level < 1) { - PyObject *err_msg = PyBytes_FromFormat( - "Parent module '%.200s' not found " - "while handling absolute import", buf); - if (err_msg == NULL) { - return NULL; - } - if (!PyErr_WarnEx(PyExc_RuntimeWarning, - PyBytes_AsString(err_msg), 1)) { - *buf = '\0'; - *p_buflen = 0; - parent = Py_None; - } - Py_DECREF(err_msg); - } else { - PyErr_Format(PyExc_SystemError, - "Parent module '%.200s' not loaded, " - "cannot perform relative import", 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? */ + static PyObject *namestr = NULL; + static PyObject *pathstr = NULL; + static PyObject *pkgstr = NULL; + PyObject *pkgname, *modname, *modpath, *modules, *parent; + int orig_level = level; + + if (globals == NULL || !PyDict_Check(globals) || !level) + return Py_None; + + if (namestr == NULL) { + namestr = PyUnicode_InternFromString("__name__"); + if (namestr == NULL) + return NULL; + } + if (pathstr == NULL) { + pathstr = PyUnicode_InternFromString("__path__"); + if (pathstr == NULL) + return NULL; + } + if (pkgstr == NULL) { + pkgstr = PyUnicode_InternFromString("__package__"); + if (pkgstr == NULL) + return NULL; + } + + *buf = '\0'; + *p_buflen = 0; + pkgname = PyDict_GetItem(globals, pkgstr); + + if ((pkgname != NULL) && (pkgname != Py_None)) { + /* __package__ is set, so use it */ + char *pkgname_str; + Py_ssize_t len; + + if (!PyUnicode_Check(pkgname)) { + PyErr_SetString(PyExc_ValueError, + "__package__ set to non-string"); + return NULL; + } + pkgname_str = _PyUnicode_AsStringAndSize(pkgname, &len); + if (len == 0) { + if (level > 0) { + PyErr_SetString(PyExc_ValueError, + "Attempted relative import in non-package"); + return NULL; + } + return Py_None; + } + if (len > MAXPATHLEN) { + PyErr_SetString(PyExc_ValueError, + "Package name too long"); + return NULL; + } + strcpy(buf, pkgname_str); + } else { + /* __package__ not set, so figure it out and set it */ + modname = PyDict_GetItem(globals, namestr); + if (modname == NULL || !PyUnicode_Check(modname)) + return Py_None; + + modpath = PyDict_GetItem(globals, pathstr); + if (modpath != NULL) { + /* __path__ is set, so modname is already the package name */ + char *modname_str; + Py_ssize_t len; + int error; + + modname_str = _PyUnicode_AsStringAndSize(modname, &len); + if (len > MAXPATHLEN) { + PyErr_SetString(PyExc_ValueError, + "Module name too long"); + return NULL; + } + strcpy(buf, modname_str); + error = PyDict_SetItem(globals, pkgstr, modname); + if (error) { + PyErr_SetString(PyExc_ValueError, + "Could not set __package__"); + return NULL; + } + } else { + /* Normal module, so work out the package name if any */ + char *start = _PyUnicode_AsString(modname); + char *lastdot = strrchr(start, '.'); + size_t len; + int error; + if (lastdot == NULL && level > 0) { + PyErr_SetString(PyExc_ValueError, + "Attempted relative import in non-package"); + return NULL; + } + if (lastdot == NULL) { + error = PyDict_SetItem(globals, pkgstr, Py_None); + if (error) { + PyErr_SetString(PyExc_ValueError, + "Could not set __package__"); + return 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'; + pkgname = PyUnicode_FromString(buf); + if (pkgname == NULL) { + return NULL; + } + error = PyDict_SetItem(globals, pkgstr, pkgname); + Py_DECREF(pkgname); + if (error) { + PyErr_SetString(PyExc_ValueError, + "Could not set __package__"); + return NULL; + } + } + } + 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) { + if (orig_level < 1) { + PyObject *err_msg = PyBytes_FromFormat( + "Parent module '%.200s' not found " + "while handling absolute import", buf); + if (err_msg == NULL) { + return NULL; + } + if (!PyErr_WarnEx(PyExc_RuntimeWarning, + PyBytes_AsString(err_msg), 1)) { + *buf = '\0'; + *p_buflen = 0; + parent = Py_None; + } + Py_DECREF(err_msg); + } else { + PyErr_Format(PyExc_SystemError, + "Parent module '%.200s' not loaded, " + "cannot perform relative import", 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; + 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); + 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 (!PyUnicode_Check(item)) { - PyErr_SetString(PyExc_TypeError, - "Item in ``from list'' not a string"); - Py_DECREF(item); - return 0; - } - if (PyUnicode_AS_UNICODE(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) { - PyObject *item8; - char *subname; - PyObject *submod; - char *p; - if (!Py_FileSystemDefaultEncoding) { - item8 = PyUnicode_EncodeASCII(PyUnicode_AsUnicode(item), - PyUnicode_GetSize(item), - NULL); - } else { - item8 = PyUnicode_AsEncodedString(item, - Py_FileSystemDefaultEncoding, NULL); - } - if (!item8) { - PyErr_SetString(PyExc_ValueError, "Cannot encode path item"); - return 0; - } - subname = PyBytes_AS_STRING(item8); - 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_DECREF(item8); - Py_XDECREF(submod); - if (submod == NULL) { - Py_DECREF(item); - return 0; - } - } - Py_DECREF(item); - } - - /* NOTREACHED */ + 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 (!PyUnicode_Check(item)) { + PyErr_SetString(PyExc_TypeError, + "Item in ``from list'' not a string"); + Py_DECREF(item); + return 0; + } + if (PyUnicode_AS_UNICODE(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) { + PyObject *item8; + char *subname; + PyObject *submod; + char *p; + if (!Py_FileSystemDefaultEncoding) { + item8 = PyUnicode_EncodeASCII(PyUnicode_AsUnicode(item), + PyUnicode_GetSize(item), + NULL); + } else { + item8 = PyUnicode_AsEncodedString(item, + Py_FileSystemDefaultEncoding, NULL); + } + if (!item8) { + PyErr_SetString(PyExc_ValueError, "Cannot encode path item"); + return 0; + } + subname = PyBytes_AS_STRING(item8); + 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_DECREF(item8); + 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; + 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; + 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; } @@ -2884,96 +2884,96 @@ import_submodule(PyObject *mod, char *subname, char *fullname) 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 = (char*)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; - } - existing_m = PyDict_GetItemString(modules_reloading, name); - if (existing_m != NULL) { - /* Due to a recursive reload, this module is already - being reloaded. */ - Py_INCREF(existing_m); - return existing_m; - } - if (PyDict_SetItemString(modules_reloading, name, m) < 0) - return NULL; - - subname = strrchr(name, '.'); - if (subname == NULL) - subname = name; - else { - PyObject *parentname, *parent; - parentname = PyUnicode_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 %U not in sys.modules", - 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; + 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 = (char*)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; + } + existing_m = PyDict_GetItemString(modules_reloading, name); + if (existing_m != NULL) { + /* Due to a recursive reload, this module is already + being reloaded. */ + Py_INCREF(existing_m); + return existing_m; + } + if (PyDict_SetItemString(modules_reloading, name, m) < 0) + return NULL; + + subname = strrchr(name, '.'); + if (subname == NULL) + subname = name; + else { + PyObject *parentname, *parent; + parentname = PyUnicode_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 %U not in sys.modules", + 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; } @@ -2989,68 +2989,68 @@ PyImport_ReloadModule(PyObject *m) 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 = PyUnicode_InternFromString("__import__"); - if (import_str == NULL) - return NULL; - builtins_str = PyUnicode_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 */ - builtins = PyImport_ImportModuleLevel("builtins", - 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 - * Always use absolute import here. */ - r = PyObject_CallFunction(import, "OOOOi", module_name, globals, - globals, silly_list, 0, NULL); + 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 = PyUnicode_InternFromString("__import__"); + if (import_str == NULL) + return NULL; + builtins_str = PyUnicode_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 */ + builtins = PyImport_ImportModuleLevel("builtins", + 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 + * Always use absolute import here. */ + r = PyObject_CallFunction(import, "OOOOi", module_name, globals, + globals, silly_list, 0, NULL); err: - Py_XDECREF(globals); - Py_XDECREF(builtins); - Py_XDECREF(import); + Py_XDECREF(globals); + Py_XDECREF(builtins); + Py_XDECREF(import); - return r; + return r; } @@ -3061,257 +3061,257 @@ PyImport_Import(PyObject *module_name) static PyObject * imp_make_magic(long magic) { - char buf[4]; + char buf[4]; - buf[0] = (char) ((magic >> 0) & 0xff); - buf[1] = (char) ((magic >> 8) & 0xff); - buf[2] = (char) ((magic >> 16) & 0xff); - buf[3] = (char) ((magic >> 24) & 0xff); + buf[0] = (char) ((magic >> 0) & 0xff); + buf[1] = (char) ((magic >> 8) & 0xff); + buf[2] = (char) ((magic >> 16) & 0xff); + buf[3] = (char) ((magic >> 24) & 0xff); - return PyBytes_FromStringAndSize(buf, 4); -}; + return PyBytes_FromStringAndSize(buf, 4); +}; static PyObject * imp_get_magic(PyObject *self, PyObject *noargs) { - return imp_make_magic(pyc_magic); + return imp_make_magic(pyc_magic); } static PyObject * imp_get_tag(PyObject *self, PyObject *noargs) { - return PyUnicode_FromString(pyc_tag); + return PyUnicode_FromString(pyc_tag); } 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; + 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; - PyObject *pathobj; - struct filedescr *fdp; - char pathname[MAXPATHLEN+1]; - FILE *fp = NULL; - int fd = -1; - char *found_encoding = NULL; - char *encoding = 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) { - fd = fileno(fp); - if (fd != -1) - fd = dup(fd); - fclose(fp); - fp = NULL; - } - if (fd != -1) { - if (strchr(fdp->mode, 'b') == NULL) { - /* PyTokenizer_FindEncoding() returns PyMem_MALLOC'ed - memory. */ - found_encoding = PyTokenizer_FindEncoding(fd); - lseek(fd, 0, 0); /* Reset position */ - if (found_encoding == NULL && PyErr_Occurred()) - return NULL; - encoding = (found_encoding != NULL) ? found_encoding : - (char*)PyUnicode_GetDefaultEncoding(); - } - fob = PyFile_FromFd(fd, pathname, fdp->mode, -1, - (char*)encoding, NULL, NULL, 1); - if (fob == NULL) { - close(fd); - PyMem_FREE(found_encoding); - return NULL; - } - } - else { - fob = Py_None; - Py_INCREF(fob); - } - pathobj = PyUnicode_DecodeFSDefault(pathname); - ret = Py_BuildValue("NN(ssi)", - fob, pathobj, fdp->suffix, fdp->mode, fdp->type); - PyMem_FREE(found_encoding); - - return ret; + extern int fclose(FILE *); + PyObject *fob, *ret; + PyObject *pathobj; + struct filedescr *fdp; + char pathname[MAXPATHLEN+1]; + FILE *fp = NULL; + int fd = -1; + char *found_encoding = NULL; + char *encoding = 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) { + fd = fileno(fp); + if (fd != -1) + fd = dup(fd); + fclose(fp); + fp = NULL; + } + if (fd != -1) { + if (strchr(fdp->mode, 'b') == NULL) { + /* PyTokenizer_FindEncoding() returns PyMem_MALLOC'ed + memory. */ + found_encoding = PyTokenizer_FindEncoding(fd); + lseek(fd, 0, 0); /* Reset position */ + if (found_encoding == NULL && PyErr_Occurred()) + return NULL; + encoding = (found_encoding != NULL) ? found_encoding : + (char*)PyUnicode_GetDefaultEncoding(); + } + fob = PyFile_FromFd(fd, pathname, fdp->mode, -1, + (char*)encoding, NULL, NULL, 1); + if (fob == NULL) { + close(fd); + PyMem_FREE(found_encoding); + return NULL; + } + } + else { + fob = Py_None; + Py_INCREF(fob); + } + pathobj = PyUnicode_DecodeFSDefault(pathname); + ret = Py_BuildValue("NN(ssi)", + fob, pathobj, fdp->suffix, fdp->mode, fdp->type); + PyMem_FREE(found_encoding); + + return ret; } static PyObject * imp_find_module(PyObject *self, PyObject *args) { - char *name; - PyObject *ret, *path = NULL; - if (!PyArg_ParseTuple(args, "es|O:find_module", - Py_FileSystemDefaultEncoding, &name, - &path)) - return NULL; - ret = call_find_module(name, path); - PyMem_Free(name); - return ret; + char *name; + PyObject *ret, *path = NULL; + if (!PyArg_ParseTuple(args, "es|O:find_module", + Py_FileSystemDefaultEncoding, &name, + &path)) + return NULL; + ret = call_find_module(name, path); + PyMem_Free(name); + return ret; } 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; + 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; + 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; + char *name; - if (!PyArg_ParseTuple(args, "s:get_frozen_object", &name)) - return NULL; - return get_frozen_object(name); + if (!PyArg_ParseTuple(args, "s:get_frozen_object", &name)) + return NULL; + return get_frozen_object(name); } static PyObject * imp_is_frozen_package(PyObject *self, PyObject *args) { - char *name; + char *name; - if (!PyArg_ParseTuple(args, "s:is_frozen_package", &name)) - return NULL; - return is_frozen_package(name); + if (!PyArg_ParseTuple(args, "s:is_frozen_package", &name)) + return NULL; + return is_frozen_package(name); } static PyObject * imp_is_builtin(PyObject *self, PyObject *args) { - char *name; - if (!PyArg_ParseTuple(args, "s:is_builtin", &name)) - return NULL; - return PyLong_FromLong(is_builtin(name)); + char *name; + if (!PyArg_ParseTuple(args, "s:is_builtin", &name)) + return NULL; + return PyLong_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)); + 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 (mode[0] == 'U') - mode = "r" PY_STDIOTEXTMODE; - if (fob == NULL) { - fp = fopen(pathname, mode); - } - else { - int fd = PyObject_AsFileDescriptor(fob); - if (fd == -1) - return NULL; - if (!_PyVerify_fd(fd)) - goto error; - /* the FILE struct gets a new fd, so that it can be closed - * independently of the file descriptor given - */ - fd = dup(fd); - if (fd == -1) - goto error; - fp = fdopen(fd, mode); - } - if (fp) - return fp; + FILE *fp; + if (mode[0] == 'U') + mode = "r" PY_STDIOTEXTMODE; + if (fob == NULL) { + fp = fopen(pathname, mode); + } + else { + int fd = PyObject_AsFileDescriptor(fob); + if (fd == -1) + return NULL; + if (!_PyVerify_fd(fd)) + goto error; + /* the FILE struct gets a new fd, so that it can be closed + * independently of the file descriptor given + */ + fd = dup(fd); + if (fd == -1) + goto error; + fp = fdopen(fd, mode); + } + if (fp) + return fp; error: - PyErr_SetFromErrno(PyExc_IOError); - return NULL; + PyErr_SetFromErrno(PyExc_IOError); + return NULL; } static PyObject * imp_load_compiled(PyObject *self, PyObject *args) { - char *name; - char *pathname; - PyObject *fob = NULL; - PyObject *m; - FILE *fp; - if (!PyArg_ParseTuple(args, "ses|O:load_compiled", - &name, - Py_FileSystemDefaultEncoding, &pathname, - &fob)) - return NULL; - fp = get_file(pathname, fob, "rb"); - if (fp == NULL) { - PyMem_Free(pathname); - return NULL; - } - m = load_compiled_module(name, pathname, fp); - fclose(fp); - PyMem_Free(pathname); - return m; + char *name; + char *pathname; + PyObject *fob = NULL; + PyObject *m; + FILE *fp; + if (!PyArg_ParseTuple(args, "ses|O:load_compiled", + &name, + Py_FileSystemDefaultEncoding, &pathname, + &fob)) + return NULL; + fp = get_file(pathname, fob, "rb"); + if (fp == NULL) { + PyMem_Free(pathname); + return NULL; + } + m = load_compiled_module(name, pathname, fp); + fclose(fp); + PyMem_Free(pathname); + return m; } #ifdef HAVE_DYNAMIC_LOADING @@ -3319,28 +3319,28 @@ imp_load_compiled(PyObject *self, PyObject *args) 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, "ses|O:load_dynamic", - &name, - Py_FileSystemDefaultEncoding, &pathname, - &fob)) - return NULL; - if (fob) { - fp = get_file(pathname, fob, "r"); - if (fp == NULL) { - PyMem_Free(pathname); - return NULL; - } - } - m = _PyImport_LoadDynamicModule(name, pathname, fp); - PyMem_Free(pathname); - if (fp) - fclose(fp); - return m; + char *name; + char *pathname; + PyObject *fob = NULL; + PyObject *m; + FILE *fp = NULL; + if (!PyArg_ParseTuple(args, "ses|O:load_dynamic", + &name, + Py_FileSystemDefaultEncoding, &pathname, + &fob)) + return NULL; + if (fob) { + fp = get_file(pathname, fob, "r"); + if (fp == NULL) { + PyMem_Free(pathname); + return NULL; + } + } + m = _PyImport_LoadDynamicModule(name, pathname, fp); + PyMem_Free(pathname); + if (fp) + fclose(fp); + return m; } #endif /* HAVE_DYNAMIC_LOADING */ @@ -3348,99 +3348,99 @@ imp_load_dynamic(PyObject *self, PyObject *args) static PyObject * imp_load_source(PyObject *self, PyObject *args) { - char *name; - char *pathname; - PyObject *fob = NULL; - PyObject *m; - FILE *fp; - if (!PyArg_ParseTuple(args, "ses|O:load_source", - &name, - Py_FileSystemDefaultEncoding, &pathname, - &fob)) - return NULL; - fp = get_file(pathname, fob, "r"); - if (fp == NULL) { - PyMem_Free(pathname); - return NULL; - } - m = load_source_module(name, pathname, fp); - PyMem_Free(pathname); - fclose(fp); - return m; + char *name; + char *pathname; + PyObject *fob = NULL; + PyObject *m; + FILE *fp; + if (!PyArg_ParseTuple(args, "ses|O:load_source", + &name, + Py_FileSystemDefaultEncoding, &pathname, + &fob)) + return NULL; + fp = get_file(pathname, fob, "r"); + if (fp == NULL) { + PyMem_Free(pathname); + return NULL; + } + m = load_source_module(name, pathname, fp); + PyMem_Free(pathname); + fclose(fp); + return m; } static PyObject * imp_load_module(PyObject *self, PyObject *args) { - char *name; - PyObject *fob; - char *pathname; - PyObject * ret; - char *suffix; /* Unused */ - char *mode; - int type; - FILE *fp; - - if (!PyArg_ParseTuple(args, "sOes(ssi):load_module", - &name, &fob, - Py_FileSystemDefaultEncoding, &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); - PyMem_Free(pathname); - return NULL; - } - } - if (fob == Py_None) - fp = NULL; - else { - fp = get_file(NULL, fob, mode); - if (fp == NULL) { - PyMem_Free(pathname); - return NULL; - } - } - ret = load_module(name, fp, pathname, type, NULL); - PyMem_Free(pathname); - if (fp) - fclose(fp); - return ret; + char *name; + PyObject *fob; + char *pathname; + PyObject * ret; + char *suffix; /* Unused */ + char *mode; + int type; + FILE *fp; + + if (!PyArg_ParseTuple(args, "sOes(ssi):load_module", + &name, &fob, + Py_FileSystemDefaultEncoding, &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); + PyMem_Free(pathname); + return NULL; + } + } + if (fob == Py_None) + fp = NULL; + else { + fp = get_file(NULL, fob, mode); + if (fp == NULL) { + PyMem_Free(pathname); + return NULL; + } + } + ret = load_module(name, fp, pathname, type, NULL); + PyMem_Free(pathname); + if (fp) + fclose(fp); + return ret; } static PyObject * imp_load_package(PyObject *self, PyObject *args) { - char *name; - char *pathname; - PyObject * ret; - if (!PyArg_ParseTuple(args, "ses:load_package", - &name, Py_FileSystemDefaultEncoding, &pathname)) - return NULL; - ret = load_package(name, pathname); - PyMem_Free(pathname); - return ret; + char *name; + char *pathname; + PyObject * ret; + if (!PyArg_ParseTuple(args, "ses:load_package", + &name, Py_FileSystemDefaultEncoding, &pathname)) + return NULL; + ret = load_package(name, pathname); + PyMem_Free(pathname); + return ret; } 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); + char *name; + if (!PyArg_ParseTuple(args, "s:new_module", &name)) + return NULL; + return PyModule_New(name); } static PyObject * imp_reload(PyObject *self, PyObject *v) { - return PyImport_ReloadModule(v); + return PyImport_ReloadModule(v); } PyDoc_STRVAR(doc_reload, @@ -3451,30 +3451,30 @@ Reload the module. The module must have been successfully imported before."); static PyObject * imp_cache_from_source(PyObject *self, PyObject *args, PyObject *kws) { - static char *kwlist[] = {"path", "debug_override", NULL}; + static char *kwlist[] = {"path", "debug_override", NULL}; - char buf[MAXPATHLEN+1]; - char *pathname, *cpathname; - PyObject *debug_override = Py_None; - int debug = !Py_OptimizeFlag; + char buf[MAXPATHLEN+1]; + char *pathname, *cpathname; + PyObject *debug_override = Py_None; + int debug = !Py_OptimizeFlag; - if (!PyArg_ParseTupleAndKeywords( - args, kws, "es|O", kwlist, - Py_FileSystemDefaultEncoding, &pathname, &debug_override)) - return NULL; + if (!PyArg_ParseTupleAndKeywords( + args, kws, "es|O", kwlist, + Py_FileSystemDefaultEncoding, &pathname, &debug_override)) + return NULL; - if (debug_override != Py_None) - if ((debug = PyObject_IsTrue(debug_override)) < 0) - return NULL; + if (debug_override != Py_None) + if ((debug = PyObject_IsTrue(debug_override)) < 0) + return NULL; - cpathname = make_compiled_pathname(pathname, buf, MAXPATHLEN+1, debug); - PyMem_Free(pathname); + cpathname = make_compiled_pathname(pathname, buf, MAXPATHLEN+1, debug); + PyMem_Free(pathname); - if (cpathname == NULL) { - PyErr_Format(PyExc_SystemError, "path buffer too short"); - return NULL; - } - return PyUnicode_FromString(buf); + if (cpathname == NULL) { + PyErr_Format(PyExc_SystemError, "path buffer too short"); + return NULL; + } + return PyUnicode_FromString(buf); } PyDoc_STRVAR(doc_cache_from_source, @@ -3490,24 +3490,24 @@ the value of __debug__ instead."); static PyObject * imp_source_from_cache(PyObject *self, PyObject *args, PyObject *kws) { - static char *kwlist[] = {"path", NULL}; + static char *kwlist[] = {"path", NULL}; - char *pathname; - char buf[MAXPATHLEN+1]; + char *pathname; + char buf[MAXPATHLEN+1]; - if (!PyArg_ParseTupleAndKeywords( - args, kws, "es", kwlist, - Py_FileSystemDefaultEncoding, &pathname)) - return NULL; + if (!PyArg_ParseTupleAndKeywords( + args, kws, "es", kwlist, + Py_FileSystemDefaultEncoding, &pathname)) + return NULL; - if (make_source_pathname(pathname, buf) == NULL) { - PyErr_Format(PyExc_ValueError, "Not a PEP 3147 pyc path: %s", - pathname); - PyMem_Free(pathname); - return NULL; - } - PyMem_Free(pathname); - return PyUnicode_FromString(buf); + if (make_source_pathname(pathname, buf) == NULL) { + PyErr_Format(PyExc_ValueError, "Not a PEP 3147 pyc path: %s", + pathname); + PyMem_Free(pathname); + return NULL; + } + PyMem_Free(pathname); + return PyUnicode_FromString(buf); } PyDoc_STRVAR(doc_source_from_cache, @@ -3571,46 +3571,46 @@ 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_tag", imp_get_tag, METH_NOARGS, doc_get_tag}, - {"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}, - {"reload", imp_reload, METH_O, doc_reload}, - {"cache_from_source", (PyCFunction)imp_cache_from_source, - METH_VARARGS | METH_KEYWORDS, doc_cache_from_source}, - {"source_from_cache", (PyCFunction)imp_source_from_cache, - METH_VARARGS | METH_KEYWORDS, doc_source_from_cache}, - /* The rest are obsolete */ - {"get_frozen_object", imp_get_frozen_object, METH_VARARGS}, - {"is_frozen_package", imp_is_frozen_package, 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}, + {"find_module", imp_find_module, METH_VARARGS, doc_find_module}, + {"get_magic", imp_get_magic, METH_NOARGS, doc_get_magic}, + {"get_tag", imp_get_tag, METH_NOARGS, doc_get_tag}, + {"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}, + {"reload", imp_reload, METH_O, doc_reload}, + {"cache_from_source", (PyCFunction)imp_cache_from_source, + METH_VARARGS | METH_KEYWORDS, doc_cache_from_source}, + {"source_from_cache", (PyCFunction)imp_source_from_cache, + METH_VARARGS | METH_KEYWORDS, doc_source_from_cache}, + /* The rest are obsolete */ + {"get_frozen_object", imp_get_frozen_object, METH_VARARGS}, + {"is_frozen_package", imp_is_frozen_package, 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}, + {"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 */ + {"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; + PyObject *v; + int err; - v = PyLong_FromLong((long)value); - err = PyDict_SetItemString(d, name, v); - Py_XDECREF(v); - return err; + v = PyLong_FromLong((long)value); + err = PyDict_SetItemString(d, name, v); + Py_XDECREF(v); + return err; } typedef struct { @@ -3620,158 +3620,158 @@ typedef struct { static int NullImporter_init(NullImporter *self, PyObject *args, PyObject *kwds) { - char *path; - Py_ssize_t pathlen; + char *path; + Py_ssize_t pathlen; - if (!_PyArg_NoKeywords("NullImporter()", kwds)) - return -1; + if (!_PyArg_NoKeywords("NullImporter()", kwds)) + return -1; - if (!PyArg_ParseTuple(args, "es:NullImporter", - Py_FileSystemDefaultEncoding, &path)) - return -1; + if (!PyArg_ParseTuple(args, "es:NullImporter", + Py_FileSystemDefaultEncoding, &path)) + return -1; - pathlen = strlen(path); - if (pathlen == 0) { - PyMem_Free(path); - PyErr_SetString(PyExc_ImportError, "empty pathname"); - return -1; - } else { + pathlen = strlen(path); + if (pathlen == 0) { + PyMem_Free(path); + PyErr_SetString(PyExc_ImportError, "empty pathname"); + return -1; + } else { #ifndef MS_WINDOWS - struct stat statbuf; - int rv; - - rv = stat(path, &statbuf); - PyMem_Free(path); - if (rv == 0) { - /* it exists */ - if (S_ISDIR(statbuf.st_mode)) { - /* it's a directory */ - PyErr_SetString(PyExc_ImportError, - "existing directory"); - return -1; - } - } + struct stat statbuf; + int rv; + + rv = stat(path, &statbuf); + PyMem_Free(path); + if (rv == 0) { + /* it exists */ + if (S_ISDIR(statbuf.st_mode)) { + /* it's a directory */ + PyErr_SetString(PyExc_ImportError, + "existing directory"); + return -1; + } + } #else /* MS_WINDOWS */ - DWORD rv; - /* see issue1293 and issue3677: - * stat() on Windows doesn't recognise paths like - * "e:\\shared\\" and "\\\\whiterab-c2znlh\\shared" as dirs. - */ - rv = GetFileAttributesA(path); - PyMem_Free(path); - if (rv != INVALID_FILE_ATTRIBUTES) { - /* it exists */ - if (rv & FILE_ATTRIBUTE_DIRECTORY) { - /* it's a directory */ - PyErr_SetString(PyExc_ImportError, - "existing directory"); - return -1; - } - } + DWORD rv; + /* see issue1293 and issue3677: + * stat() on Windows doesn't recognise paths like + * "e:\\shared\\" and "\\\\whiterab-c2znlh\\shared" as dirs. + */ + rv = GetFileAttributesA(path); + PyMem_Free(path); + if (rv != INVALID_FILE_ATTRIBUTES) { + /* it exists */ + if (rv & FILE_ATTRIBUTE_DIRECTORY) { + /* it's a directory */ + PyErr_SetString(PyExc_ImportError, + "existing directory"); + return -1; + } + } #endif - } - return 0; + } + return 0; } static PyObject * NullImporter_find_module(NullImporter *self, PyObject *args) { - Py_RETURN_NONE; + Py_RETURN_NONE; } static PyMethodDef NullImporter_methods[] = { - {"find_module", (PyCFunction)NullImporter_find_module, METH_VARARGS, - "Always return None" - }, - {NULL} /* Sentinel */ + {"find_module", (PyCFunction)NullImporter_find_module, METH_VARARGS, + "Always return None" + }, + {NULL} /* Sentinel */ }; PyTypeObject PyNullImporter_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "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_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 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 */ + PyVarObject_HEAD_INIT(NULL, 0) + "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_reserved*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 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 */ }; static struct PyModuleDef impmodule = { - PyModuleDef_HEAD_INIT, - "imp", - doc_imp, - 0, - imp_methods, - NULL, - NULL, - NULL, - NULL + PyModuleDef_HEAD_INIT, + "imp", + doc_imp, + 0, + imp_methods, + NULL, + NULL, + NULL, + NULL }; PyMODINIT_FUNC PyInit_imp(void) { - PyObject *m, *d; - - if (PyType_Ready(&PyNullImporter_Type) < 0) - return NULL; - - m = PyModule_Create(&impmodule); - 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(&PyNullImporter_Type); - PyModule_AddObject(m, "NullImporter", (PyObject *)&PyNullImporter_Type); - return m; + PyObject *m, *d; + + if (PyType_Ready(&PyNullImporter_Type) < 0) + return NULL; + + m = PyModule_Create(&impmodule); + 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(&PyNullImporter_Type); + PyModule_AddObject(m, "NullImporter", (PyObject *)&PyNullImporter_Type); + return m; failure: - Py_XDECREF(m); - return NULL; + Py_XDECREF(m); + return NULL; } @@ -3785,31 +3785,31 @@ PyInit_imp(void) int PyImport_ExtendInittab(struct _inittab *newtab) { - static struct _inittab *our_copy = NULL; - struct _inittab *p; - int i, n; + 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++) - ; + /* 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; + /* 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)); + /* 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; + return 0; } /* Shorthand to add a single entry given a name and a function */ @@ -3817,14 +3817,14 @@ PyImport_ExtendInittab(struct _inittab *newtab) int PyImport_AppendInittab(const char *name, PyObject* (*initfunc)(void)) { - struct _inittab newtab[2]; + struct _inittab newtab[2]; - memset(newtab, '\0', sizeof newtab); + memset(newtab, '\0', sizeof newtab); - newtab[0].name = (char *)name; - newtab[0].initfunc = initfunc; + newtab[0].name = (char *)name; + newtab[0].initfunc = initfunc; - return PyImport_ExtendInittab(newtab); + return PyImport_ExtendInittab(newtab); } #ifdef __cplusplus diff --git a/Python/importdl.c b/Python/importdl.c index d214ba1bb8..507222b0c2 100644 --- a/Python/importdl.c +++ b/Python/importdl.c @@ -13,76 +13,76 @@ #include "importdl.h" extern dl_funcptr _PyImport_GetDynLoadFunc(const char *name, - const char *shortname, - const char *pathname, FILE *fp); + const char *shortname, + const char *pathname, FILE *fp); PyObject * _PyImport_LoadDynamicModule(char *name, char *pathname, FILE *fp) { - PyObject *m; - PyObject *path; - char *lastdot, *shortname, *packagecontext, *oldcontext; - dl_funcptr p0; - PyObject* (*p)(void); - struct PyModuleDef *def; + PyObject *m; + PyObject *path; + char *lastdot, *shortname, *packagecontext, *oldcontext; + dl_funcptr p0; + PyObject* (*p)(void); + struct PyModuleDef *def; - if ((m = _PyImport_FindExtension(name, pathname)) != NULL) { - Py_INCREF(m); - return m; - } - lastdot = strrchr(name, '.'); - if (lastdot == NULL) { - packagecontext = NULL; - shortname = name; - } - else { - packagecontext = name; - shortname = lastdot+1; - } + if ((m = _PyImport_FindExtension(name, pathname)) != NULL) { + Py_INCREF(m); + return m; + } + lastdot = strrchr(name, '.'); + if (lastdot == NULL) { + packagecontext = NULL; + shortname = name; + } + else { + packagecontext = name; + shortname = lastdot+1; + } - p0 = _PyImport_GetDynLoadFunc(name, shortname, pathname, fp); - p = (PyObject*(*)(void))p0; - if (PyErr_Occurred()) - return NULL; - if (p == NULL) { - PyErr_Format(PyExc_ImportError, - "dynamic module does not define init function (PyInit_%.200s)", - shortname); - return NULL; - } - oldcontext = _Py_PackageContext; - _Py_PackageContext = packagecontext; - m = (*p)(); - _Py_PackageContext = oldcontext; - if (m == NULL) - return NULL; + p0 = _PyImport_GetDynLoadFunc(name, shortname, pathname, fp); + p = (PyObject*(*)(void))p0; + if (PyErr_Occurred()) + return NULL; + if (p == NULL) { + PyErr_Format(PyExc_ImportError, + "dynamic module does not define init function (PyInit_%.200s)", + shortname); + return NULL; + } + oldcontext = _Py_PackageContext; + _Py_PackageContext = packagecontext; + m = (*p)(); + _Py_PackageContext = oldcontext; + if (m == NULL) + return NULL; - if (PyErr_Occurred()) { - Py_DECREF(m); - PyErr_Format(PyExc_SystemError, - "initialization of %s raised unreported exception", - shortname); - return NULL; - } + if (PyErr_Occurred()) { + Py_DECREF(m); + PyErr_Format(PyExc_SystemError, + "initialization of %s raised unreported exception", + shortname); + return NULL; + } - /* Remember pointer to module init function. */ - def = PyModule_GetDef(m); - def->m_base.m_init = p; + /* Remember pointer to module init function. */ + def = PyModule_GetDef(m); + def->m_base.m_init = p; - /* Remember the filename as the __file__ attribute */ - path = PyUnicode_DecodeFSDefault(pathname); - if (PyModule_AddObject(m, "__file__", path) < 0) - PyErr_Clear(); /* Not important enough to report */ + /* Remember the filename as the __file__ attribute */ + path = PyUnicode_DecodeFSDefault(pathname); + if (PyModule_AddObject(m, "__file__", path) < 0) + PyErr_Clear(); /* Not important enough to report */ - if (_PyImport_FixupExtension(m, name, pathname) < 0) - return NULL; - if (Py_VerboseFlag) - PySys_WriteStderr( - "import %s # dynamically loaded from %s\n", - name, pathname); - return m; + if (_PyImport_FixupExtension(m, name, pathname) < 0) + return NULL; + if (Py_VerboseFlag) + PySys_WriteStderr( + "import %s # dynamically loaded from %s\n", + name, pathname); + return m; } #endif /* HAVE_DYNAMIC_LOADING */ diff --git a/Python/importdl.h b/Python/importdl.h index 5a2d45c462..b4d21be6f0 100644 --- a/Python/importdl.h +++ b/Python/importdl.h @@ -8,28 +8,28 @@ extern "C" { /* Definitions for dynamic loading of extension modules */ enum filetype { - SEARCH_ERROR, - PY_SOURCE, - PY_COMPILED, - C_EXTENSION, - PY_RESOURCE, /* Mac only */ - PKG_DIRECTORY, - C_BUILTIN, - PY_FROZEN, - PY_CODERESOURCE, /* Mac only */ - IMP_HOOK + SEARCH_ERROR, + PY_SOURCE, + PY_COMPILED, + C_EXTENSION, + PY_RESOURCE, /* Mac only */ + PKG_DIRECTORY, + C_BUILTIN, + PY_FROZEN, + PY_CODERESOURCE, /* Mac only */ + IMP_HOOK }; struct filedescr { - char *suffix; - char *mode; - enum filetype type; + char *suffix; + char *mode; + enum filetype type; }; extern struct filedescr * _PyImport_Filetab; extern const struct filedescr _PyImport_DynLoadFiletab[]; extern PyObject *_PyImport_LoadDynamicModule(char *name, char *pathname, - FILE *); + FILE *); /* Max length of module suffix searched for -- accommodates "module.slb" */ #define MAXSUFFIXSIZE 12 diff --git a/Python/makeopcodetargets.py b/Python/makeopcodetargets.py index a85ac52151..5d8e5a9a46 100755 --- a/Python/makeopcodetargets.py +++ b/Python/makeopcodetargets.py @@ -28,7 +28,7 @@ def write_contents(f): continue targets[op] = "TARGET_%s" % opname f.write("static void *opcode_targets[256] = {\n") - f.write(",\n".join(["\t&&%s" % s for s in targets])) + f.write(",\n".join([" &&%s" % s for s in targets])) f.write("\n};\n") diff --git a/Python/marshal.c b/Python/marshal.c index 90cd306a92..73d4f374cd 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -24,28 +24,28 @@ #define MAX_MARSHAL_STACK_DEPTH 2000 #endif -#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_TUPLE '(' -#define TYPE_LIST '[' -#define TYPE_DICT '{' -#define TYPE_CODE 'c' -#define TYPE_UNICODE 'u' -#define TYPE_UNKNOWN '?' -#define TYPE_SET '<' -#define TYPE_FROZENSET '>' +#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_TUPLE '(' +#define TYPE_LIST '[' +#define TYPE_DICT '{' +#define TYPE_CODE 'c' +#define TYPE_UNICODE 'u' +#define TYPE_UNKNOWN '?' +#define TYPE_SET '<' +#define TYPE_FROZENSET '>' #define WFERR_OK 0 #define WFERR_UNMARSHALLABLE 1 @@ -53,79 +53,79 @@ #define WFERR_NOMEMORY 3 typedef struct { - FILE *fp; - int error; /* see WFERR_* values */ - 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; + FILE *fp; + int error; /* see WFERR_* values */ + 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) + 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 = PyBytes_Size(p->str); - newsize = size + size + 1024; - if (newsize > 32*1024*1024) { - newsize = size + (size >> 3); /* 12.5% overallocation */ - } - if (_PyBytes_Resize(&p->str, newsize) != 0) { - p->ptr = p->end = NULL; - } - else { - p->ptr = PyBytes_AS_STRING((PyBytesObject *)p->str) + size; - p->end = - PyBytes_AS_STRING((PyBytesObject *)p->str) + newsize; - *p->ptr++ = Py_SAFE_DOWNCAST(c, int, char); - } + Py_ssize_t size, newsize; + if (p->str == NULL) + return; /* An error already occurred */ + size = PyBytes_Size(p->str); + newsize = size + size + 1024; + if (newsize > 32*1024*1024) { + newsize = size + (size >> 3); /* 12.5% overallocation */ + } + if (_PyBytes_Resize(&p->str, newsize) != 0) { + p->ptr = p->end = NULL; + } + else { + p->ptr = PyBytes_AS_STRING((PyBytesObject *)p->str) + size; + p->end = + PyBytes_AS_STRING((PyBytesObject *)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++; - } - } + 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); + 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); + 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); + w_long(x, p); + w_long(x>>32, p); } #endif @@ -144,322 +144,322 @@ w_long64(long x, WFILE *p) static void w_PyLong(const PyLongObject *ob, WFILE *p) { - Py_ssize_t i, j, n, l; - digit d; - - w_byte(TYPE_LONG, p); - if (Py_SIZE(ob) == 0) { - w_long((long)0, p); - return; - } - - /* set l to number of base PyLong_MARSHAL_BASE digits */ - n = ABS(Py_SIZE(ob)); - l = (n-1) * PyLong_MARSHAL_RATIO; - d = ob->ob_digit[n-1]; - assert(d != 0); /* a PyLong is always normalized */ - do { - d >>= PyLong_MARSHAL_SHIFT; - l++; - } while (d != 0); - w_long((long)(Py_SIZE(ob) > 0 ? l : -l), p); - - for (i=0; i < n-1; i++) { - d = ob->ob_digit[i]; - for (j=0; j < PyLong_MARSHAL_RATIO; j++) { - w_short(d & PyLong_MARSHAL_MASK, p); - d >>= PyLong_MARSHAL_SHIFT; - } - assert (d == 0); - } - d = ob->ob_digit[n-1]; - do { - w_short(d & PyLong_MARSHAL_MASK, p); - d >>= PyLong_MARSHAL_SHIFT; - } while (d != 0); + Py_ssize_t i, j, n, l; + digit d; + + w_byte(TYPE_LONG, p); + if (Py_SIZE(ob) == 0) { + w_long((long)0, p); + return; + } + + /* set l to number of base PyLong_MARSHAL_BASE digits */ + n = ABS(Py_SIZE(ob)); + l = (n-1) * PyLong_MARSHAL_RATIO; + d = ob->ob_digit[n-1]; + assert(d != 0); /* a PyLong is always normalized */ + do { + d >>= PyLong_MARSHAL_SHIFT; + l++; + } while (d != 0); + w_long((long)(Py_SIZE(ob) > 0 ? l : -l), p); + + for (i=0; i < n-1; i++) { + d = ob->ob_digit[i]; + for (j=0; j < PyLong_MARSHAL_RATIO; j++) { + w_short(d & PyLong_MARSHAL_MASK, p); + d >>= PyLong_MARSHAL_SHIFT; + } + assert (d == 0); + } + d = ob->ob_digit[n-1]; + do { + w_short(d & PyLong_MARSHAL_MASK, p); + d >>= PyLong_MARSHAL_SHIFT; + } while (d != 0); } static void w_object(PyObject *v, WFILE *p) { - Py_ssize_t i, n; - - p->depth++; - - if (p->depth > MAX_MARSHAL_STACK_DEPTH) { - p->error = WFERR_NESTEDTOODEEP; - } - 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 (PyLong_CheckExact(v)) { - long x = PyLong_AsLong(v); - if ((x == -1) && PyErr_Occurred()) { - PyLongObject *ob = (PyLongObject *)v; - PyErr_Clear(); - w_PyLong(ob, p); - } - else { + Py_ssize_t i, n; + + p->depth++; + + if (p->depth > MAX_MARSHAL_STACK_DEPTH) { + p->error = WFERR_NESTEDTOODEEP; + } + 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 (PyLong_CheckExact(v)) { + long x = PyLong_AsLong(v); + if ((x == -1) && PyErr_Occurred()) { + PyLongObject *ob = (PyLongObject *)v; + PyErr_Clear(); + w_PyLong(ob, p); + } + else { #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 + 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 (PyFloat_CheckExact(v)) { - if (p->version > 1) { - unsigned char buf[8]; - if (_PyFloat_Pack8(PyFloat_AsDouble(v), - buf, 1) < 0) { - p->error = WFERR_UNMARSHALLABLE; - return; - } - w_byte(TYPE_BINARY_FLOAT, p); - w_string((char*)buf, 8, p); - } - else { - char *buf = PyOS_double_to_string(PyFloat_AS_DOUBLE(v), - 'g', 17, 0, NULL); - if (!buf) { - p->error = WFERR_NOMEMORY; - return; - } - n = strlen(buf); - w_byte(TYPE_FLOAT, p); - w_byte((int)n, p); - w_string(buf, (int)n, p); - PyMem_Free(buf); - } - } - else if (PyComplex_CheckExact(v)) { - if (p->version > 1) { - unsigned char buf[8]; - if (_PyFloat_Pack8(PyComplex_RealAsDouble(v), - buf, 1) < 0) { - p->error = WFERR_UNMARSHALLABLE; - return; - } - w_byte(TYPE_BINARY_COMPLEX, p); - w_string((char*)buf, 8, p); - if (_PyFloat_Pack8(PyComplex_ImagAsDouble(v), - buf, 1) < 0) { - p->error = WFERR_UNMARSHALLABLE; - return; - } - w_string((char*)buf, 8, p); - } - else { - char *buf; - w_byte(TYPE_COMPLEX, p); - buf = PyOS_double_to_string(PyComplex_RealAsDouble(v), - 'g', 17, 0, NULL); - if (!buf) { - p->error = WFERR_NOMEMORY; - return; - } - n = strlen(buf); - w_byte((int)n, p); - w_string(buf, (int)n, p); - PyMem_Free(buf); - buf = PyOS_double_to_string(PyComplex_ImagAsDouble(v), - 'g', 17, 0, NULL); - if (!buf) { - p->error = WFERR_NOMEMORY; - return; - } - n = strlen(buf); - w_byte((int)n, p); - w_string(buf, (int)n, p); - PyMem_Free(buf); - } - } - else if (PyBytes_CheckExact(v)) { - w_byte(TYPE_STRING, p); - n = PyBytes_GET_SIZE(v); - if (n > INT_MAX) { - /* huge strings are not supported */ - p->depth--; - p->error = WFERR_UNMARSHALLABLE; - return; - } - w_long((long)n, p); - w_string(PyBytes_AS_STRING(v), (int)n, p); - } - else if (PyUnicode_CheckExact(v)) { - PyObject *utf8; - utf8 = PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(v), - PyUnicode_GET_SIZE(v), - "surrogatepass"); - if (utf8 == NULL) { - p->depth--; - p->error = WFERR_UNMARSHALLABLE; - return; - } - w_byte(TYPE_UNICODE, p); - n = PyBytes_GET_SIZE(utf8); - if (n > INT_MAX) { - p->depth--; - p->error = WFERR_UNMARSHALLABLE; - return; - } - w_long((long)n, p); - w_string(PyBytes_AS_STRING(utf8), (int)n, p); - Py_DECREF(utf8); - } - else if (PyTuple_CheckExact(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_CheckExact(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_CheckExact(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_CheckExact(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 = WFERR_UNMARSHALLABLE; - return; - } - w_long((long)n, p); - it = PyObject_GetIter(v); - if (it == NULL) { - p->depth--; - p->error = WFERR_UNMARSHALLABLE; - return; - } - while ((value = PyIter_Next(it)) != NULL) { - w_object(value, p); - Py_DECREF(value); - } - Py_DECREF(it); - if (PyErr_Occurred()) { - p->depth--; - p->error = WFERR_UNMARSHALLABLE; - 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_kwonlyargcount, 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_CheckBuffer(v)) { - /* Write unknown buffer-style objects as a string */ - char *s; - PyBufferProcs *pb = v->ob_type->tp_as_buffer; - Py_buffer view; - if ((*pb->bf_getbuffer)(v, &view, PyBUF_SIMPLE) != 0) { - w_byte(TYPE_UNKNOWN, p); - p->error = WFERR_UNMARSHALLABLE; - } - w_byte(TYPE_STRING, p); - n = view.len; - s = view.buf; - if (n > INT_MAX) { - p->depth--; - p->error = WFERR_UNMARSHALLABLE; - return; - } - w_long((long)n, p); - w_string(s, (int)n, p); - if (pb->bf_releasebuffer != NULL) - (*pb->bf_releasebuffer)(v, &view); - } - else { - w_byte(TYPE_UNKNOWN, p); - p->error = WFERR_UNMARSHALLABLE; - } - p->depth--; + { + w_byte(TYPE_INT, p); + w_long(x, p); + } + } + } + else if (PyFloat_CheckExact(v)) { + if (p->version > 1) { + unsigned char buf[8]; + if (_PyFloat_Pack8(PyFloat_AsDouble(v), + buf, 1) < 0) { + p->error = WFERR_UNMARSHALLABLE; + return; + } + w_byte(TYPE_BINARY_FLOAT, p); + w_string((char*)buf, 8, p); + } + else { + char *buf = PyOS_double_to_string(PyFloat_AS_DOUBLE(v), + 'g', 17, 0, NULL); + if (!buf) { + p->error = WFERR_NOMEMORY; + return; + } + n = strlen(buf); + w_byte(TYPE_FLOAT, p); + w_byte((int)n, p); + w_string(buf, (int)n, p); + PyMem_Free(buf); + } + } + else if (PyComplex_CheckExact(v)) { + if (p->version > 1) { + unsigned char buf[8]; + if (_PyFloat_Pack8(PyComplex_RealAsDouble(v), + buf, 1) < 0) { + p->error = WFERR_UNMARSHALLABLE; + return; + } + w_byte(TYPE_BINARY_COMPLEX, p); + w_string((char*)buf, 8, p); + if (_PyFloat_Pack8(PyComplex_ImagAsDouble(v), + buf, 1) < 0) { + p->error = WFERR_UNMARSHALLABLE; + return; + } + w_string((char*)buf, 8, p); + } + else { + char *buf; + w_byte(TYPE_COMPLEX, p); + buf = PyOS_double_to_string(PyComplex_RealAsDouble(v), + 'g', 17, 0, NULL); + if (!buf) { + p->error = WFERR_NOMEMORY; + return; + } + n = strlen(buf); + w_byte((int)n, p); + w_string(buf, (int)n, p); + PyMem_Free(buf); + buf = PyOS_double_to_string(PyComplex_ImagAsDouble(v), + 'g', 17, 0, NULL); + if (!buf) { + p->error = WFERR_NOMEMORY; + return; + } + n = strlen(buf); + w_byte((int)n, p); + w_string(buf, (int)n, p); + PyMem_Free(buf); + } + } + else if (PyBytes_CheckExact(v)) { + w_byte(TYPE_STRING, p); + n = PyBytes_GET_SIZE(v); + if (n > INT_MAX) { + /* huge strings are not supported */ + p->depth--; + p->error = WFERR_UNMARSHALLABLE; + return; + } + w_long((long)n, p); + w_string(PyBytes_AS_STRING(v), (int)n, p); + } + else if (PyUnicode_CheckExact(v)) { + PyObject *utf8; + utf8 = PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(v), + PyUnicode_GET_SIZE(v), + "surrogatepass"); + if (utf8 == NULL) { + p->depth--; + p->error = WFERR_UNMARSHALLABLE; + return; + } + w_byte(TYPE_UNICODE, p); + n = PyBytes_GET_SIZE(utf8); + if (n > INT_MAX) { + p->depth--; + p->error = WFERR_UNMARSHALLABLE; + return; + } + w_long((long)n, p); + w_string(PyBytes_AS_STRING(utf8), (int)n, p); + Py_DECREF(utf8); + } + else if (PyTuple_CheckExact(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_CheckExact(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_CheckExact(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_CheckExact(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 = WFERR_UNMARSHALLABLE; + return; + } + w_long((long)n, p); + it = PyObject_GetIter(v); + if (it == NULL) { + p->depth--; + p->error = WFERR_UNMARSHALLABLE; + return; + } + while ((value = PyIter_Next(it)) != NULL) { + w_object(value, p); + Py_DECREF(value); + } + Py_DECREF(it); + if (PyErr_Occurred()) { + p->depth--; + p->error = WFERR_UNMARSHALLABLE; + 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_kwonlyargcount, 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_CheckBuffer(v)) { + /* Write unknown buffer-style objects as a string */ + char *s; + PyBufferProcs *pb = v->ob_type->tp_as_buffer; + Py_buffer view; + if ((*pb->bf_getbuffer)(v, &view, PyBUF_SIMPLE) != 0) { + w_byte(TYPE_UNKNOWN, p); + p->error = WFERR_UNMARSHALLABLE; + } + w_byte(TYPE_STRING, p); + n = view.len; + s = view.buf; + if (n > INT_MAX) { + p->depth--; + p->error = WFERR_UNMARSHALLABLE; + return; + } + w_long((long)n, p); + w_string(s, (int)n, p); + if (pb->bf_releasebuffer != NULL) + (*pb->bf_releasebuffer)(v, &view); + } + else { + w_byte(TYPE_UNKNOWN, p); + p->error = WFERR_UNMARSHALLABLE; + } + 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 = WFERR_OK; - wf.depth = 0; - wf.strings = NULL; - wf.version = version; - w_long(x, &wf); + WFILE wf; + wf.fp = fp; + wf.error = WFERR_OK; + 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 = WFERR_OK; - wf.depth = 0; - wf.strings = (version > 0) ? PyDict_New() : NULL; - wf.version = version; - w_object(x, &wf); - Py_XDECREF(wf.strings); + WFILE wf; + wf.fp = fp; + wf.error = WFERR_OK; + 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 */ @@ -471,49 +471,49 @@ typedef WFILE RFILE; /* Same struct with different invariants */ 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; + 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; + 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; - } + 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); + /* Sign extension for 64-bit machines */ + x |= -(x & 0x80000000L); #endif - return x; + return x; } /* r_long64 deals with the TYPE_INT64 code. On a machine with @@ -526,534 +526,534 @@ r_long(RFILE *p) static PyObject * r_long64(RFILE *p) { - long lo4 = r_long(p); - long hi4 = r_long(p); + long lo4 = r_long(p); + long hi4 = r_long(p); #if SIZEOF_LONG > 4 - long x = (hi4 << 32) | (lo4 & 0xFFFFFFFFL); - return PyLong_FromLong(x); + long x = (hi4 << 32) | (lo4 & 0xFFFFFFFFL); + return PyLong_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); + 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_PyLong(RFILE *p) { - PyLongObject *ob; - int size, i, j, md, shorts_in_top_digit; - long n; - digit d; - - n = r_long(p); - if (n == 0) - return (PyObject *)_PyLong_New(0); - if (n < -INT_MAX || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, - "bad marshal data (long size out of range)"); - return NULL; - } - - size = 1 + (ABS(n) - 1) / PyLong_MARSHAL_RATIO; - shorts_in_top_digit = 1 + (ABS(n) - 1) % PyLong_MARSHAL_RATIO; - ob = _PyLong_New(size); - if (ob == NULL) - return NULL; - Py_SIZE(ob) = n > 0 ? size : -size; - - for (i = 0; i < size-1; i++) { - d = 0; - for (j=0; j < PyLong_MARSHAL_RATIO; j++) { - md = r_short(p); - if (md < 0 || md > PyLong_MARSHAL_BASE) - goto bad_digit; - d += (digit)md << j*PyLong_MARSHAL_SHIFT; - } - ob->ob_digit[i] = d; - } - d = 0; - for (j=0; j < shorts_in_top_digit; j++) { - md = r_short(p); - if (md < 0 || md > PyLong_MARSHAL_BASE) - goto bad_digit; - /* topmost marshal digit should be nonzero */ - if (md == 0 && j == shorts_in_top_digit - 1) { - Py_DECREF(ob); - PyErr_SetString(PyExc_ValueError, - "bad marshal data (unnormalized long data)"); - return NULL; - } - d += (digit)md << j*PyLong_MARSHAL_SHIFT; - } - /* top digit should be nonzero, else the resulting PyLong won't be - normalized */ - ob->ob_digit[size-1] = d; - return (PyObject *)ob; + PyLongObject *ob; + int size, i, j, md, shorts_in_top_digit; + long n; + digit d; + + n = r_long(p); + if (n == 0) + return (PyObject *)_PyLong_New(0); + if (n < -INT_MAX || n > INT_MAX) { + PyErr_SetString(PyExc_ValueError, + "bad marshal data (long size out of range)"); + return NULL; + } + + size = 1 + (ABS(n) - 1) / PyLong_MARSHAL_RATIO; + shorts_in_top_digit = 1 + (ABS(n) - 1) % PyLong_MARSHAL_RATIO; + ob = _PyLong_New(size); + if (ob == NULL) + return NULL; + Py_SIZE(ob) = n > 0 ? size : -size; + + for (i = 0; i < size-1; i++) { + d = 0; + for (j=0; j < PyLong_MARSHAL_RATIO; j++) { + md = r_short(p); + if (md < 0 || md > PyLong_MARSHAL_BASE) + goto bad_digit; + d += (digit)md << j*PyLong_MARSHAL_SHIFT; + } + ob->ob_digit[i] = d; + } + d = 0; + for (j=0; j < shorts_in_top_digit; j++) { + md = r_short(p); + if (md < 0 || md > PyLong_MARSHAL_BASE) + goto bad_digit; + /* topmost marshal digit should be nonzero */ + if (md == 0 && j == shorts_in_top_digit - 1) { + Py_DECREF(ob); + PyErr_SetString(PyExc_ValueError, + "bad marshal data (unnormalized long data)"); + return NULL; + } + d += (digit)md << j*PyLong_MARSHAL_SHIFT; + } + /* top digit should be nonzero, else the resulting PyLong won't be + normalized */ + ob->ob_digit[size-1] = d; + return (PyObject *)ob; bad_digit: - Py_DECREF(ob); - PyErr_SetString(PyExc_ValueError, - "bad marshal data (digit out of range in long)"); - return NULL; + Py_DECREF(ob); + PyErr_SetString(PyExc_ValueError, + "bad marshal data (digit out of range in long)"); + return NULL; } 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; - long i, n; - int type = r_byte(p); - PyObject *retval; - - p->depth++; - - if (p->depth > MAX_MARSHAL_STACK_DEPTH) { - p->depth--; - PyErr_SetString(PyExc_ValueError, "recursion limit exceeded"); - return NULL; - } - - switch (type) { - - case EOF: - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - retval = NULL; - break; - - case TYPE_NULL: - retval = NULL; - break; - - case TYPE_NONE: - Py_INCREF(Py_None); - retval = Py_None; - break; - - case TYPE_STOPITER: - Py_INCREF(PyExc_StopIteration); - retval = PyExc_StopIteration; - break; - - case TYPE_ELLIPSIS: - Py_INCREF(Py_Ellipsis); - retval = Py_Ellipsis; - break; - - case TYPE_FALSE: - Py_INCREF(Py_False); - retval = Py_False; - break; - - case TYPE_TRUE: - Py_INCREF(Py_True); - retval = Py_True; - break; - - case TYPE_INT: - retval = PyLong_FromLong(r_long(p)); - break; - - case TYPE_INT64: - retval = r_long64(p); - break; - - case TYPE_LONG: - retval = r_PyLong(p); - break; - - case TYPE_FLOAT: - { - char buf[256]; - double dx; - retval = NULL; - n = r_byte(p); - if (n == EOF || r_string(buf, (int)n, p) != n) { - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - break; - } - buf[n] = '\0'; - dx = PyOS_string_to_double(buf, NULL, NULL); - if (dx == -1.0 && PyErr_Occurred()) - break; - retval = PyFloat_FromDouble(dx); - break; - } - - 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"); - retval = NULL; - break; - } - x = _PyFloat_Unpack8(buf, 1); - if (x == -1.0 && PyErr_Occurred()) { - retval = NULL; - break; - } - retval = PyFloat_FromDouble(x); - break; - } - - case TYPE_COMPLEX: - { - char buf[256]; - Py_complex c; - retval = NULL; - n = r_byte(p); - if (n == EOF || r_string(buf, (int)n, p) != n) { - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - break; - } - buf[n] = '\0'; - c.real = PyOS_string_to_double(buf, NULL, NULL); - if (c.real == -1.0 && PyErr_Occurred()) - break; - n = r_byte(p); - if (n == EOF || r_string(buf, (int)n, p) != n) { - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - break; - } - buf[n] = '\0'; - c.imag = PyOS_string_to_double(buf, NULL, NULL); - if (c.imag == -1.0 && PyErr_Occurred()) - break; - retval = PyComplex_FromCComplex(c); - break; - } - - 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"); - retval = NULL; - break; - } - c.real = _PyFloat_Unpack8(buf, 1); - if (c.real == -1.0 && PyErr_Occurred()) { - retval = NULL; - break; - } - if (r_string((char*)buf, 8, p) != 8) { - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - retval = NULL; - break; - } - c.imag = _PyFloat_Unpack8(buf, 1); - if (c.imag == -1.0 && PyErr_Occurred()) { - retval = NULL; - break; - } - retval = PyComplex_FromCComplex(c); - break; - } - - case TYPE_STRING: - n = r_long(p); - if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data (string size out of range)"); - retval = NULL; - break; - } - v = PyBytes_FromStringAndSize((char *)NULL, n); - if (v == NULL) { - retval = NULL; - break; - } - if (r_string(PyBytes_AS_STRING(v), (int)n, p) != n) { - Py_DECREF(v); - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - retval = NULL; - break; - } - retval = v; - break; - - case TYPE_UNICODE: - { - char *buffer; - - n = r_long(p); - if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data (unicode size out of range)"); - retval = NULL; - break; - } - buffer = PyMem_NEW(char, n); - if (buffer == NULL) { - retval = PyErr_NoMemory(); - break; - } - if (r_string(buffer, (int)n, p) != n) { - PyMem_DEL(buffer); - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - retval = NULL; - break; - } - v = PyUnicode_DecodeUTF8(buffer, n, "surrogatepass"); - PyMem_DEL(buffer); - retval = v; - break; - } - - case TYPE_TUPLE: - n = r_long(p); - if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data (tuple size out of range)"); - retval = NULL; - break; - } - v = PyTuple_New((int)n); - if (v == NULL) { - retval = NULL; - break; - } - 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 for tuple"); - Py_DECREF(v); - v = NULL; - break; - } - PyTuple_SET_ITEM(v, (int)i, v2); - } - retval = v; - break; - - case TYPE_LIST: - n = r_long(p); - if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data (list size out of range)"); - retval = NULL; - break; - } - v = PyList_New((int)n); - if (v == NULL) { - retval = NULL; - break; - } - 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 for list"); - Py_DECREF(v); - v = NULL; - break; - } - PyList_SET_ITEM(v, (int)i, v2); - } - retval = v; - break; - - case TYPE_DICT: - v = PyDict_New(); - if (v == NULL) { - retval = NULL; - break; - } - 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; - } - retval = v; - break; - - case TYPE_SET: - case TYPE_FROZENSET: - n = r_long(p); - if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data (set size out of range)"); - retval = NULL; - break; - } - v = (type == TYPE_SET) ? PySet_New(NULL) : PyFrozenSet_New(NULL); - if (v == NULL) { - retval = NULL; - break; - } - 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 for set"); - Py_DECREF(v); - v = NULL; - break; - } - if (PySet_Add(v, v2) == -1) { - Py_DECREF(v); - Py_DECREF(v2); - v = NULL; - break; - } - Py_DECREF(v2); - } - retval = v; - break; - - case TYPE_CODE: - { - int argcount; - int kwonlyargcount; - 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); - kwonlyargcount = (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, kwonlyargcount, - 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); - } - retval = v; - break; - - default: - /* Bogus data got written, which isn't ideal. - This will let you keep working and recover. */ - PyErr_SetString(PyExc_ValueError, "bad marshal data (unknown type code)"); - retval = NULL; - break; - - } - p->depth--; - return retval; + /* NULL is a valid return value, it does not necessarily means that + an exception is set. */ + PyObject *v, *v2; + long i, n; + int type = r_byte(p); + PyObject *retval; + + p->depth++; + + if (p->depth > MAX_MARSHAL_STACK_DEPTH) { + p->depth--; + PyErr_SetString(PyExc_ValueError, "recursion limit exceeded"); + return NULL; + } + + switch (type) { + + case EOF: + PyErr_SetString(PyExc_EOFError, + "EOF read where object expected"); + retval = NULL; + break; + + case TYPE_NULL: + retval = NULL; + break; + + case TYPE_NONE: + Py_INCREF(Py_None); + retval = Py_None; + break; + + case TYPE_STOPITER: + Py_INCREF(PyExc_StopIteration); + retval = PyExc_StopIteration; + break; + + case TYPE_ELLIPSIS: + Py_INCREF(Py_Ellipsis); + retval = Py_Ellipsis; + break; + + case TYPE_FALSE: + Py_INCREF(Py_False); + retval = Py_False; + break; + + case TYPE_TRUE: + Py_INCREF(Py_True); + retval = Py_True; + break; + + case TYPE_INT: + retval = PyLong_FromLong(r_long(p)); + break; + + case TYPE_INT64: + retval = r_long64(p); + break; + + case TYPE_LONG: + retval = r_PyLong(p); + break; + + case TYPE_FLOAT: + { + char buf[256]; + double dx; + retval = NULL; + n = r_byte(p); + if (n == EOF || r_string(buf, (int)n, p) != n) { + PyErr_SetString(PyExc_EOFError, + "EOF read where object expected"); + break; + } + buf[n] = '\0'; + dx = PyOS_string_to_double(buf, NULL, NULL); + if (dx == -1.0 && PyErr_Occurred()) + break; + retval = PyFloat_FromDouble(dx); + break; + } + + 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"); + retval = NULL; + break; + } + x = _PyFloat_Unpack8(buf, 1); + if (x == -1.0 && PyErr_Occurred()) { + retval = NULL; + break; + } + retval = PyFloat_FromDouble(x); + break; + } + + case TYPE_COMPLEX: + { + char buf[256]; + Py_complex c; + retval = NULL; + n = r_byte(p); + if (n == EOF || r_string(buf, (int)n, p) != n) { + PyErr_SetString(PyExc_EOFError, + "EOF read where object expected"); + break; + } + buf[n] = '\0'; + c.real = PyOS_string_to_double(buf, NULL, NULL); + if (c.real == -1.0 && PyErr_Occurred()) + break; + n = r_byte(p); + if (n == EOF || r_string(buf, (int)n, p) != n) { + PyErr_SetString(PyExc_EOFError, + "EOF read where object expected"); + break; + } + buf[n] = '\0'; + c.imag = PyOS_string_to_double(buf, NULL, NULL); + if (c.imag == -1.0 && PyErr_Occurred()) + break; + retval = PyComplex_FromCComplex(c); + break; + } + + 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"); + retval = NULL; + break; + } + c.real = _PyFloat_Unpack8(buf, 1); + if (c.real == -1.0 && PyErr_Occurred()) { + retval = NULL; + break; + } + if (r_string((char*)buf, 8, p) != 8) { + PyErr_SetString(PyExc_EOFError, + "EOF read where object expected"); + retval = NULL; + break; + } + c.imag = _PyFloat_Unpack8(buf, 1); + if (c.imag == -1.0 && PyErr_Occurred()) { + retval = NULL; + break; + } + retval = PyComplex_FromCComplex(c); + break; + } + + case TYPE_STRING: + n = r_long(p); + if (n < 0 || n > INT_MAX) { + PyErr_SetString(PyExc_ValueError, "bad marshal data (string size out of range)"); + retval = NULL; + break; + } + v = PyBytes_FromStringAndSize((char *)NULL, n); + if (v == NULL) { + retval = NULL; + break; + } + if (r_string(PyBytes_AS_STRING(v), (int)n, p) != n) { + Py_DECREF(v); + PyErr_SetString(PyExc_EOFError, + "EOF read where object expected"); + retval = NULL; + break; + } + retval = v; + break; + + case TYPE_UNICODE: + { + char *buffer; + + n = r_long(p); + if (n < 0 || n > INT_MAX) { + PyErr_SetString(PyExc_ValueError, "bad marshal data (unicode size out of range)"); + retval = NULL; + break; + } + buffer = PyMem_NEW(char, n); + if (buffer == NULL) { + retval = PyErr_NoMemory(); + break; + } + if (r_string(buffer, (int)n, p) != n) { + PyMem_DEL(buffer); + PyErr_SetString(PyExc_EOFError, + "EOF read where object expected"); + retval = NULL; + break; + } + v = PyUnicode_DecodeUTF8(buffer, n, "surrogatepass"); + PyMem_DEL(buffer); + retval = v; + break; + } + + case TYPE_TUPLE: + n = r_long(p); + if (n < 0 || n > INT_MAX) { + PyErr_SetString(PyExc_ValueError, "bad marshal data (tuple size out of range)"); + retval = NULL; + break; + } + v = PyTuple_New((int)n); + if (v == NULL) { + retval = NULL; + break; + } + 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 for tuple"); + Py_DECREF(v); + v = NULL; + break; + } + PyTuple_SET_ITEM(v, (int)i, v2); + } + retval = v; + break; + + case TYPE_LIST: + n = r_long(p); + if (n < 0 || n > INT_MAX) { + PyErr_SetString(PyExc_ValueError, "bad marshal data (list size out of range)"); + retval = NULL; + break; + } + v = PyList_New((int)n); + if (v == NULL) { + retval = NULL; + break; + } + 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 for list"); + Py_DECREF(v); + v = NULL; + break; + } + PyList_SET_ITEM(v, (int)i, v2); + } + retval = v; + break; + + case TYPE_DICT: + v = PyDict_New(); + if (v == NULL) { + retval = NULL; + break; + } + 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; + } + retval = v; + break; + + case TYPE_SET: + case TYPE_FROZENSET: + n = r_long(p); + if (n < 0 || n > INT_MAX) { + PyErr_SetString(PyExc_ValueError, "bad marshal data (set size out of range)"); + retval = NULL; + break; + } + v = (type == TYPE_SET) ? PySet_New(NULL) : PyFrozenSet_New(NULL); + if (v == NULL) { + retval = NULL; + break; + } + 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 for set"); + Py_DECREF(v); + v = NULL; + break; + } + if (PySet_Add(v, v2) == -1) { + Py_DECREF(v); + Py_DECREF(v2); + v = NULL; + break; + } + Py_DECREF(v2); + } + retval = v; + break; + + case TYPE_CODE: + { + int argcount; + int kwonlyargcount; + 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); + kwonlyargcount = (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, kwonlyargcount, + 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); + } + retval = v; + break; + + default: + /* Bogus data got written, which isn't ideal. + This will let you keep working and recover. */ + PyErr_SetString(PyExc_ValueError, "bad marshal data (unknown type code)"); + retval = NULL; + break; + + } + p->depth--; + return retval; } 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 for object"); - return v; + 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 for object"); + 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); + 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; - rf.ptr = rf.end = NULL; - return r_long(&rf); + RFILE rf; + rf.fp = fp; + rf.strings = NULL; + rf.ptr = rf.end = NULL; + return r_long(&rf); } #ifdef HAVE_FSTAT @@ -1061,11 +1061,11 @@ PyMarshal_ReadLongFromFile(FILE *fp) static off_t getfilesize(FILE *fp) { - struct stat st; - if (fstat(fileno(fp), &st) != 0) - return -1; - else - return st.st_size; + struct stat st; + if (fstat(fileno(fp), &st) != 0) + return -1; + else + return st.st_size; } #endif @@ -1081,27 +1081,27 @@ PyMarshal_ReadLastObjectFromFile(FILE *fp) /* REASONABLE_FILE_LIMIT is by defn something big enough for Tkinter.pyc. */ #define REASONABLE_FILE_LIMIT (1L << 18) #ifdef HAVE_FSTAT - off_t filesize; - filesize = getfilesize(fp); - if (filesize > 0 && filesize <= REASONABLE_FILE_LIMIT) { - char* pBuf = (char *)PyMem_MALLOC(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); - PyMem_FREE(pBuf); - return v; - } - - } + off_t filesize; + filesize = getfilesize(fp); + if (filesize > 0 && filesize <= REASONABLE_FILE_LIMIT) { + char* pBuf = (char *)PyMem_MALLOC(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); + 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); + /* 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 REASONABLE_FILE_LIMIT } @@ -1109,77 +1109,77 @@ PyMarshal_ReadLastObjectFromFile(FILE *fp) PyObject * PyMarshal_ReadObjectFromFile(FILE *fp) { - RFILE rf; - PyObject *result; - rf.fp = fp; - rf.strings = PyList_New(0); - rf.depth = 0; - rf.ptr = rf.end = NULL; - result = r_object(&rf); - Py_DECREF(rf.strings); - return result; + RFILE rf; + PyObject *result; + rf.fp = fp; + rf.strings = PyList_New(0); + rf.depth = 0; + rf.ptr = rf.end = NULL; + 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); - rf.depth = 0; - result = r_object(&rf); - Py_DECREF(rf.strings); - return result; + RFILE rf; + PyObject *result; + rf.fp = NULL; + rf.ptr = str; + rf.end = str + len; + rf.strings = PyList_New(0); + rf.depth = 0; + result = r_object(&rf); + Py_DECREF(rf.strings); + return result; } PyObject * PyMarshal_WriteObjectToString(PyObject *x, int version) { - WFILE wf; - PyObject *res = NULL; - - wf.fp = NULL; - wf.str = PyBytes_FromStringAndSize((char *)NULL, 50); - if (wf.str == NULL) - return NULL; - wf.ptr = PyBytes_AS_STRING((PyBytesObject *)wf.str); - wf.end = wf.ptr + PyBytes_Size(wf.str); - wf.error = WFERR_OK; - 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 = PyBytes_AS_STRING((PyBytesObject *)wf.str); - if (wf.ptr - base > PY_SSIZE_T_MAX) { - Py_DECREF(wf.str); - PyErr_SetString(PyExc_OverflowError, - "too much marshal data for a string"); - return NULL; - } - if (_PyBytes_Resize(&wf.str, (Py_ssize_t)(wf.ptr - base)) < 0) - return NULL; - } - if (wf.error != WFERR_OK) { - Py_XDECREF(wf.str); - if (wf.error == WFERR_NOMEMORY) - PyErr_NoMemory(); - else - PyErr_SetString(PyExc_ValueError, - (wf.error==WFERR_UNMARSHALLABLE)?"unmarshallable object" - :"object too deeply nested to marshal"); - return NULL; - } - if (wf.str != NULL) { - /* XXX Quick hack -- need to do this differently */ - res = PyBytes_FromObject(wf.str); - Py_DECREF(wf.str); - } - return res; + WFILE wf; + PyObject *res = NULL; + + wf.fp = NULL; + wf.str = PyBytes_FromStringAndSize((char *)NULL, 50); + if (wf.str == NULL) + return NULL; + wf.ptr = PyBytes_AS_STRING((PyBytesObject *)wf.str); + wf.end = wf.ptr + PyBytes_Size(wf.str); + wf.error = WFERR_OK; + 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 = PyBytes_AS_STRING((PyBytesObject *)wf.str); + if (wf.ptr - base > PY_SSIZE_T_MAX) { + Py_DECREF(wf.str); + PyErr_SetString(PyExc_OverflowError, + "too much marshal data for a string"); + return NULL; + } + if (_PyBytes_Resize(&wf.str, (Py_ssize_t)(wf.ptr - base)) < 0) + return NULL; + } + if (wf.error != WFERR_OK) { + Py_XDECREF(wf.str); + if (wf.error == WFERR_NOMEMORY) + PyErr_NoMemory(); + else + PyErr_SetString(PyExc_ValueError, + (wf.error==WFERR_UNMARSHALLABLE)?"unmarshallable object" + :"object too deeply nested to marshal"); + return NULL; + } + if (wf.str != NULL) { + /* XXX Quick hack -- need to do this differently */ + res = PyBytes_FromObject(wf.str); + Py_DECREF(wf.str); + } + return res; } /* And an interface for Python programs... */ @@ -1187,20 +1187,20 @@ PyMarshal_WriteObjectToString(PyObject *x, int version) static PyObject * marshal_dump(PyObject *self, PyObject *args) { - /* XXX Quick hack -- need to do this differently */ - PyObject *x; - PyObject *f; - int version = Py_MARSHAL_VERSION; - PyObject *s; - PyObject *res; - if (!PyArg_ParseTuple(args, "OO|i:dump", &x, &f, &version)) - return NULL; - s = PyMarshal_WriteObjectToString(x, version); - if (s == NULL) - return NULL; - res = PyObject_CallMethod(f, "write", "O", s); - Py_DECREF(s); - return res; + /* XXX Quick hack -- need to do this differently */ + PyObject *x; + PyObject *f; + int version = Py_MARSHAL_VERSION; + PyObject *s; + PyObject *res; + if (!PyArg_ParseTuple(args, "OO|i:dump", &x, &f, &version)) + return NULL; + s = PyMarshal_WriteObjectToString(x, version); + if (s == NULL) + return NULL; + res = PyObject_CallMethod(f, "write", "O", s); + Py_DECREF(s); + return res; } PyDoc_STRVAR(dump_doc, @@ -1219,35 +1219,35 @@ The version argument indicates the data format that dump should use."); static PyObject * marshal_load(PyObject *self, PyObject *f) { - /* XXX Quick hack -- need to do this differently */ - PyObject *data, *result; - RFILE rf; - data = PyObject_CallMethod(f, "read", ""); - if (data == NULL) - return NULL; - rf.fp = NULL; - if (PyBytes_Check(data)) { - rf.ptr = PyBytes_AS_STRING(data); - rf.end = rf.ptr + PyBytes_GET_SIZE(data); - } - else if (PyBytes_Check(data)) { - rf.ptr = PyBytes_AS_STRING(data); - rf.end = rf.ptr + PyBytes_GET_SIZE(data); - } - else { - PyErr_Format(PyExc_TypeError, - "f.read() returned neither string " - "nor bytes but %.100s", - data->ob_type->tp_name); - Py_DECREF(data); - return NULL; - } - rf.strings = PyList_New(0); - rf.depth = 0; - result = read_object(&rf); - Py_DECREF(rf.strings); - Py_DECREF(data); - return result; + /* XXX Quick hack -- need to do this differently */ + PyObject *data, *result; + RFILE rf; + data = PyObject_CallMethod(f, "read", ""); + if (data == NULL) + return NULL; + rf.fp = NULL; + if (PyBytes_Check(data)) { + rf.ptr = PyBytes_AS_STRING(data); + rf.end = rf.ptr + PyBytes_GET_SIZE(data); + } + else if (PyBytes_Check(data)) { + rf.ptr = PyBytes_AS_STRING(data); + rf.end = rf.ptr + PyBytes_GET_SIZE(data); + } + else { + PyErr_Format(PyExc_TypeError, + "f.read() returned neither string " + "nor bytes but %.100s", + data->ob_type->tp_name); + Py_DECREF(data); + return NULL; + } + rf.strings = PyList_New(0); + rf.depth = 0; + result = read_object(&rf); + Py_DECREF(rf.strings); + Py_DECREF(data); + return result; } PyDoc_STRVAR(load_doc, @@ -1266,11 +1266,11 @@ dump(), load() will substitute None for the unmarshallable type."); 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); + PyObject *x; + int version = Py_MARSHAL_VERSION; + if (!PyArg_ParseTuple(args, "O|i:dumps", &x, &version)) + return NULL; + return PyMarshal_WriteObjectToString(x, version); } PyDoc_STRVAR(dumps_doc, @@ -1286,24 +1286,24 @@ The version argument indicates the data format that dumps should use."); static PyObject * marshal_loads(PyObject *self, PyObject *args) { - RFILE rf; - Py_buffer p; - char *s; - Py_ssize_t n; - PyObject* result; - if (!PyArg_ParseTuple(args, "s*:loads", &p)) - return NULL; - s = p.buf; - n = p.len; - rf.fp = NULL; - rf.ptr = s; - rf.end = s + n; - rf.strings = PyList_New(0); - rf.depth = 0; - result = read_object(&rf); - Py_DECREF(rf.strings); - PyBuffer_Release(&p); - return result; + RFILE rf; + Py_buffer p; + char *s; + Py_ssize_t n; + PyObject* result; + if (!PyArg_ParseTuple(args, "s*:loads", &p)) + return NULL; + s = p.buf; + n = p.len; + rf.fp = NULL; + rf.ptr = s; + rf.end = s + n; + rf.strings = PyList_New(0); + rf.depth = 0; + result = read_object(&rf); + Py_DECREF(rf.strings); + PyBuffer_Release(&p); + return result; } PyDoc_STRVAR(loads_doc, @@ -1314,11 +1314,11 @@ EOFError, ValueError or TypeError. Extra characters in the string are\n\ ignored."); static PyMethodDef marshal_methods[] = { - {"dump", marshal_dump, METH_VARARGS, dump_doc}, - {"load", marshal_load, METH_O, load_doc}, - {"dumps", marshal_dumps, METH_VARARGS, dumps_doc}, - {"loads", marshal_loads, METH_VARARGS, loads_doc}, - {NULL, NULL} /* sentinel */ + {"dump", marshal_dump, METH_VARARGS, dump_doc}, + {"load", marshal_load, METH_O, load_doc}, + {"dumps", marshal_dumps, METH_VARARGS, dumps_doc}, + {"loads", marshal_loads, METH_VARARGS, loads_doc}, + {NULL, NULL} /* sentinel */ }; @@ -1353,23 +1353,23 @@ loads() -- read value from a string"); static struct PyModuleDef marshalmodule = { - PyModuleDef_HEAD_INIT, - "marshal", - module_doc, - 0, - marshal_methods, - NULL, - NULL, - NULL, - NULL + PyModuleDef_HEAD_INIT, + "marshal", + module_doc, + 0, + marshal_methods, + NULL, + NULL, + NULL, + NULL }; PyMODINIT_FUNC PyMarshal_Init(void) { - PyObject *mod = PyModule_Create(&marshalmodule); - if (mod == NULL) - return NULL; - PyModule_AddIntConstant(mod, "version", Py_MARSHAL_VERSION); - return mod; + PyObject *mod = PyModule_Create(&marshalmodule); + if (mod == NULL) + return NULL; + PyModule_AddIntConstant(mod, "version", Py_MARSHAL_VERSION); + return mod; } diff --git a/Python/modsupport.c b/Python/modsupport.c index 0f31634a78..a68e10bc41 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -16,41 +16,41 @@ char *_Py_PackageContext = NULL; 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; + 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; } @@ -66,550 +66,550 @@ 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; + 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; + 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; } static int _ustrlen(Py_UNICODE *u) { - int i = 0; - Py_UNICODE *v = u; - while (*v != 0) { i++; v++; } - return i; + int i = 0; + Py_UNICODE *v = u; + while (*v != 0) { i++; v++; } + return i; } 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; + 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 PyLong_FromLong((long)va_arg(*p_va, int)); - - case 'H': - return PyLong_FromLong((long)va_arg(*p_va, unsigned int)); - - case 'I': - { - unsigned int n; - n = va_arg(*p_va, unsigned int); - return PyLong_FromUnsignedLong(n); - } - - case 'n': + for (;;) { + switch (*(*p_format)++) { + case '(': + return do_mktuple(p_format, p_va, ')', + countformat(*p_format, ')'), flags); + + case '[': + return do_mklist(p_format, p_va, ']', + countformat(*p_format, ']'), flags); + + case '{': + return do_mkdict(p_format, p_va, '}', + countformat(*p_format, '}'), flags); + + case 'b': + case 'B': + case 'h': + case 'i': + return PyLong_FromLong((long)va_arg(*p_va, int)); + + case 'H': + return PyLong_FromLong((long)va_arg(*p_va, unsigned int)); + + case 'I': + { + unsigned int n; + n = va_arg(*p_va, unsigned int); + return PyLong_FromUnsignedLong(n); + } + + case 'n': #if SIZEOF_SIZE_T!=SIZEOF_LONG - return PyLong_FromSsize_t(va_arg(*p_va, Py_ssize_t)); + return PyLong_FromSsize_t(va_arg(*p_va, Py_ssize_t)); #endif - /* Fall through from 'n' to 'l' if Py_ssize_t is long */ - case 'l': - return PyLong_FromLong(va_arg(*p_va, long)); + /* Fall through from 'n' to 'l' if Py_ssize_t is long */ + case 'l': + return PyLong_FromLong(va_arg(*p_va, long)); - case 'k': - { - unsigned long n; - n = va_arg(*p_va, unsigned long); - return PyLong_FromUnsignedLong(n); - } + case 'k': + { + unsigned long n; + n = va_arg(*p_va, unsigned long); + return PyLong_FromUnsignedLong(n); + } #ifdef HAVE_LONG_LONG - case 'L': - return PyLong_FromLongLong((PY_LONG_LONG)va_arg(*p_va, PY_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)); + case 'K': + return PyLong_FromUnsignedLongLong((PY_LONG_LONG)va_arg(*p_va, unsigned PY_LONG_LONG)); #endif - 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; - } - case 'f': - case 'd': - return PyFloat_FromDouble( - (double)va_arg(*p_va, va_double)); - - case 'D': - return PyComplex_FromCComplex( - *((Py_complex *)va_arg(*p_va, Py_complex *))); - - case 'c': - { - char p[1]; - p[0] = (char)va_arg(*p_va, int); - return PyBytes_FromStringAndSize(p, 1); - } - case 'C': - { - int i = va_arg(*p_va, int); - if (i < 0 || i > PyUnicode_GetMax()) { - PyErr_SetString(PyExc_OverflowError, - "%c arg not in range(0x110000)"); - return NULL; - } - return PyUnicode_FromOrdinal(i); - } - - 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 = PyUnicode_FromStringAndSize(str, n); - } - return v; - } - - case 'U': - { - 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 = PyUnicode_FromStringAndSize(str, n); - } - return v; - } - - case 'y': - { - 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 bytes"); - return NULL; - } - n = (Py_ssize_t)m; - } - v = PyBytes_FromStringAndSize(str, n); - } - return v; - } - - case 'N': - case 'S': - case 'O': - if (**p_format == '&') { - typedef PyObject *(*converter)(void *); - converter func = va_arg(*p_va, converter); - void *arg = va_arg(*p_va, void *); - ++*p_format; - return (*func)(arg); - } - else { - PyObject *v; - v = va_arg(*p_va, PyObject *); - if (v != NULL) { - if (*(*p_format - 1) != 'N') - Py_INCREF(v); - } - else if (!PyErr_Occurred()) - /* If a NULL was passed - * because a call that should - * have constructed a value - * failed, that's OK, and we - * pass the error on; but if - * no error occurred it's not - * clear that the caller knew - * what she was doing. */ - PyErr_SetString(PyExc_SystemError, - "NULL object passed to Py_BuildValue"); - return v; - } - - case ':': - case ',': - case ' ': - case '\t': - break; - - default: - PyErr_SetString(PyExc_SystemError, - "bad format char passed to Py_BuildValue"); - return NULL; - - } - } + 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; + } + case 'f': + case 'd': + return PyFloat_FromDouble( + (double)va_arg(*p_va, va_double)); + + case 'D': + return PyComplex_FromCComplex( + *((Py_complex *)va_arg(*p_va, Py_complex *))); + + case 'c': + { + char p[1]; + p[0] = (char)va_arg(*p_va, int); + return PyBytes_FromStringAndSize(p, 1); + } + case 'C': + { + int i = va_arg(*p_va, int); + if (i < 0 || i > PyUnicode_GetMax()) { + PyErr_SetString(PyExc_OverflowError, + "%c arg not in range(0x110000)"); + return NULL; + } + return PyUnicode_FromOrdinal(i); + } + + 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 = PyUnicode_FromStringAndSize(str, n); + } + return v; + } + + case 'U': + { + 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 = PyUnicode_FromStringAndSize(str, n); + } + return v; + } + + case 'y': + { + 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 bytes"); + return NULL; + } + n = (Py_ssize_t)m; + } + v = PyBytes_FromStringAndSize(str, n); + } + return v; + } + + case 'N': + case 'S': + case 'O': + if (**p_format == '&') { + typedef PyObject *(*converter)(void *); + converter func = va_arg(*p_va, converter); + void *arg = va_arg(*p_va, void *); + ++*p_format; + return (*func)(arg); + } + else { + PyObject *v; + v = va_arg(*p_va, PyObject *); + if (v != NULL) { + if (*(*p_format - 1) != 'N') + Py_INCREF(v); + } + else if (!PyErr_Occurred()) + /* If a NULL was passed + * because a call that should + * have constructed a value + * failed, that's OK, and we + * pass the error on; but if + * no error occurred it's not + * clear that the caller knew + * what she was doing. */ + PyErr_SetString(PyExc_SystemError, + "NULL object passed to Py_BuildValue"); + return v; + } + + case ':': + case ',': + case ' ': + case '\t': + break; + + default: + PyErr_SetString(PyExc_SystemError, + "bad format char passed to Py_BuildValue"); + return NULL; + + } + } } PyObject * Py_BuildValue(const char *format, ...) { - va_list va; - PyObject* retval; - va_start(va, format); - retval = va_build_value(format, va, 0); - va_end(va); - return retval; + 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; + 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); + 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); + 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; + const char *f = format; + int n = countformat(f, '\0'); + va_list lva; #ifdef VA_LIST_IS_ARRAY - memcpy(lva, va, sizeof(va_list)); + memcpy(lva, va, sizeof(va_list)); #else #ifdef __va_copy - __va_copy(lva, va); + __va_copy(lva, va); #else - lva = va; + 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); + 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_list vargs; + PyObject *args; + PyObject *res; - va_start(vargs, format); + va_start(vargs, format); - args = Py_VaBuildValue(format, vargs); - va_end(vargs); + args = Py_VaBuildValue(format, vargs); + va_end(vargs); - if (args == NULL) - return NULL; + if (args == NULL) + return NULL; - res = PyEval_CallObject(obj, args); - Py_DECREF(args); + res = PyEval_CallObject(obj, args); + Py_DECREF(args); - return res; + return res; } PyObject * PyEval_CallMethod(PyObject *obj, const char *methodname, const char *format, ...) { - va_list vargs; - PyObject *meth; - PyObject *args; - PyObject *res; + va_list vargs; + PyObject *meth; + PyObject *args; + PyObject *res; - meth = PyObject_GetAttrString(obj, methodname); - if (meth == NULL) - return NULL; + meth = PyObject_GetAttrString(obj, methodname); + if (meth == NULL) + return NULL; - va_start(vargs, format); + va_start(vargs, format); - args = Py_VaBuildValue(format, vargs); - va_end(vargs); + args = Py_VaBuildValue(format, vargs); + va_end(vargs); - if (args == NULL) { - Py_DECREF(meth); - return NULL; - } + if (args == NULL) { + Py_DECREF(meth); + return NULL; + } - res = PyEval_CallObject(meth, args); - Py_DECREF(meth); - Py_DECREF(args); + res = PyEval_CallObject(meth, args); + Py_DECREF(meth); + Py_DECREF(args); - return res; + 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; + 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 +int PyModule_AddIntConstant(PyObject *m, const char *name, long value) { - PyObject *o = PyLong_FromLong(value); - if (!o) - return -1; - if (PyModule_AddObject(m, name, o) == 0) - return 0; - Py_DECREF(o); - return -1; + PyObject *o = PyLong_FromLong(value); + if (!o) + return -1; + if (PyModule_AddObject(m, name, o) == 0) + return 0; + Py_DECREF(o); + return -1; } -int +int PyModule_AddStringConstant(PyObject *m, const char *name, const char *value) { - PyObject *o = PyUnicode_FromString(value); - if (!o) - return -1; - if (PyModule_AddObject(m, name, o) == 0) - return 0; - Py_DECREF(o); - return -1; + PyObject *o = PyUnicode_FromString(value); + if (!o) + return -1; + if (PyModule_AddObject(m, name, o) == 0) + return 0; + Py_DECREF(o); + return -1; } diff --git a/Python/mysnprintf.c b/Python/mysnprintf.c index 8cd412fb3f..a08e249b42 100644 --- a/Python/mysnprintf.c +++ b/Python/mysnprintf.c @@ -19,20 +19,20 @@ Return value (rv): - When 0 <= rv < size, the output conversion was unexceptional, and - rv characters were written to str (excluding a trailing \0 byte at - str[rv]). + When 0 <= rv < size, the output conversion was unexceptional, and + rv characters were written to str (excluding a trailing \0 byte at + str[rv]). - When rv >= size, output conversion was truncated, and a buffer of - size rv+1 would have been needed to avoid truncation. str[size-1] - is \0 in this case. + When rv >= size, output conversion was truncated, and a buffer of + size rv+1 would have been needed to avoid truncation. str[size-1] + is \0 in this case. - When rv < 0, "something bad happened". str[size-1] is \0 in this - case too, but the rest of str is unreliable. It could be that - an error in format codes was detected by libc, or on platforms - with a non-C99 vsnprintf simply that the buffer wasn't big enough - to avoid truncation, or on platforms without any vsnprintf that - PyMem_Malloc couldn't obtain space for a temp buffer. + When rv < 0, "something bad happened". str[size-1] is \0 in this + case too, but the rest of str is unreliable. It could be that + an error in format codes was detected by libc, or on platforms + with a non-C99 vsnprintf simply that the buffer wasn't big enough + to avoid truncation, or on platforms without any vsnprintf that + PyMem_Malloc couldn't obtain space for a temp buffer. CAUTION: Unlike C99, str != NULL and size > 0 are required. */ @@ -40,65 +40,65 @@ int PyOS_snprintf(char *str, size_t size, const char *format, ...) { - int rc; - va_list va; + int rc; + va_list va; - va_start(va, format); - rc = PyOS_vsnprintf(str, size, format, va); - va_end(va); - return rc; + va_start(va, format); + rc = PyOS_vsnprintf(str, size, format, va); + va_end(va); + return rc; } int PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va) { - int len; /* # bytes written, excluding \0 */ + int len; /* # bytes written, excluding \0 */ #ifdef HAVE_SNPRINTF #define _PyOS_vsnprintf_EXTRA_SPACE 1 #else #define _PyOS_vsnprintf_EXTRA_SPACE 512 - char *buffer; + char *buffer; #endif - assert(str != NULL); - assert(size > 0); - assert(format != NULL); - /* We take a size_t as input but return an int. Sanity check - * our input so that it won't cause an overflow in the - * vsnprintf return value or the buffer malloc size. */ - if (size > INT_MAX - _PyOS_vsnprintf_EXTRA_SPACE) { - len = -666; - goto Done; - } + assert(str != NULL); + assert(size > 0); + assert(format != NULL); + /* We take a size_t as input but return an int. Sanity check + * our input so that it won't cause an overflow in the + * vsnprintf return value or the buffer malloc size. */ + if (size > INT_MAX - _PyOS_vsnprintf_EXTRA_SPACE) { + len = -666; + goto Done; + } #ifdef HAVE_SNPRINTF - len = vsnprintf(str, size, format, va); + len = vsnprintf(str, size, format, va); #else - /* Emulate it. */ - buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE); - if (buffer == NULL) { - len = -666; - goto Done; - } - - len = vsprintf(buffer, format, va); - if (len < 0) - /* ignore the error */; - - else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE) - Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf"); - - else { - const size_t to_copy = (size_t)len < size ? - (size_t)len : size - 1; - assert(to_copy < size); - memcpy(str, buffer, to_copy); - str[to_copy] = '\0'; - } - PyMem_FREE(buffer); + /* Emulate it. */ + buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE); + if (buffer == NULL) { + len = -666; + goto Done; + } + + len = vsprintf(buffer, format, va); + if (len < 0) + /* ignore the error */; + + else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE) + Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf"); + + else { + const size_t to_copy = (size_t)len < size ? + (size_t)len : size - 1; + assert(to_copy < size); + memcpy(str, buffer, to_copy); + str[to_copy] = '\0'; + } + PyMem_FREE(buffer); #endif Done: - if (size > 0) - str[size-1] = '\0'; - return len; + if (size > 0) + str[size-1] = '\0'; + return len; #undef _PyOS_vsnprintf_EXTRA_SPACE } diff --git a/Python/mystrtoul.c b/Python/mystrtoul.c index 347f361e03..52502cba46 100644 --- a/Python/mystrtoul.c +++ b/Python/mystrtoul.c @@ -18,43 +18,43 @@ * i * base doesn't overflow unsigned long. */ static unsigned long smallmax[] = { - 0, /* bases 0 and 1 are invalid */ - 0, - ULONG_MAX / 2, - ULONG_MAX / 3, - ULONG_MAX / 4, - ULONG_MAX / 5, - ULONG_MAX / 6, - ULONG_MAX / 7, - ULONG_MAX / 8, - ULONG_MAX / 9, - ULONG_MAX / 10, - ULONG_MAX / 11, - ULONG_MAX / 12, - ULONG_MAX / 13, - ULONG_MAX / 14, - ULONG_MAX / 15, - ULONG_MAX / 16, - ULONG_MAX / 17, - ULONG_MAX / 18, - ULONG_MAX / 19, - ULONG_MAX / 20, - ULONG_MAX / 21, - ULONG_MAX / 22, - ULONG_MAX / 23, - ULONG_MAX / 24, - ULONG_MAX / 25, - ULONG_MAX / 26, - ULONG_MAX / 27, - ULONG_MAX / 28, - ULONG_MAX / 29, - ULONG_MAX / 30, - ULONG_MAX / 31, - ULONG_MAX / 32, - ULONG_MAX / 33, - ULONG_MAX / 34, - ULONG_MAX / 35, - ULONG_MAX / 36, + 0, /* bases 0 and 1 are invalid */ + 0, + ULONG_MAX / 2, + ULONG_MAX / 3, + ULONG_MAX / 4, + ULONG_MAX / 5, + ULONG_MAX / 6, + ULONG_MAX / 7, + ULONG_MAX / 8, + ULONG_MAX / 9, + ULONG_MAX / 10, + ULONG_MAX / 11, + ULONG_MAX / 12, + ULONG_MAX / 13, + ULONG_MAX / 14, + ULONG_MAX / 15, + ULONG_MAX / 16, + ULONG_MAX / 17, + ULONG_MAX / 18, + ULONG_MAX / 19, + ULONG_MAX / 20, + ULONG_MAX / 21, + ULONG_MAX / 22, + ULONG_MAX / 23, + ULONG_MAX / 24, + ULONG_MAX / 25, + ULONG_MAX / 26, + ULONG_MAX / 27, + ULONG_MAX / 28, + ULONG_MAX / 29, + ULONG_MAX / 30, + ULONG_MAX / 31, + ULONG_MAX / 32, + ULONG_MAX / 33, + ULONG_MAX / 34, + ULONG_MAX / 35, + ULONG_MAX / 36, }; /* maximum digits that can't ever overflow for bases 2 through 36, @@ -63,229 +63,229 @@ static unsigned long smallmax[] = { */ #if SIZEOF_LONG == 4 static int digitlimit[] = { - 0, 0, 32, 20, 16, 13, 12, 11, 10, 10, /* 0 - 9 */ - 9, 9, 8, 8, 8, 8, 8, 7, 7, 7, /* 10 - 19 */ - 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, /* 20 - 29 */ - 6, 6, 6, 6, 6, 6, 6}; /* 30 - 36 */ + 0, 0, 32, 20, 16, 13, 12, 11, 10, 10, /* 0 - 9 */ + 9, 9, 8, 8, 8, 8, 8, 7, 7, 7, /* 10 - 19 */ + 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, /* 20 - 29 */ + 6, 6, 6, 6, 6, 6, 6}; /* 30 - 36 */ #elif SIZEOF_LONG == 8 /* [int(math.floor(math.log(2**64, i))) for i in range(2, 37)] */ static int digitlimit[] = { - 0, 0, 64, 40, 32, 27, 24, 22, 21, 20, /* 0 - 9 */ - 19, 18, 17, 17, 16, 16, 16, 15, 15, 15, /* 10 - 19 */ - 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, /* 20 - 29 */ - 13, 12, 12, 12, 12, 12, 12}; /* 30 - 36 */ + 0, 0, 64, 40, 32, 27, 24, 22, 21, 20, /* 0 - 9 */ + 19, 18, 17, 17, 16, 16, 16, 15, 15, 15, /* 10 - 19 */ + 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, /* 20 - 29 */ + 13, 12, 12, 12, 12, 12, 12}; /* 30 - 36 */ #else #error "Need table for SIZEOF_LONG" #endif /* -** strtoul -** This is a general purpose routine for converting -** an ascii string to an integer in an arbitrary base. -** Leading white space is ignored. If 'base' is zero -** it looks for a leading 0b, 0o or 0x to tell which -** base. If these are absent it defaults to 10. -** Base must be 0 or between 2 and 36 (inclusive). -** If 'ptr' is non-NULL it will contain a pointer to -** the end of the scan. -** Errors due to bad pointers will probably result in -** exceptions - we don't check for them. +** strtoul +** This is a general purpose routine for converting +** an ascii string to an integer in an arbitrary base. +** Leading white space is ignored. If 'base' is zero +** it looks for a leading 0b, 0o or 0x to tell which +** base. If these are absent it defaults to 10. +** Base must be 0 or between 2 and 36 (inclusive). +** If 'ptr' is non-NULL it will contain a pointer to +** the end of the scan. +** Errors due to bad pointers will probably result in +** exceptions - we don't check for them. */ unsigned long PyOS_strtoul(register char *str, char **ptr, int base) { - register unsigned long result = 0; /* return value of the function */ - register int c; /* current input character */ - register int ovlimit; /* required digits to overflow */ + register unsigned long result = 0; /* return value of the function */ + register int c; /* current input character */ + register int ovlimit; /* required digits to overflow */ - /* skip leading white space */ - while (*str && isspace(Py_CHARMASK(*str))) - ++str; + /* skip leading white space */ + while (*str && isspace(Py_CHARMASK(*str))) + ++str; - /* check for leading 0b, 0o or 0x for auto-base or base 16 */ - switch (base) { - case 0: /* look for leading 0b, 0o or 0x */ - if (*str == '0') { - ++str; - if (*str == 'x' || *str == 'X') { - /* there must be at least one digit after 0x */ - if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) { - if (ptr) - *ptr = str; - return 0; - } - ++str; - base = 16; - } else if (*str == 'o' || *str == 'O') { - /* there must be at least one digit after 0o */ - if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) { - if (ptr) - *ptr = str; - return 0; - } - ++str; - base = 8; - } else if (*str == 'b' || *str == 'B') { - /* there must be at least one digit after 0b */ - if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) { - if (ptr) - *ptr = str; - return 0; - } - ++str; - base = 2; - } else { - /* skip all zeroes... */ - while (*str == '0') - ++str; - while (isspace(Py_CHARMASK(*str))) - ++str; - if (ptr) - *ptr = str; - return 0; - } - } - else - base = 10; - break; + /* check for leading 0b, 0o or 0x for auto-base or base 16 */ + switch (base) { + case 0: /* look for leading 0b, 0o or 0x */ + if (*str == '0') { + ++str; + if (*str == 'x' || *str == 'X') { + /* there must be at least one digit after 0x */ + if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) { + if (ptr) + *ptr = str; + return 0; + } + ++str; + base = 16; + } else if (*str == 'o' || *str == 'O') { + /* there must be at least one digit after 0o */ + if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) { + if (ptr) + *ptr = str; + return 0; + } + ++str; + base = 8; + } else if (*str == 'b' || *str == 'B') { + /* there must be at least one digit after 0b */ + if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) { + if (ptr) + *ptr = str; + return 0; + } + ++str; + base = 2; + } else { + /* skip all zeroes... */ + while (*str == '0') + ++str; + while (isspace(Py_CHARMASK(*str))) + ++str; + if (ptr) + *ptr = str; + return 0; + } + } + else + base = 10; + break; - /* even with explicit base, skip leading 0? prefix */ - case 16: - if (*str == '0') { - ++str; - if (*str == 'x' || *str == 'X') { - /* there must be at least one digit after 0x */ - if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) { - if (ptr) - *ptr = str; - return 0; - } - ++str; - } - } - break; - case 8: - if (*str == '0') { - ++str; - if (*str == 'o' || *str == 'O') { - /* there must be at least one digit after 0o */ - if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) { - if (ptr) - *ptr = str; - return 0; - } - ++str; - } - } - break; - case 2: - if(*str == '0') { - ++str; - if (*str == 'b' || *str == 'B') { - /* there must be at least one digit after 0b */ - if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) { - if (ptr) - *ptr = str; - return 0; - } - ++str; - } - } - break; - } + /* even with explicit base, skip leading 0? prefix */ + case 16: + if (*str == '0') { + ++str; + if (*str == 'x' || *str == 'X') { + /* there must be at least one digit after 0x */ + if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) { + if (ptr) + *ptr = str; + return 0; + } + ++str; + } + } + break; + case 8: + if (*str == '0') { + ++str; + if (*str == 'o' || *str == 'O') { + /* there must be at least one digit after 0o */ + if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) { + if (ptr) + *ptr = str; + return 0; + } + ++str; + } + } + break; + case 2: + if(*str == '0') { + ++str; + if (*str == 'b' || *str == 'B') { + /* there must be at least one digit after 0b */ + if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) { + if (ptr) + *ptr = str; + return 0; + } + ++str; + } + } + break; + } - /* catch silly bases */ - if (base < 2 || base > 36) { - if (ptr) - *ptr = str; - return 0; - } + /* catch silly bases */ + if (base < 2 || base > 36) { + if (ptr) + *ptr = str; + return 0; + } - /* skip leading zeroes */ - while (*str == '0') - ++str; + /* skip leading zeroes */ + while (*str == '0') + ++str; - /* base is guaranteed to be in [2, 36] at this point */ - ovlimit = digitlimit[base]; + /* base is guaranteed to be in [2, 36] at this point */ + ovlimit = digitlimit[base]; - /* do the conversion until non-digit character encountered */ - while ((c = _PyLong_DigitValue[Py_CHARMASK(*str)]) < base) { - if (ovlimit > 0) /* no overflow check required */ - result = result * base + c; - else { /* requires overflow check */ - register unsigned long temp_result; + /* do the conversion until non-digit character encountered */ + while ((c = _PyLong_DigitValue[Py_CHARMASK(*str)]) < base) { + if (ovlimit > 0) /* no overflow check required */ + result = result * base + c; + else { /* requires overflow check */ + register unsigned long temp_result; - if (ovlimit < 0) /* guaranteed overflow */ - goto overflowed; + if (ovlimit < 0) /* guaranteed overflow */ + goto overflowed; - /* there could be an overflow */ - /* check overflow just from shifting */ - if (result > smallmax[base]) - goto overflowed; + /* there could be an overflow */ + /* check overflow just from shifting */ + if (result > smallmax[base]) + goto overflowed; - result *= base; + result *= base; - /* check overflow from the digit's value */ - temp_result = result + c; - if (temp_result < result) - goto overflowed; + /* check overflow from the digit's value */ + temp_result = result + c; + if (temp_result < result) + goto overflowed; - result = temp_result; - } + result = temp_result; + } - ++str; - --ovlimit; - } + ++str; + --ovlimit; + } - /* set pointer to point to the last character scanned */ - if (ptr) - *ptr = str; + /* set pointer to point to the last character scanned */ + if (ptr) + *ptr = str; - return result; + return result; overflowed: - if (ptr) { - /* spool through remaining digit characters */ - while (_PyLong_DigitValue[Py_CHARMASK(*str)] < base) - ++str; - *ptr = str; - } - errno = ERANGE; - return (unsigned long)-1; + if (ptr) { + /* spool through remaining digit characters */ + while (_PyLong_DigitValue[Py_CHARMASK(*str)] < base) + ++str; + *ptr = str; + } + errno = ERANGE; + return (unsigned long)-1; } /* Checking for overflow in PyOS_strtol is a PITA; see comments * about PY_ABS_LONG_MIN in longobject.c. */ -#define PY_ABS_LONG_MIN (0-(unsigned long)LONG_MIN) +#define PY_ABS_LONG_MIN (0-(unsigned long)LONG_MIN) long PyOS_strtol(char *str, char **ptr, int base) { - long result; - unsigned long uresult; - char sign; + long result; + unsigned long uresult; + char sign; - while (*str && isspace(Py_CHARMASK(*str))) - str++; + while (*str && isspace(Py_CHARMASK(*str))) + str++; - sign = *str; - if (sign == '+' || sign == '-') - str++; + sign = *str; + if (sign == '+' || sign == '-') + str++; - uresult = PyOS_strtoul(str, ptr, base); + uresult = PyOS_strtoul(str, ptr, base); - if (uresult <= (unsigned long)LONG_MAX) { - result = (long)uresult; - if (sign == '-') - result = -result; - } - else if (sign == '-' && uresult == PY_ABS_LONG_MIN) { - result = LONG_MIN; - } - else { - errno = ERANGE; - result = LONG_MAX; - } - return result; + if (uresult <= (unsigned long)LONG_MAX) { + result = (long)uresult; + if (sign == '-') + result = -result; + } + else if (sign == '-' && uresult == PY_ABS_LONG_MIN) { + result = LONG_MIN; + } + else { + errno = ERANGE; + result = LONG_MAX; + } + return result; } diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index deaf0a31b7..20c9f258e4 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -1,258 +1,258 @@ static void *opcode_targets[256] = { - &&_unknown_opcode, - &&TARGET_POP_TOP, - &&TARGET_ROT_TWO, - &&TARGET_ROT_THREE, - &&TARGET_DUP_TOP, - &&TARGET_ROT_FOUR, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&TARGET_NOP, - &&TARGET_UNARY_POSITIVE, - &&TARGET_UNARY_NEGATIVE, - &&TARGET_UNARY_NOT, - &&_unknown_opcode, - &&_unknown_opcode, - &&TARGET_UNARY_INVERT, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&TARGET_BINARY_POWER, - &&TARGET_BINARY_MULTIPLY, - &&_unknown_opcode, - &&TARGET_BINARY_MODULO, - &&TARGET_BINARY_ADD, - &&TARGET_BINARY_SUBTRACT, - &&TARGET_BINARY_SUBSCR, - &&TARGET_BINARY_FLOOR_DIVIDE, - &&TARGET_BINARY_TRUE_DIVIDE, - &&TARGET_INPLACE_FLOOR_DIVIDE, - &&TARGET_INPLACE_TRUE_DIVIDE, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&TARGET_STORE_MAP, - &&TARGET_INPLACE_ADD, - &&TARGET_INPLACE_SUBTRACT, - &&TARGET_INPLACE_MULTIPLY, - &&_unknown_opcode, - &&TARGET_INPLACE_MODULO, - &&TARGET_STORE_SUBSCR, - &&TARGET_DELETE_SUBSCR, - &&TARGET_BINARY_LSHIFT, - &&TARGET_BINARY_RSHIFT, - &&TARGET_BINARY_AND, - &&TARGET_BINARY_XOR, - &&TARGET_BINARY_OR, - &&TARGET_INPLACE_POWER, - &&TARGET_GET_ITER, - &&TARGET_STORE_LOCALS, - &&TARGET_PRINT_EXPR, - &&TARGET_LOAD_BUILD_CLASS, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&TARGET_INPLACE_LSHIFT, - &&TARGET_INPLACE_RSHIFT, - &&TARGET_INPLACE_AND, - &&TARGET_INPLACE_XOR, - &&TARGET_INPLACE_OR, - &&TARGET_BREAK_LOOP, - &&TARGET_WITH_CLEANUP, - &&_unknown_opcode, - &&TARGET_RETURN_VALUE, - &&TARGET_IMPORT_STAR, - &&_unknown_opcode, - &&TARGET_YIELD_VALUE, - &&TARGET_POP_BLOCK, - &&TARGET_END_FINALLY, - &&TARGET_POP_EXCEPT, - &&TARGET_STORE_NAME, - &&TARGET_DELETE_NAME, - &&TARGET_UNPACK_SEQUENCE, - &&TARGET_FOR_ITER, - &&TARGET_UNPACK_EX, - &&TARGET_STORE_ATTR, - &&TARGET_DELETE_ATTR, - &&TARGET_STORE_GLOBAL, - &&TARGET_DELETE_GLOBAL, - &&TARGET_DUP_TOPX, - &&TARGET_LOAD_CONST, - &&TARGET_LOAD_NAME, - &&TARGET_BUILD_TUPLE, - &&TARGET_BUILD_LIST, - &&TARGET_BUILD_SET, - &&TARGET_BUILD_MAP, - &&TARGET_LOAD_ATTR, - &&TARGET_COMPARE_OP, - &&TARGET_IMPORT_NAME, - &&TARGET_IMPORT_FROM, - &&TARGET_JUMP_FORWARD, - &&TARGET_JUMP_IF_FALSE_OR_POP, - &&TARGET_JUMP_IF_TRUE_OR_POP, - &&TARGET_JUMP_ABSOLUTE, - &&TARGET_POP_JUMP_IF_FALSE, - &&TARGET_POP_JUMP_IF_TRUE, - &&TARGET_LOAD_GLOBAL, - &&_unknown_opcode, - &&_unknown_opcode, - &&TARGET_CONTINUE_LOOP, - &&TARGET_SETUP_LOOP, - &&TARGET_SETUP_EXCEPT, - &&TARGET_SETUP_FINALLY, - &&_unknown_opcode, - &&TARGET_LOAD_FAST, - &&TARGET_STORE_FAST, - &&TARGET_DELETE_FAST, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&TARGET_RAISE_VARARGS, - &&TARGET_CALL_FUNCTION, - &&TARGET_MAKE_FUNCTION, - &&TARGET_BUILD_SLICE, - &&TARGET_MAKE_CLOSURE, - &&TARGET_LOAD_CLOSURE, - &&TARGET_LOAD_DEREF, - &&TARGET_STORE_DEREF, - &&_unknown_opcode, - &&_unknown_opcode, - &&TARGET_CALL_FUNCTION_VAR, - &&TARGET_CALL_FUNCTION_KW, - &&TARGET_CALL_FUNCTION_VAR_KW, - &&TARGET_SETUP_WITH, - &&TARGET_EXTENDED_ARG, - &&TARGET_LIST_APPEND, - &&TARGET_SET_ADD, - &&TARGET_MAP_ADD, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode + &&_unknown_opcode, + &&TARGET_POP_TOP, + &&TARGET_ROT_TWO, + &&TARGET_ROT_THREE, + &&TARGET_DUP_TOP, + &&TARGET_ROT_FOUR, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&TARGET_NOP, + &&TARGET_UNARY_POSITIVE, + &&TARGET_UNARY_NEGATIVE, + &&TARGET_UNARY_NOT, + &&_unknown_opcode, + &&_unknown_opcode, + &&TARGET_UNARY_INVERT, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&TARGET_BINARY_POWER, + &&TARGET_BINARY_MULTIPLY, + &&_unknown_opcode, + &&TARGET_BINARY_MODULO, + &&TARGET_BINARY_ADD, + &&TARGET_BINARY_SUBTRACT, + &&TARGET_BINARY_SUBSCR, + &&TARGET_BINARY_FLOOR_DIVIDE, + &&TARGET_BINARY_TRUE_DIVIDE, + &&TARGET_INPLACE_FLOOR_DIVIDE, + &&TARGET_INPLACE_TRUE_DIVIDE, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&TARGET_STORE_MAP, + &&TARGET_INPLACE_ADD, + &&TARGET_INPLACE_SUBTRACT, + &&TARGET_INPLACE_MULTIPLY, + &&_unknown_opcode, + &&TARGET_INPLACE_MODULO, + &&TARGET_STORE_SUBSCR, + &&TARGET_DELETE_SUBSCR, + &&TARGET_BINARY_LSHIFT, + &&TARGET_BINARY_RSHIFT, + &&TARGET_BINARY_AND, + &&TARGET_BINARY_XOR, + &&TARGET_BINARY_OR, + &&TARGET_INPLACE_POWER, + &&TARGET_GET_ITER, + &&TARGET_STORE_LOCALS, + &&TARGET_PRINT_EXPR, + &&TARGET_LOAD_BUILD_CLASS, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&TARGET_INPLACE_LSHIFT, + &&TARGET_INPLACE_RSHIFT, + &&TARGET_INPLACE_AND, + &&TARGET_INPLACE_XOR, + &&TARGET_INPLACE_OR, + &&TARGET_BREAK_LOOP, + &&TARGET_WITH_CLEANUP, + &&_unknown_opcode, + &&TARGET_RETURN_VALUE, + &&TARGET_IMPORT_STAR, + &&_unknown_opcode, + &&TARGET_YIELD_VALUE, + &&TARGET_POP_BLOCK, + &&TARGET_END_FINALLY, + &&TARGET_POP_EXCEPT, + &&TARGET_STORE_NAME, + &&TARGET_DELETE_NAME, + &&TARGET_UNPACK_SEQUENCE, + &&TARGET_FOR_ITER, + &&TARGET_UNPACK_EX, + &&TARGET_STORE_ATTR, + &&TARGET_DELETE_ATTR, + &&TARGET_STORE_GLOBAL, + &&TARGET_DELETE_GLOBAL, + &&TARGET_DUP_TOPX, + &&TARGET_LOAD_CONST, + &&TARGET_LOAD_NAME, + &&TARGET_BUILD_TUPLE, + &&TARGET_BUILD_LIST, + &&TARGET_BUILD_SET, + &&TARGET_BUILD_MAP, + &&TARGET_LOAD_ATTR, + &&TARGET_COMPARE_OP, + &&TARGET_IMPORT_NAME, + &&TARGET_IMPORT_FROM, + &&TARGET_JUMP_FORWARD, + &&TARGET_JUMP_IF_FALSE_OR_POP, + &&TARGET_JUMP_IF_TRUE_OR_POP, + &&TARGET_JUMP_ABSOLUTE, + &&TARGET_POP_JUMP_IF_FALSE, + &&TARGET_POP_JUMP_IF_TRUE, + &&TARGET_LOAD_GLOBAL, + &&_unknown_opcode, + &&_unknown_opcode, + &&TARGET_CONTINUE_LOOP, + &&TARGET_SETUP_LOOP, + &&TARGET_SETUP_EXCEPT, + &&TARGET_SETUP_FINALLY, + &&_unknown_opcode, + &&TARGET_LOAD_FAST, + &&TARGET_STORE_FAST, + &&TARGET_DELETE_FAST, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&TARGET_RAISE_VARARGS, + &&TARGET_CALL_FUNCTION, + &&TARGET_MAKE_FUNCTION, + &&TARGET_BUILD_SLICE, + &&TARGET_MAKE_CLOSURE, + &&TARGET_LOAD_CLOSURE, + &&TARGET_LOAD_DEREF, + &&TARGET_STORE_DEREF, + &&_unknown_opcode, + &&_unknown_opcode, + &&TARGET_CALL_FUNCTION_VAR, + &&TARGET_CALL_FUNCTION_KW, + &&TARGET_CALL_FUNCTION_VAR_KW, + &&TARGET_SETUP_WITH, + &&TARGET_EXTENDED_ARG, + &&TARGET_LIST_APPEND, + &&TARGET_SET_ADD, + &&TARGET_MAP_ADD, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode }; diff --git a/Python/peephole.c b/Python/peephole.c index eeb31d54bd..7deb02d267 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -12,271 +12,271 @@ #include "opcode.h" #define GETARG(arr, i) ((int)((arr[i+2]<<8) + arr[i+1])) -#define UNCONDITIONAL_JUMP(op) (op==JUMP_ABSOLUTE || op==JUMP_FORWARD) +#define UNCONDITIONAL_JUMP(op) (op==JUMP_ABSOLUTE || op==JUMP_FORWARD) #define CONDITIONAL_JUMP(op) (op==POP_JUMP_IF_FALSE || op==POP_JUMP_IF_TRUE \ - || op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP) + || op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP) #define ABSOLUTE_JUMP(op) (op==JUMP_ABSOLUTE || op==CONTINUE_LOOP \ - || op==POP_JUMP_IF_FALSE || op==POP_JUMP_IF_TRUE \ - || op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP) + || op==POP_JUMP_IF_FALSE || op==POP_JUMP_IF_TRUE \ + || op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP) #define JUMPS_ON_TRUE(op) (op==POP_JUMP_IF_TRUE || op==JUMP_IF_TRUE_OR_POP) #define GETJUMPTGT(arr, i) (GETARG(arr,i) + (ABSOLUTE_JUMP(arr[i]) ? 0 : i+3)) #define SETARG(arr, i, val) arr[i+2] = val>>8; arr[i+1] = val & 255 #define CODESIZE(op) (HAS_ARG(op) ? 3 : 1) #define ISBASICBLOCK(blocks, start, bytes) \ - (blocks[start]==blocks[start+bytes-1]) + (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). + 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. + Bails out with no change if one or more of the LOAD_CONSTs is missing. Also works for BUILD_LIST and BUILT_SET when followed by an "in" or "not in" test; for BUILD_SET it assembles a frozenset rather than a tuple. */ static int tuple_of_constants(unsigned char *codestr, Py_ssize_t n, PyObject *consts) { - PyObject *newconst, *constant; - Py_ssize_t i, arg, len_consts; - - /* Pre-conditions */ - assert(PyList_CheckExact(consts)); - assert(codestr[n*3] == BUILD_TUPLE || codestr[n*3] == BUILD_LIST || codestr[n*3] == BUILD_SET); - assert(GETARG(codestr, (n*3)) == n); - for (i=0 ; i 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; + 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_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_INVERT: - newconst = PyNumber_Invert(v); - break; - case UNARY_POSITIVE: - newconst = PyNumber_Positive(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; + 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_INVERT: + newconst = PyNumber_Invert(v); + break; + case UNARY_POSITIVE: + newconst = PyNumber_Positive(v); + break; + default: + /* Called with an unknown opcode */ + PyErr_Format(PyExc_SystemError, + "unexpected unary operation %d on a constant", + opcode); + return 0; + } + if (newconst == NULL) { + PyErr_Clear(); + return 0; + } + + /* Append folded constant into consts table */ + len_consts = PyList_GET_SIZE(consts); + if (PyList_Append(consts, newconst)) { + Py_DECREF(newconst); + return 0; + } + Py_DECREF(newconst); + + /* Write NOP LOAD_CONST newconst */ + codestr[0] = NOP; + codestr[1] = LOAD_CONST; + SETARG(codestr, 1, len_consts); + return 1; } static unsigned int * markblocks(unsigned char *code, Py_ssize_t len) { - unsigned int *blocks = (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= 255. EXTENDED_ARG can appear before MAKE_FUNCTION; in this case both opcodes are skipped. EXTENDED_ARG preceding any other opcode causes the optimizer to bail. 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 + single basic block. All transformations keep the code size the same or + smaller. For those that reduce size, the gaps are initially filled with + NOPs. Later those NOPs are removed and the jump addresses retargeted in a single pass. Line numbering is adjusted accordingly. */ PyObject * PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, PyObject *lineno_obj) { - Py_ssize_t i, j, codelen; - int nops, h, adj; - int tgt, tgttgt, opcode; - unsigned char *codestr = NULL; - unsigned char *lineno; - int *addrmap = NULL; - int new_line, cum_orig_line, last_line, tabsiz; - int cumlc=0, lastlc=0; /* Count runs of consecutive LOAD_CONSTs */ - unsigned int *blocks = NULL; - char *name; - - /* Bail out if an exception is set */ - if (PyErr_Occurred()) - goto exitError; - - /* Bypass optimization when the lineno table is too complex */ - assert(PyBytes_Check(lineno_obj)); - lineno = (unsigned char*)PyBytes_AS_STRING(lineno_obj); - tabsiz = PyBytes_GET_SIZE(lineno_obj); - if (memchr(lineno, 255, tabsiz) != NULL) - goto exitUnchanged; - - /* Avoid situations where jump retargeting could overflow */ - assert(PyBytes_Check(code)); - codelen = PyBytes_GET_SIZE(code); - if (codelen > 32700) - goto exitUnchanged; - - /* Make a modifiable copy of the code string */ - codestr = (unsigned char *)PyMem_Malloc(codelen); - if (codestr == NULL) - goto exitError; - codestr = (unsigned char *)memcpy(codestr, - PyBytes_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 exitError; - - blocks = markblocks(codestr, codelen); - if (blocks == NULL) - goto exitError; - assert(PyList_Check(consts)); - - for (i=0 ; i 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/True/False - with LOAD_CONST None/True/False */ - case LOAD_NAME: - case LOAD_GLOBAL: - j = GETARG(codestr, i); - name = _PyUnicode_AsString(PyTuple_GET_ITEM(names, j)); - h = load_global(codestr, i, name, consts); - if (h < 0) - goto exitError; - else if (h == 0) - continue; - cumlc = lastlc + 1; - break; - - /* Skip over LOAD_CONST trueconst - POP_JUMP_IF_FALSE xx. This improves - "while 1" performance. */ - case LOAD_CONST: - cumlc = lastlc + 1; - j = GETARG(codestr, i); - if (codestr[i+3] != POP_JUMP_IF_FALSE || - !ISBASICBLOCK(blocks,i,6) || - !PyObject_IsTrue(PyList_GET_ITEM(consts, j))) - continue; - memset(codestr+i, NOP, 6); - cumlc = 0; - break; - - /* Try to fold tuples of constants (includes a case for lists and sets - 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: - case BUILD_SET: - 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 || opcode == BUILD_SET) && - 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_INVERT: - case UNARY_POSITIVE: - if (lastlc >= 1 && - ISBASICBLOCK(blocks, i-3, 4) && - fold_unaryops_on_constants(&codestr[i-3], consts)) { - i -= 2; - assert(codestr[i] == LOAD_CONST); - cumlc = 1; - } - break; - - /* Simplify conditional jump to conditional jump where the - result of the first test implies the success of a similar - test or the failure of the opposite test. - Arises in code like: - "if a and b:" - "if a or b:" - "a and b or c" - "(a and b) and c" - x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_FALSE_OR_POP z - --> x:JUMP_IF_FALSE_OR_POP z - x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_TRUE_OR_POP z - --> x:POP_JUMP_IF_FALSE y+3 - where y+3 is the instruction following the second test. - */ - case JUMP_IF_FALSE_OR_POP: - case JUMP_IF_TRUE_OR_POP: - tgt = GETJUMPTGT(codestr, i); - j = codestr[tgt]; - if (CONDITIONAL_JUMP(j)) { - /* NOTE: all possible jumps here are - absolute! */ - if (JUMPS_ON_TRUE(j) == JUMPS_ON_TRUE(opcode)) { - /* The second jump will be - taken iff the first is. */ - tgttgt = GETJUMPTGT(codestr, tgt); - /* The current opcode inherits - its target's stack behaviour */ - codestr[i] = j; - SETARG(codestr, i, tgttgt); - goto reoptimize_current; - } else { - /* The second jump is not taken - if the first is (so jump past - it), and all conditional - jumps pop their argument when - they're not taken (so change - the first jump to pop its - argument when it's taken). */ - if (JUMPS_ON_TRUE(opcode)) - codestr[i] = POP_JUMP_IF_TRUE; - else - codestr[i] = POP_JUMP_IF_FALSE; - SETARG(codestr, i, (tgt + 3)); - goto reoptimize_current; - } - } - /* Intentional fallthrough */ - - /* Replace jumps to unconditional jumps */ - case POP_JUMP_IF_FALSE: - case POP_JUMP_IF_TRUE: - case FOR_ITER: - case JUMP_FORWARD: - case JUMP_ABSOLUTE: - case CONTINUE_LOOP: - case SETUP_LOOP: - case SETUP_EXCEPT: - case SETUP_FINALLY: - case SETUP_WITH: - tgt = GETJUMPTGT(codestr, i); - /* Replace JUMP_* to a RETURN into just a RETURN */ - if (UNCONDITIONAL_JUMP(opcode) && - codestr[tgt] == RETURN_VALUE) { - codestr[i] = RETURN_VALUE; - memset(codestr+i+1, NOP, 2); - continue; - } - if (!UNCONDITIONAL_JUMP(codestr[tgt])) - continue; - tgttgt = GETJUMPTGT(codestr, tgt); - if (opcode == JUMP_FORWARD) /* JMP_ABS can go backwards */ - opcode = JUMP_ABSOLUTE; - if (!ABSOLUTE_JUMP(opcode)) - tgttgt -= i + 3; /* Calc relative jump addr */ - if (tgttgt < 0) /* No backward relative jumps */ - continue; - codestr[i] = opcode; - SETARG(codestr, i, tgttgt); - break; - - case EXTENDED_ARG: - if (codestr[i+3] != MAKE_FUNCTION) - goto exitUnchanged; - /* don't visit MAKE_FUNCTION as GETARG will be wrong */ - i += 3; - break; - - /* Replace RETURN LOAD_CONST None RETURN with just RETURN */ - /* Remove unreachable JUMPs after RETURN */ - case RETURN_VALUE: - if (i+4 >= codelen) - continue; - if (codestr[i+4] == RETURN_VALUE && - ISBASICBLOCK(blocks,i,5)) - memset(codestr+i+1, NOP, 4); - else if (UNCONDITIONAL_JUMP(codestr[i+1]) && - ISBASICBLOCK(blocks,i,4)) - memset(codestr+i+1, NOP, 3); - break; - } - } - - /* Fixup linenotab */ - for (i=0, nops=0 ; i 32700) + goto exitUnchanged; + + /* Make a modifiable copy of the code string */ + codestr = (unsigned char *)PyMem_Malloc(codelen); + if (codestr == NULL) + goto exitError; + codestr = (unsigned char *)memcpy(codestr, + PyBytes_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 exitError; + + blocks = markblocks(codestr, codelen); + if (blocks == NULL) + goto exitError; + assert(PyList_Check(consts)); + + for (i=0 ; i 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/True/False + with LOAD_CONST None/True/False */ + case LOAD_NAME: + case LOAD_GLOBAL: + j = GETARG(codestr, i); + name = _PyUnicode_AsString(PyTuple_GET_ITEM(names, j)); + h = load_global(codestr, i, name, consts); + if (h < 0) + goto exitError; + else if (h == 0) + continue; + cumlc = lastlc + 1; + break; + + /* Skip over LOAD_CONST trueconst + POP_JUMP_IF_FALSE xx. This improves + "while 1" performance. */ + case LOAD_CONST: + cumlc = lastlc + 1; + j = GETARG(codestr, i); + if (codestr[i+3] != POP_JUMP_IF_FALSE || + !ISBASICBLOCK(blocks,i,6) || + !PyObject_IsTrue(PyList_GET_ITEM(consts, j))) + continue; + memset(codestr+i, NOP, 6); + cumlc = 0; + break; + + /* Try to fold tuples of constants (includes a case for lists and sets + 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: + case BUILD_SET: + 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 || opcode == BUILD_SET) && + 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_INVERT: + case UNARY_POSITIVE: + if (lastlc >= 1 && + ISBASICBLOCK(blocks, i-3, 4) && + fold_unaryops_on_constants(&codestr[i-3], consts)) { + i -= 2; + assert(codestr[i] == LOAD_CONST); + cumlc = 1; + } + break; + + /* Simplify conditional jump to conditional jump where the + result of the first test implies the success of a similar + test or the failure of the opposite test. + Arises in code like: + "if a and b:" + "if a or b:" + "a and b or c" + "(a and b) and c" + x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_FALSE_OR_POP z + --> x:JUMP_IF_FALSE_OR_POP z + x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_TRUE_OR_POP z + --> x:POP_JUMP_IF_FALSE y+3 + where y+3 is the instruction following the second test. + */ + case JUMP_IF_FALSE_OR_POP: + case JUMP_IF_TRUE_OR_POP: + tgt = GETJUMPTGT(codestr, i); + j = codestr[tgt]; + if (CONDITIONAL_JUMP(j)) { + /* NOTE: all possible jumps here are + absolute! */ + if (JUMPS_ON_TRUE(j) == JUMPS_ON_TRUE(opcode)) { + /* The second jump will be + taken iff the first is. */ + tgttgt = GETJUMPTGT(codestr, tgt); + /* The current opcode inherits + its target's stack behaviour */ + codestr[i] = j; + SETARG(codestr, i, tgttgt); + goto reoptimize_current; + } else { + /* The second jump is not taken + if the first is (so jump past + it), and all conditional + jumps pop their argument when + they're not taken (so change + the first jump to pop its + argument when it's taken). */ + if (JUMPS_ON_TRUE(opcode)) + codestr[i] = POP_JUMP_IF_TRUE; + else + codestr[i] = POP_JUMP_IF_FALSE; + SETARG(codestr, i, (tgt + 3)); + goto reoptimize_current; + } + } + /* Intentional fallthrough */ + + /* Replace jumps to unconditional jumps */ + case POP_JUMP_IF_FALSE: + case POP_JUMP_IF_TRUE: + case FOR_ITER: + case JUMP_FORWARD: + case JUMP_ABSOLUTE: + case CONTINUE_LOOP: + case SETUP_LOOP: + case SETUP_EXCEPT: + case SETUP_FINALLY: + case SETUP_WITH: + tgt = GETJUMPTGT(codestr, i); + /* Replace JUMP_* to a RETURN into just a RETURN */ + if (UNCONDITIONAL_JUMP(opcode) && + codestr[tgt] == RETURN_VALUE) { + codestr[i] = RETURN_VALUE; + memset(codestr+i+1, NOP, 2); + continue; + } + if (!UNCONDITIONAL_JUMP(codestr[tgt])) + continue; + tgttgt = GETJUMPTGT(codestr, tgt); + if (opcode == JUMP_FORWARD) /* JMP_ABS can go backwards */ + opcode = JUMP_ABSOLUTE; + if (!ABSOLUTE_JUMP(opcode)) + tgttgt -= i + 3; /* Calc relative jump addr */ + if (tgttgt < 0) /* No backward relative jumps */ + continue; + codestr[i] = opcode; + SETARG(codestr, i, tgttgt); + break; + + case EXTENDED_ARG: + if (codestr[i+3] != MAKE_FUNCTION) + goto exitUnchanged; + /* don't visit MAKE_FUNCTION as GETARG will be wrong */ + i += 3; + break; + + /* Replace RETURN LOAD_CONST None RETURN with just RETURN */ + /* Remove unreachable JUMPs after RETURN */ + case RETURN_VALUE: + if (i+4 >= codelen) + continue; + if (codestr[i+4] == RETURN_VALUE && + ISBASICBLOCK(blocks,i,5)) + memset(codestr+i+1, NOP, 4); + else if (UNCONDITIONAL_JUMP(codestr[i+1]) && + ISBASICBLOCK(blocks,i,4)) + memset(codestr+i+1, NOP, 3); + break; + } + } + + /* Fixup linenotab */ + for (i=0, nops=0 ; iab_size = size; - b->ab_mem = (void *)(b + 1); - b->ab_next = NULL; - b->ab_offset = ROUNDUP((Py_uintptr_t)(b->ab_mem)) - - (Py_uintptr_t)(b->ab_mem); - return b; + /* Allocate header and block as one unit. + ab_mem points just past header. */ + block *b = (block *)malloc(sizeof(block) + size); + if (!b) + return NULL; + b->ab_size = size; + b->ab_mem = (void *)(b + 1); + b->ab_next = NULL; + b->ab_offset = ROUNDUP((Py_uintptr_t)(b->ab_mem)) - + (Py_uintptr_t)(b->ab_mem); + return b; } static void block_free(block *b) { - while (b) { - block *next = b->ab_next; - free(b); - b = next; - } + while (b) { + block *next = b->ab_next; + free(b); + b = next; + } } static void * block_alloc(block *b, size_t size) { - void *p; - assert(b); - size = ROUNDUP(size); - if (b->ab_offset + size > b->ab_size) { - /* If we need to allocate more memory than will fit in - the default block, allocate a one-off block that is - exactly the right size. */ - /* TODO(jhylton): Think about space waste at end of block */ - block *newbl = block_new( - size < DEFAULT_BLOCK_SIZE ? - DEFAULT_BLOCK_SIZE : size); - if (!newbl) - return NULL; - assert(!b->ab_next); - b->ab_next = newbl; - b = newbl; - } - - assert(b->ab_offset + size <= b->ab_size); - p = (void *)(((char *)b->ab_mem) + b->ab_offset); - b->ab_offset += size; - return p; + 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(); - } + 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; + arena->total_allocs = 0; + arena->total_size = 0; + arena->total_blocks = 1; + arena->total_block_size = DEFAULT_BLOCK_SIZE; + arena->total_big_blocks = 0; #endif - return arena; + return arena; } void PyArena_Free(PyArena *arena) { - int r; - assert(arena); + int r; + assert(arena); #if defined(Py_DEBUG) - /* - fprintf(stderr, - "alloc=%d size=%d blocks=%d block_size=%d big=%d objects=%d\n", - arena->total_allocs, arena->total_size, arena->total_blocks, - arena->total_block_size, arena->total_big_blocks, - PyList_Size(arena->a_objects)); - */ + /* + fprintf(stderr, + "alloc=%d size=%d blocks=%d block_size=%d big=%d objects=%d\n", + arena->total_allocs, arena->total_size, arena->total_blocks, + arena->total_block_size, arena->total_big_blocks, + PyList_Size(arena->a_objects)); + */ #endif - block_free(arena->a_head); - /* This property normally holds, except when the code being compiled - is sys.getobjects(0), in which case there will be two references. - assert(arena->a_objects->ob_refcnt == 1); - */ - - /* 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); + 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(); + void *p = block_alloc(arena->a_cur, size); + if (!p) + return PyErr_NoMemory(); #if defined(Py_DEBUG) - arena->total_allocs++; - arena->total_size += size; + arena->total_allocs++; + arena->total_size += size; #endif - /* Reset cur if we allocated a new block. */ - if (arena->a_cur->ab_next) { - arena->a_cur = arena->a_cur->ab_next; + /* Reset cur if we allocated a new block. */ + if (arena->a_cur->ab_next) { + arena->a_cur = arena->a_cur->ab_next; #if defined(Py_DEBUG) - arena->total_blocks++; - arena->total_block_size += arena->a_cur->ab_size; - if (arena->a_cur->ab_size > DEFAULT_BLOCK_SIZE) - ++arena->total_big_blocks; + arena->total_blocks++; + arena->total_block_size += arena->a_cur->ab_size; + if (arena->a_cur->ab_size > DEFAULT_BLOCK_SIZE) + ++arena->total_big_blocks; #endif - } - return p; + } + return p; } int PyArena_AddPyObject(PyArena *arena, PyObject *obj) { - int r = PyList_Append(arena->a_objects, obj); - if (r >= 0) { - Py_DECREF(obj); - } - return r; + int r = PyList_Append(arena->a_objects, obj); + if (r >= 0) { + Py_DECREF(obj); + } + return r; } diff --git a/Python/pymath.c b/Python/pymath.c index 83105f2668..827a773a6a 100644 --- a/Python/pymath.c +++ b/Python/pymath.c @@ -7,9 +7,9 @@ thus rounding from extended precision to double precision. */ double _Py_force_double(double x) { - volatile double y; - y = x; - return y; + volatile double y; + y = x; + return y; } #endif @@ -34,21 +34,21 @@ void _Py_set_387controlword(unsigned short cw) { #ifndef HAVE_HYPOT double hypot(double x, double y) { - double yx; + double yx; - x = fabs(x); - y = fabs(y); - if (x < y) { - double temp = x; - x = y; - y = temp; - } - if (x == 0.) - return 0.; - else { - yx = y/x; - return x*sqrt(1.+yx*yx); - } + x = fabs(x); + y = fabs(y); + if (x < y) { + double temp = x; + x = y; + y = temp; + } + if (x == 0.) + return 0.; + else { + yx = y/x; + return x*sqrt(1.+yx*yx); + } } #endif /* HAVE_HYPOT */ @@ -56,12 +56,12 @@ double hypot(double x, double y) double copysign(double x, double y) { - /* use atan2 to distinguish -0. from 0. */ - if (y > 0. || (y == 0. && atan2(y, -1.) > 0.)) { - return fabs(x); - } else { - return -fabs(x); - } + /* use atan2 to distinguish -0. from 0. */ + if (y > 0. || (y == 0. && atan2(y, -1.) > 0.)) { + return fabs(x); + } else { + return -fabs(x); + } } #endif /* HAVE_COPYSIGN */ @@ -73,7 +73,7 @@ round(double x) absx = fabs(x); y = floor(absx); if (absx - y >= 0.5) - y += 1.0; + y += 1.0; return copysign(y, x); } #endif /* HAVE_ROUND */ diff --git a/Python/pystate.c b/Python/pystate.c index 7154aeac24..f113839ef0 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -60,95 +60,95 @@ static void _PyGILState_NoteThreadState(PyThreadState* tstate); PyInterpreterState * PyInterpreterState_New(void) { - PyInterpreterState *interp = (PyInterpreterState *) - malloc(sizeof(PyInterpreterState)); + PyInterpreterState *interp = (PyInterpreterState *) + malloc(sizeof(PyInterpreterState)); - if (interp != NULL) { - HEAD_INIT(); + if (interp != NULL) { + HEAD_INIT(); #ifdef WITH_THREAD - if (head_mutex == NULL) - Py_FatalError("Can't initialize threads for interpreter"); + if (head_mutex == NULL) + Py_FatalError("Can't initialize threads for interpreter"); #endif - interp->modules = NULL; - interp->modules_reloading = NULL; - interp->modules_by_index = NULL; - interp->sysdict = NULL; - interp->builtins = NULL; - interp->tstate_head = NULL; - interp->codec_search_path = NULL; - interp->codec_search_cache = NULL; - interp->codec_error_registry = NULL; - interp->codecs_initialized = 0; + interp->modules = NULL; + interp->modules_reloading = NULL; + interp->modules_by_index = NULL; + interp->sysdict = NULL; + interp->builtins = NULL; + interp->tstate_head = NULL; + interp->codec_search_path = NULL; + interp->codec_search_cache = NULL; + interp->codec_error_registry = NULL; + interp->codecs_initialized = 0; #ifdef HAVE_DLOPEN #ifdef RTLD_NOW - interp->dlopenflags = RTLD_NOW; + interp->dlopenflags = RTLD_NOW; #else - interp->dlopenflags = RTLD_LAZY; + interp->dlopenflags = RTLD_LAZY; #endif #endif #ifdef WITH_TSC - interp->tscdump = 0; + interp->tscdump = 0; #endif - HEAD_LOCK(); - interp->next = interp_head; - interp_head = interp; - HEAD_UNLOCK(); - } + HEAD_LOCK(); + interp->next = interp_head; + interp_head = interp; + HEAD_UNLOCK(); + } - return interp; + return interp; } void PyInterpreterState_Clear(PyInterpreterState *interp) { - PyThreadState *p; - HEAD_LOCK(); - for (p = interp->tstate_head; p != NULL; p = p->next) - PyThreadState_Clear(p); - HEAD_UNLOCK(); - Py_CLEAR(interp->codec_search_path); - Py_CLEAR(interp->codec_search_cache); - Py_CLEAR(interp->codec_error_registry); - Py_CLEAR(interp->modules); - Py_CLEAR(interp->modules_by_index); - Py_CLEAR(interp->modules_reloading); - Py_CLEAR(interp->sysdict); - Py_CLEAR(interp->builtins); + PyThreadState *p; + HEAD_LOCK(); + for (p = interp->tstate_head; p != NULL; p = p->next) + PyThreadState_Clear(p); + HEAD_UNLOCK(); + Py_CLEAR(interp->codec_search_path); + Py_CLEAR(interp->codec_search_cache); + Py_CLEAR(interp->codec_error_registry); + Py_CLEAR(interp->modules); + Py_CLEAR(interp->modules_by_index); + Py_CLEAR(interp->modules_reloading); + Py_CLEAR(interp->sysdict); + Py_CLEAR(interp->builtins); } static void zapthreads(PyInterpreterState *interp) { - PyThreadState *p; - /* No need to lock the mutex here because this should only happen - when the threads are all really dead (XXX famous last words). */ - while ((p = interp->tstate_head) != NULL) { - PyThreadState_Delete(p); - } + PyThreadState *p; + /* No need to lock the mutex here because this should only happen + when the threads are all really dead (XXX famous last words). */ + while ((p = interp->tstate_head) != NULL) { + PyThreadState_Delete(p); + } } void PyInterpreterState_Delete(PyInterpreterState *interp) { - PyInterpreterState **p; - zapthreads(interp); - HEAD_LOCK(); - for (p = &interp_head; ; p = &(*p)->next) { - if (*p == NULL) - Py_FatalError( - "PyInterpreterState_Delete: invalid interp"); - if (*p == interp) - break; - } - if (interp->tstate_head != NULL) - Py_FatalError("PyInterpreterState_Delete: remaining threads"); - *p = interp->next; - HEAD_UNLOCK(); - free(interp); + PyInterpreterState **p; + zapthreads(interp); + HEAD_LOCK(); + for (p = &interp_head; ; p = &(*p)->next) { + if (*p == NULL) + Py_FatalError( + "PyInterpreterState_Delete: invalid interp"); + if (*p == interp) + break; + } + if (interp->tstate_head != NULL) + Py_FatalError("PyInterpreterState_Delete: remaining threads"); + *p = interp->next; + HEAD_UNLOCK(); + free(interp); } @@ -156,141 +156,141 @@ PyInterpreterState_Delete(PyInterpreterState *interp) static struct _frame * threadstate_getframe(PyThreadState *self) { - return self->frame; + return self->frame; } static PyThreadState * new_threadstate(PyInterpreterState *interp, int init) { - PyThreadState *tstate = (PyThreadState *)malloc(sizeof(PyThreadState)); - - if (_PyThreadState_GetFrame == NULL) - _PyThreadState_GetFrame = threadstate_getframe; - - if (tstate != NULL) { - tstate->interp = interp; - - tstate->frame = NULL; - tstate->recursion_depth = 0; - tstate->overflowed = 0; - tstate->recursion_critical = 0; - tstate->tracing = 0; - tstate->use_tracing = 0; - tstate->tick_counter = 0; - tstate->gilstate_counter = 0; - tstate->async_exc = NULL; + 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->overflowed = 0; + tstate->recursion_critical = 0; + tstate->tracing = 0; + tstate->use_tracing = 0; + tstate->tick_counter = 0; + tstate->gilstate_counter = 0; + tstate->async_exc = NULL; #ifdef WITH_THREAD - tstate->thread_id = PyThread_get_thread_ident(); + tstate->thread_id = PyThread_get_thread_ident(); #else - tstate->thread_id = 0; + tstate->thread_id = 0; #endif - tstate->dict = NULL; + tstate->dict = NULL; - tstate->curexc_type = NULL; - tstate->curexc_value = NULL; - tstate->curexc_traceback = NULL; + tstate->curexc_type = NULL; + tstate->curexc_value = NULL; + tstate->curexc_traceback = NULL; - tstate->exc_type = NULL; - tstate->exc_value = NULL; - tstate->exc_traceback = NULL; + tstate->exc_type = NULL; + tstate->exc_value = NULL; + tstate->exc_traceback = NULL; - tstate->c_profilefunc = NULL; - tstate->c_tracefunc = NULL; - tstate->c_profileobj = NULL; - tstate->c_traceobj = NULL; + tstate->c_profilefunc = NULL; + tstate->c_tracefunc = NULL; + tstate->c_profileobj = NULL; + tstate->c_traceobj = NULL; - if (init) - _PyThreadState_Init(tstate); + if (init) + _PyThreadState_Init(tstate); - HEAD_LOCK(); - tstate->next = interp->tstate_head; - interp->tstate_head = tstate; - HEAD_UNLOCK(); - } + HEAD_LOCK(); + tstate->next = interp->tstate_head; + interp->tstate_head = tstate; + HEAD_UNLOCK(); + } - return tstate; + return tstate; } PyThreadState * PyThreadState_New(PyInterpreterState *interp) { - return new_threadstate(interp, 1); + return new_threadstate(interp, 1); } PyThreadState * _PyThreadState_Prealloc(PyInterpreterState *interp) { - return new_threadstate(interp, 0); + return new_threadstate(interp, 0); } void _PyThreadState_Init(PyThreadState *tstate) { #ifdef WITH_THREAD - _PyGILState_NoteThreadState(tstate); + _PyGILState_NoteThreadState(tstate); #endif } PyObject* PyState_FindModule(struct PyModuleDef* m) { - Py_ssize_t index = m->m_base.m_index; - PyInterpreterState *state = PyThreadState_GET()->interp; - PyObject *res; - if (index == 0) - return NULL; - if (state->modules_by_index == NULL) - return NULL; - if (index > PyList_GET_SIZE(state->modules_by_index)) - return NULL; - res = PyList_GET_ITEM(state->modules_by_index, index); - return res==Py_None ? NULL : res; + Py_ssize_t index = m->m_base.m_index; + PyInterpreterState *state = PyThreadState_GET()->interp; + PyObject *res; + if (index == 0) + return NULL; + if (state->modules_by_index == NULL) + return NULL; + if (index > PyList_GET_SIZE(state->modules_by_index)) + return NULL; + res = PyList_GET_ITEM(state->modules_by_index, index); + return res==Py_None ? NULL : res; } int _PyState_AddModule(PyObject* module, struct PyModuleDef* def) { - PyInterpreterState *state = PyThreadState_GET()->interp; - if (!def) - return -1; - if (!state->modules_by_index) { - state->modules_by_index = PyList_New(0); - if (!state->modules_by_index) - return -1; - } - while(PyList_GET_SIZE(state->modules_by_index) <= def->m_base.m_index) - if (PyList_Append(state->modules_by_index, Py_None) < 0) - return -1; - Py_INCREF(module); - return PyList_SetItem(state->modules_by_index, - def->m_base.m_index, module); + PyInterpreterState *state = PyThreadState_GET()->interp; + if (!def) + return -1; + if (!state->modules_by_index) { + state->modules_by_index = PyList_New(0); + if (!state->modules_by_index) + return -1; + } + while(PyList_GET_SIZE(state->modules_by_index) <= def->m_base.m_index) + if (PyList_Append(state->modules_by_index, Py_None) < 0) + return -1; + Py_INCREF(module); + return PyList_SetItem(state->modules_by_index, + def->m_base.m_index, module); } void PyThreadState_Clear(PyThreadState *tstate) { - if (Py_VerboseFlag && tstate->frame != NULL) - fprintf(stderr, - "PyThreadState_Clear: warning: thread still has a frame\n"); + if (Py_VerboseFlag && tstate->frame != NULL) + fprintf(stderr, + "PyThreadState_Clear: warning: thread still has a frame\n"); - Py_CLEAR(tstate->frame); + Py_CLEAR(tstate->frame); - Py_CLEAR(tstate->dict); - Py_CLEAR(tstate->async_exc); + Py_CLEAR(tstate->dict); + Py_CLEAR(tstate->async_exc); - Py_CLEAR(tstate->curexc_type); - Py_CLEAR(tstate->curexc_value); - Py_CLEAR(tstate->curexc_traceback); + Py_CLEAR(tstate->curexc_type); + Py_CLEAR(tstate->curexc_value); + Py_CLEAR(tstate->curexc_traceback); - Py_CLEAR(tstate->exc_type); - Py_CLEAR(tstate->exc_value); - Py_CLEAR(tstate->exc_traceback); + Py_CLEAR(tstate->exc_type); + Py_CLEAR(tstate->exc_value); + Py_CLEAR(tstate->exc_traceback); - tstate->c_profilefunc = NULL; - tstate->c_tracefunc = NULL; - Py_CLEAR(tstate->c_profileobj); - Py_CLEAR(tstate->c_traceobj); + tstate->c_profilefunc = NULL; + tstate->c_tracefunc = NULL; + Py_CLEAR(tstate->c_profileobj); + Py_CLEAR(tstate->c_traceobj); } @@ -298,50 +298,50 @@ PyThreadState_Clear(PyThreadState *tstate) static void tstate_delete_common(PyThreadState *tstate) { - PyInterpreterState *interp; - PyThreadState **p; - PyThreadState *prev_p = NULL; - if (tstate == NULL) - Py_FatalError("PyThreadState_Delete: NULL tstate"); - interp = tstate->interp; - if (interp == NULL) - Py_FatalError("PyThreadState_Delete: NULL interp"); - HEAD_LOCK(); - for (p = &interp->tstate_head; ; p = &(*p)->next) { - if (*p == NULL) - Py_FatalError( - "PyThreadState_Delete: invalid tstate"); - if (*p == tstate) - break; - /* Sanity check. These states should never happen but if - * they do we must abort. Otherwise we'll end up spinning in - * in a tight loop with the lock held. A similar check is done - * in thread.c find_key(). */ - if (*p == prev_p) - Py_FatalError( - "PyThreadState_Delete: small circular list(!)" - " and tstate not found."); - prev_p = *p; - if ((*p)->next == interp->tstate_head) - Py_FatalError( - "PyThreadState_Delete: circular list(!) and" - " tstate not found."); - } - *p = tstate->next; - HEAD_UNLOCK(); - free(tstate); + PyInterpreterState *interp; + PyThreadState **p; + PyThreadState *prev_p = NULL; + if (tstate == NULL) + Py_FatalError("PyThreadState_Delete: NULL tstate"); + interp = tstate->interp; + if (interp == NULL) + Py_FatalError("PyThreadState_Delete: NULL interp"); + HEAD_LOCK(); + for (p = &interp->tstate_head; ; p = &(*p)->next) { + if (*p == NULL) + Py_FatalError( + "PyThreadState_Delete: invalid tstate"); + if (*p == tstate) + break; + /* Sanity check. These states should never happen but if + * they do we must abort. Otherwise we'll end up spinning in + * in a tight loop with the lock held. A similar check is done + * in thread.c find_key(). */ + if (*p == prev_p) + Py_FatalError( + "PyThreadState_Delete: small circular list(!)" + " and tstate not found."); + prev_p = *p; + if ((*p)->next == interp->tstate_head) + Py_FatalError( + "PyThreadState_Delete: circular list(!) and" + " tstate not found."); + } + *p = tstate->next; + HEAD_UNLOCK(); + free(tstate); } void PyThreadState_Delete(PyThreadState *tstate) { - if (tstate == _Py_atomic_load_relaxed(&_PyThreadState_Current)) - Py_FatalError("PyThreadState_Delete: tstate is still current"); - tstate_delete_common(tstate); + if (tstate == _Py_atomic_load_relaxed(&_PyThreadState_Current)) + Py_FatalError("PyThreadState_Delete: tstate is still current"); + tstate_delete_common(tstate); #ifdef WITH_THREAD - if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate) - PyThread_delete_key_value(autoTLSkey); + if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate) + PyThread_delete_key_value(autoTLSkey); #endif /* WITH_THREAD */ } @@ -350,16 +350,16 @@ PyThreadState_Delete(PyThreadState *tstate) void PyThreadState_DeleteCurrent() { - PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed( - &_PyThreadState_Current); - if (tstate == NULL) - Py_FatalError( - "PyThreadState_DeleteCurrent: no current tstate"); - _Py_atomic_store_relaxed(&_PyThreadState_Current, NULL); - tstate_delete_common(tstate); - if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate) - PyThread_delete_key_value(autoTLSkey); - PyEval_ReleaseLock(); + PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed( + &_PyThreadState_Current); + if (tstate == NULL) + Py_FatalError( + "PyThreadState_DeleteCurrent: no current tstate"); + _Py_atomic_store_relaxed(&_PyThreadState_Current, NULL); + tstate_delete_common(tstate); + if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate) + PyThread_delete_key_value(autoTLSkey); + PyEval_ReleaseLock(); } #endif /* WITH_THREAD */ @@ -367,39 +367,39 @@ PyThreadState_DeleteCurrent() PyThreadState * PyThreadState_Get(void) { - PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed( - &_PyThreadState_Current); - if (tstate == NULL) - Py_FatalError("PyThreadState_Get: no current thread"); + PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed( + &_PyThreadState_Current); + if (tstate == NULL) + Py_FatalError("PyThreadState_Get: no current thread"); - return tstate; + return tstate; } PyThreadState * PyThreadState_Swap(PyThreadState *newts) { - PyThreadState *oldts = (PyThreadState*)_Py_atomic_load_relaxed( - &_PyThreadState_Current); - - _Py_atomic_store_relaxed(&_PyThreadState_Current, newts); - /* It should not be possible for more than one thread state - to be used for a thread. Check this the best we can in debug - builds. - */ + PyThreadState *oldts = (PyThreadState*)_Py_atomic_load_relaxed( + &_PyThreadState_Current); + + _Py_atomic_store_relaxed(&_PyThreadState_Current, newts); + /* It should not be possible for more than one thread state + to be used for a thread. Check this the best we can in debug + builds. + */ #if defined(Py_DEBUG) && defined(WITH_THREAD) - if (newts) { - /* This can be called from PyEval_RestoreThread(). Similar - to it, we need to ensure errno doesn't change. - */ - int err = errno; - PyThreadState *check = PyGILState_GetThisThreadState(); - if (check && check->interp == newts->interp && check != newts) - Py_FatalError("Invalid thread state for this thread"); - errno = err; - } + if (newts) { + /* This can be called from PyEval_RestoreThread(). Similar + to it, we need to ensure errno doesn't change. + */ + int err = errno; + PyThreadState *check = PyGILState_GetThisThreadState(); + if (check && check->interp == newts->interp && check != newts) + Py_FatalError("Invalid thread state for this thread"); + errno = err; + } #endif - return oldts; + return oldts; } /* An extension mechanism to store arbitrary additional per-thread state. @@ -411,18 +411,18 @@ PyThreadState_Swap(PyThreadState *newts) PyObject * PyThreadState_GetDict(void) { - PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed( - &_PyThreadState_Current); - if (tstate == NULL) - return NULL; + PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed( + &_PyThreadState_Current); + if (tstate == NULL) + return NULL; - if (tstate->dict == NULL) { - PyObject *d; - tstate->dict = d = PyDict_New(); - if (d == NULL) - PyErr_Clear(); - } - return tstate->dict; + if (tstate->dict == NULL) { + PyObject *d; + tstate->dict = d = PyDict_New(); + if (d == NULL) + PyErr_Clear(); + } + return tstate->dict; } @@ -436,37 +436,37 @@ PyThreadState_GetDict(void) int PyThreadState_SetAsyncExc(long id, PyObject *exc) { - PyThreadState *tstate = PyThreadState_GET(); - PyInterpreterState *interp = tstate->interp; - PyThreadState *p; - - /* Although the GIL is held, a few C API functions can be called - * without the GIL held, and in particular some that create and - * destroy thread and interpreter states. Those can mutate the - * list of thread states we're traversing, so to prevent that we lock - * head_mutex for the duration. - */ - HEAD_LOCK(); - for (p = interp->tstate_head; p != NULL; p = p->next) { - if (p->thread_id == id) { - /* Tricky: we need to decref the current value - * (if any) in p->async_exc, but that can in turn - * allow arbitrary Python code to run, including - * perhaps calls to this function. To prevent - * deadlock, we need to release head_mutex before - * the decref. - */ - PyObject *old_exc = p->async_exc; - Py_XINCREF(exc); - p->async_exc = exc; - HEAD_UNLOCK(); - Py_XDECREF(old_exc); - _PyEval_SignalAsyncExc(); - return 1; - } - } - HEAD_UNLOCK(); - return 0; + PyThreadState *tstate = PyThreadState_GET(); + PyInterpreterState *interp = tstate->interp; + PyThreadState *p; + + /* Although the GIL is held, a few C API functions can be called + * without the GIL held, and in particular some that create and + * destroy thread and interpreter states. Those can mutate the + * list of thread states we're traversing, so to prevent that we lock + * head_mutex for the duration. + */ + HEAD_LOCK(); + for (p = interp->tstate_head; p != NULL; p = p->next) { + if (p->thread_id == id) { + /* Tricky: we need to decref the current value + * (if any) in p->async_exc, but that can in turn + * allow arbitrary Python code to run, including + * perhaps calls to this function. To prevent + * deadlock, we need to release head_mutex before + * the decref. + */ + PyObject *old_exc = p->async_exc; + Py_XINCREF(exc); + p->async_exc = exc; + HEAD_UNLOCK(); + Py_XDECREF(old_exc); + _PyEval_SignalAsyncExc(); + return 1; + } + } + HEAD_UNLOCK(); + return 0; } @@ -476,22 +476,22 @@ PyThreadState_SetAsyncExc(long id, PyObject *exc) { PyInterpreterState * PyInterpreterState_Head(void) { - return interp_head; + return interp_head; } PyInterpreterState * PyInterpreterState_Next(PyInterpreterState *interp) { - return interp->next; + return interp->next; } PyThreadState * PyInterpreterState_ThreadHead(PyInterpreterState *interp) { - return interp->tstate_head; + return interp->tstate_head; } PyThreadState * PyThreadState_Next(PyThreadState *tstate) { - return tstate->next; + return tstate->next; } /* The implementation of sys._current_frames(). This is intended to be @@ -502,44 +502,44 @@ PyThreadState_Next(PyThreadState *tstate) { PyObject * _PyThread_CurrentFrames(void) { - PyObject *result; - PyInterpreterState *i; - - result = PyDict_New(); - if (result == NULL) - return NULL; - - /* for i in all interpreters: - * for t in all of i's thread states: - * if t's frame isn't NULL, map t's id to its frame - * Because these lists can mutute even when the GIL is held, we - * need to grab head_mutex for the duration. - */ - HEAD_LOCK(); - for (i = interp_head; i != NULL; i = i->next) { - PyThreadState *t; - for (t = i->tstate_head; t != NULL; t = t->next) { - PyObject *id; - int stat; - struct _frame *frame = t->frame; - if (frame == NULL) - continue; - id = PyLong_FromLong(t->thread_id); - if (id == NULL) - goto Fail; - stat = PyDict_SetItem(result, id, (PyObject *)frame); - Py_DECREF(id); - if (stat < 0) - goto Fail; - } - } - HEAD_UNLOCK(); - return result; + 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 = PyLong_FromLong(t->thread_id); + if (id == NULL) + goto Fail; + stat = PyDict_SetItem(result, id, (PyObject *)frame); + Py_DECREF(id); + if (stat < 0) + goto Fail; + } + } + HEAD_UNLOCK(); + return result; Fail: - HEAD_UNLOCK(); - Py_DECREF(result); - return NULL; + HEAD_UNLOCK(); + Py_DECREF(result); + return NULL; } /* Python "auto thread state" API. */ @@ -556,9 +556,9 @@ _PyThread_CurrentFrames(void) static int PyThreadState_IsCurrent(PyThreadState *tstate) { - /* Must be the tstate for this thread */ - assert(PyGILState_GetThisThreadState()==tstate); - return tstate == _Py_atomic_load_relaxed(&_PyThreadState_Current); + /* Must be the tstate for this thread */ + assert(PyGILState_GetThisThreadState()==tstate); + return tstate == _Py_atomic_load_relaxed(&_PyThreadState_Current); } /* Internal initialization/finalization functions called by @@ -567,21 +567,21 @@ PyThreadState_IsCurrent(PyThreadState *tstate) void _PyGILState_Init(PyInterpreterState *i, PyThreadState *t) { - assert(i && t); /* must init with valid states */ - autoTLSkey = PyThread_create_key(); - autoInterpreterState = i; - assert(PyThread_get_key_value(autoTLSkey) == NULL); - assert(t->gilstate_counter == 0); + assert(i && t); /* must init with valid states */ + autoTLSkey = PyThread_create_key(); + autoInterpreterState = i; + assert(PyThread_get_key_value(autoTLSkey) == NULL); + assert(t->gilstate_counter == 0); - _PyGILState_NoteThreadState(t); + _PyGILState_NoteThreadState(t); } void _PyGILState_Fini(void) { - PyThread_delete_key(autoTLSkey); - autoTLSkey = 0; - autoInterpreterState = NULL; + PyThread_delete_key(autoTLSkey); + autoTLSkey = 0; + autoInterpreterState = NULL; } /* When a thread state is created for a thread by some mechanism other than @@ -592,113 +592,113 @@ _PyGILState_Fini(void) static void _PyGILState_NoteThreadState(PyThreadState* tstate) { - /* If autoTLSkey is 0, this must be the very first threadstate created - in Py_Initialize(). Don't do anything for now (we'll be back here - when _PyGILState_Init is called). */ - if (!autoTLSkey) - return; + /* If autoTLSkey is 0, this must be the very first threadstate created + in Py_Initialize(). Don't do anything for now (we'll be back here + when _PyGILState_Init is called). */ + if (!autoTLSkey) + return; - /* Stick the thread state for this thread in thread local storage. + /* Stick the thread state for this thread in thread local storage. - The only situation where you can legitimately have more than one - thread state for an OS level thread is when there are multiple - interpreters, when: + The only situation where you can legitimately have more than one + thread state for an OS level thread is when there are multiple + interpreters, when: - a) You shouldn't really be using the PyGILState_ APIs anyway, - and: + a) You shouldn't really be using the PyGILState_ APIs anyway, + and: - b) The slightly odd way PyThread_set_key_value works (see - comments by its implementation) means that the first thread - state created for that given OS level thread will "win", - which seems reasonable behaviour. - */ - if (PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0) - Py_FatalError("Couldn't create autoTLSkey mapping"); + b) The slightly odd way PyThread_set_key_value works (see + comments by its implementation) means that the first thread + state created for that given OS level thread will "win", + which seems reasonable behaviour. + */ + if (PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0) + Py_FatalError("Couldn't create autoTLSkey mapping"); - /* PyGILState_Release must not try to delete this thread state. */ - tstate->gilstate_counter = 1; + /* PyGILState_Release must not try to delete this thread state. */ + tstate->gilstate_counter = 1; } /* The public functions */ PyThreadState * PyGILState_GetThisThreadState(void) { - if (autoInterpreterState == NULL || autoTLSkey == 0) - return NULL; - return (PyThreadState *)PyThread_get_key_value(autoTLSkey); + if (autoInterpreterState == NULL || autoTLSkey == 0) + return NULL; + return (PyThreadState *)PyThread_get_key_value(autoTLSkey); } PyGILState_STATE PyGILState_Ensure(void) { - int current; - PyThreadState *tcur; - /* Note that we do not auto-init Python here - apart from - potential races with 2 threads auto-initializing, pep-311 - spells out other issues. Embedders are expected to have - called Py_Initialize() and usually PyEval_InitThreads(). - */ - assert(autoInterpreterState); /* Py_Initialize() hasn't been called! */ - tcur = (PyThreadState *)PyThread_get_key_value(autoTLSkey); - if (tcur == NULL) { - /* Create a new thread state for this thread */ - tcur = PyThreadState_New(autoInterpreterState); - if (tcur == NULL) - Py_FatalError("Couldn't create thread-state for new thread"); - /* This is our thread state! We'll need to delete it in the - matching call to PyGILState_Release(). */ - tcur->gilstate_counter = 0; - current = 0; /* new thread state is never current */ - } - else - current = PyThreadState_IsCurrent(tcur); - if (current == 0) - PyEval_RestoreThread(tcur); - /* Update our counter in the thread-state - no need for locks: - - tcur will remain valid as we hold the GIL. - - the counter is safe as we are the only thread "allowed" - to modify this value - */ - ++tcur->gilstate_counter; - return current ? PyGILState_LOCKED : PyGILState_UNLOCKED; + int current; + PyThreadState *tcur; + /* Note that we do not auto-init Python here - apart from + potential races with 2 threads auto-initializing, pep-311 + spells out other issues. Embedders are expected to have + called Py_Initialize() and usually PyEval_InitThreads(). + */ + assert(autoInterpreterState); /* Py_Initialize() hasn't been called! */ + tcur = (PyThreadState *)PyThread_get_key_value(autoTLSkey); + if (tcur == NULL) { + /* Create a new thread state for this thread */ + tcur = PyThreadState_New(autoInterpreterState); + if (tcur == NULL) + Py_FatalError("Couldn't create thread-state for new thread"); + /* This is our thread state! We'll need to delete it in the + matching call to PyGILState_Release(). */ + tcur->gilstate_counter = 0; + current = 0; /* new thread state is never current */ + } + else + current = PyThreadState_IsCurrent(tcur); + if (current == 0) + PyEval_RestoreThread(tcur); + /* Update our counter in the thread-state - no need for locks: + - tcur will remain valid as we hold the GIL. + - the counter is safe as we are the only thread "allowed" + to modify this value + */ + ++tcur->gilstate_counter; + return current ? PyGILState_LOCKED : PyGILState_UNLOCKED; } void PyGILState_Release(PyGILState_STATE oldstate) { - PyThreadState *tcur = (PyThreadState *)PyThread_get_key_value( - autoTLSkey); - if (tcur == NULL) - Py_FatalError("auto-releasing thread-state, " - "but no thread-state for this thread"); - /* We must hold the GIL and have our thread state current */ - /* XXX - remove the check - the assert should be fine, - but while this is very new (April 2003), the extra check - by release-only users can't hurt. - */ - if (! PyThreadState_IsCurrent(tcur)) - Py_FatalError("This thread state must be current when releasing"); - assert(PyThreadState_IsCurrent(tcur)); - --tcur->gilstate_counter; - assert(tcur->gilstate_counter >= 0); /* illegal counter value */ - - /* 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(); + 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 diff --git a/Python/pystrcmp.c b/Python/pystrcmp.c index 84295e7d21..f9c2277cb5 100644 --- a/Python/pystrcmp.c +++ b/Python/pystrcmp.c @@ -6,21 +6,21 @@ int PyOS_mystrnicmp(const char *s1, const char *s2, Py_ssize_t size) { - if (size == 0) - return 0; - while ((--size > 0) && - (tolower((unsigned)*s1) == tolower((unsigned)*s2))) { - if (!*s1++ || !*s2++) - break; - } - return tolower((unsigned)*s1) - tolower((unsigned)*s2); + if (size == 0) + return 0; + while ((--size > 0) && + (tolower((unsigned)*s1) == tolower((unsigned)*s2))) { + if (!*s1++ || !*s2++) + break; + } + return tolower((unsigned)*s1) - tolower((unsigned)*s2); } int PyOS_mystricmp(const char *s1, const char *s2) { - while (*s1 && (tolower((unsigned)*s1++) == tolower((unsigned)*s2++))) { - ; - } - return (tolower((unsigned)*s1) - tolower((unsigned)*s2)); + while (*s1 && (tolower((unsigned)*s1++) == tolower((unsigned)*s2++))) { + ; + } + return (tolower((unsigned)*s1) - tolower((unsigned)*s2)); } diff --git a/Python/pystrtod.c b/Python/pystrtod.c index a1d7ff09fc..75e3032fb7 100644 --- a/Python/pystrtod.c +++ b/Python/pystrtod.c @@ -9,11 +9,11 @@ static int case_insensitive_match(const char *s, const char *t) { - while(*t && Py_TOLOWER(*s) == *t) { - s++; - t++; - } - return *t ? 0 : 1; + while(*t && Py_TOLOWER(*s) == *t) { + s++; + t++; + } + return *t ? 0 : 1; } /* _Py_parse_inf_or_nan: Attempt to parse a string of the form "nan", "inf" or @@ -25,36 +25,36 @@ case_insensitive_match(const char *s, const char *t) double _Py_parse_inf_or_nan(const char *p, char **endptr) { - double retval; - const char *s; - int negate = 0; - - s = p; - if (*s == '-') { - negate = 1; - s++; - } - else if (*s == '+') { - s++; - } - if (case_insensitive_match(s, "inf")) { - s += 3; - if (case_insensitive_match(s, "inity")) - s += 5; - retval = negate ? -Py_HUGE_VAL : Py_HUGE_VAL; - } + double retval; + const char *s; + int negate = 0; + + s = p; + if (*s == '-') { + negate = 1; + s++; + } + else if (*s == '+') { + s++; + } + if (case_insensitive_match(s, "inf")) { + s += 3; + if (case_insensitive_match(s, "inity")) + s += 5; + retval = negate ? -Py_HUGE_VAL : Py_HUGE_VAL; + } #ifdef Py_NAN - else if (case_insensitive_match(s, "nan")) { - s += 3; - retval = negate ? -Py_NAN : Py_NAN; - } + else if (case_insensitive_match(s, "nan")) { + s += 3; + retval = negate ? -Py_NAN : Py_NAN; + } #endif - else { - s = p; - retval = -1.0; - } - *endptr = (char *)s; - return retval; + else { + s = p; + retval = -1.0; + } + *endptr = (char *)s; + return retval; } /** @@ -62,7 +62,7 @@ _Py_parse_inf_or_nan(const char *p, char **endptr) * @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 @@ -79,7 +79,7 @@ _Py_parse_inf_or_nan(const char *p, char **endptr) * 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. * @@ -91,23 +91,23 @@ _Py_parse_inf_or_nan(const char *p, char **endptr) static double _PyOS_ascii_strtod(const char *nptr, char **endptr) { - double result; - _Py_SET_53BIT_PRECISION_HEADER; + double result; + _Py_SET_53BIT_PRECISION_HEADER; - assert(nptr != NULL); - /* Set errno to zero, so that we can distinguish zero results - and underflows */ - errno = 0; + assert(nptr != NULL); + /* Set errno to zero, so that we can distinguish zero results + and underflows */ + errno = 0; - _Py_SET_53BIT_PRECISION_START; - result = _Py_dg_strtod(nptr, endptr); - _Py_SET_53BIT_PRECISION_END; + _Py_SET_53BIT_PRECISION_START; + result = _Py_dg_strtod(nptr, endptr); + _Py_SET_53BIT_PRECISION_END; - if (*endptr == nptr) - /* string might represent an inf or nan */ - result = _Py_parse_inf_or_nan(nptr, endptr); + if (*endptr == nptr) + /* string might represent an inf or nan */ + result = _Py_parse_inf_or_nan(nptr, endptr); - return result; + return result; } @@ -124,148 +124,148 @@ _PyOS_ascii_strtod(const char *nptr, char **endptr) static 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 */ - const char *digits_pos = NULL; - int negate = 0; - - 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; - - /* Parse infinities and nans */ - val = _Py_parse_inf_or_nan(nptr, endptr); - if (*endptr != nptr) - return val; - - /* Set errno to zero, so that we can distinguish zero results - and underflows */ - errno = 0; - - /* We process the optional sign manually, then pass the remainder to - the system strtod. This ensures that the result of an underflow - has the correct sign. (bug #1725) */ - p = nptr; - /* Process leading sign, if present */ - if (*p == '-') { - negate = 1; - p++; - } - else if (*p == '+') { - p++; - } - - /* Some platform strtods accept hex floats; Python shouldn't (at the - moment), so we check explicitly for strings starting with '0x'. */ - if (*p == '0' && (*(p+1) == 'x' || *(p+1) == 'X')) - goto invalid_string; - - /* Check that what's left begins with a digit or decimal point */ - if (!Py_ISDIGIT(*p) && *p != '.') - goto invalid_string; - - digits_pos = p; - if (decimal_point[0] != '.' || - decimal_point[1] != 0) - { - /* Look for a '.' in the input; if present, it'll need to be - swapped for the current locale's decimal point before we - call strtod. On the other hand, if we find the current - locale's decimal point then the input is invalid. */ - while (Py_ISDIGIT(*p)) - p++; - - if (*p == '.') - { - decimal_point_pos = p++; - - /* locate end of number */ - while (Py_ISDIGIT(*p)) - p++; - - if (*p == 'e' || *p == 'E') - p++; - if (*p == '+' || *p == '-') - p++; - while (Py_ISDIGIT(*p)) - p++; - end = p; - } - else if (strncmp(p, decimal_point, decimal_point_len) == 0) - /* Python bug #1417699 */ - goto invalid_string; - /* For the other cases, we need not convert the decimal - point */ - } - - if (decimal_point_pos) { - char *copy, *c; - /* Create a copy of the input, with the '.' converted to the - locale-specific decimal point */ - copy = (char *)PyMem_MALLOC(end - digits_pos + - 1 + decimal_point_len); - if (copy == NULL) { - *endptr = (char *)nptr; - errno = ENOMEM; - return val; - } - - c = copy; - memcpy(c, digits_pos, decimal_point_pos - digits_pos); - c += decimal_point_pos - digits_pos; - 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 *)digits_pos + - (fail_pos - copy) - - (decimal_point_len - 1); - else - fail_pos = (char *)digits_pos + - (fail_pos - copy); - } - - PyMem_FREE(copy); - - } - else { - val = strtod(digits_pos, &fail_pos); - } - - if (fail_pos == digits_pos) - goto invalid_string; - - if (negate && fail_pos != nptr) - val = -val; - *endptr = fail_pos; - - return val; + 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 */ + const char *digits_pos = NULL; + int negate = 0; + + 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; + + /* Parse infinities and nans */ + val = _Py_parse_inf_or_nan(nptr, endptr); + if (*endptr != nptr) + return val; + + /* Set errno to zero, so that we can distinguish zero results + and underflows */ + errno = 0; + + /* We process the optional sign manually, then pass the remainder to + the system strtod. This ensures that the result of an underflow + has the correct sign. (bug #1725) */ + p = nptr; + /* Process leading sign, if present */ + if (*p == '-') { + negate = 1; + p++; + } + else if (*p == '+') { + p++; + } + + /* Some platform strtods accept hex floats; Python shouldn't (at the + moment), so we check explicitly for strings starting with '0x'. */ + if (*p == '0' && (*(p+1) == 'x' || *(p+1) == 'X')) + goto invalid_string; + + /* Check that what's left begins with a digit or decimal point */ + if (!Py_ISDIGIT(*p) && *p != '.') + goto invalid_string; + + digits_pos = p; + if (decimal_point[0] != '.' || + decimal_point[1] != 0) + { + /* Look for a '.' in the input; if present, it'll need to be + swapped for the current locale's decimal point before we + call strtod. On the other hand, if we find the current + locale's decimal point then the input is invalid. */ + while (Py_ISDIGIT(*p)) + p++; + + if (*p == '.') + { + decimal_point_pos = p++; + + /* locate end of number */ + while (Py_ISDIGIT(*p)) + p++; + + if (*p == 'e' || *p == 'E') + p++; + if (*p == '+' || *p == '-') + p++; + while (Py_ISDIGIT(*p)) + p++; + end = p; + } + else if (strncmp(p, decimal_point, decimal_point_len) == 0) + /* Python bug #1417699 */ + goto invalid_string; + /* For the other cases, we need not convert the decimal + point */ + } + + if (decimal_point_pos) { + char *copy, *c; + /* Create a copy of the input, with the '.' converted to the + locale-specific decimal point */ + copy = (char *)PyMem_MALLOC(end - digits_pos + + 1 + decimal_point_len); + if (copy == NULL) { + *endptr = (char *)nptr; + errno = ENOMEM; + return val; + } + + c = copy; + memcpy(c, digits_pos, decimal_point_pos - digits_pos); + c += decimal_point_pos - digits_pos; + 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 *)digits_pos + + (fail_pos - copy) - + (decimal_point_len - 1); + else + fail_pos = (char *)digits_pos + + (fail_pos - copy); + } + + PyMem_FREE(copy); + + } + else { + val = strtod(digits_pos, &fail_pos); + } + + if (fail_pos == digits_pos) + goto invalid_string; + + if (negate && fail_pos != nptr) + val = -val; + *endptr = fail_pos; + + return val; invalid_string: - *endptr = (char*)nptr; - errno = EINVAL; - return -1.0; + *endptr = (char*)nptr; + errno = EINVAL; + return -1.0; } #endif @@ -296,39 +296,39 @@ _PyOS_ascii_strtod(const char *nptr, char **endptr) double PyOS_string_to_double(const char *s, - char **endptr, - PyObject *overflow_exception) + char **endptr, + PyObject *overflow_exception) { - double x, result=-1.0; - char *fail_pos; - - errno = 0; - PyFPE_START_PROTECT("PyOS_string_to_double", return -1.0) - x = _PyOS_ascii_strtod(s, &fail_pos); - PyFPE_END_PROTECT(x) - - if (errno == ENOMEM) { - PyErr_NoMemory(); - fail_pos = (char *)s; - } - else if (!endptr && (fail_pos == s || *fail_pos != '\0')) - PyErr_Format(PyExc_ValueError, - "could not convert string to float: " - "%.200s", s); - else if (fail_pos == s) - PyErr_Format(PyExc_ValueError, - "could not convert string to float: " - "%.200s", s); - else if (errno == ERANGE && fabs(x) >= 1.0 && overflow_exception) - PyErr_Format(overflow_exception, - "value too large to convert to float: " - "%.200s", s); - else - result = x; - - if (endptr != NULL) - *endptr = fail_pos; - return result; + double x, result=-1.0; + char *fail_pos; + + errno = 0; + PyFPE_START_PROTECT("PyOS_string_to_double", return -1.0) + x = _PyOS_ascii_strtod(s, &fail_pos); + PyFPE_END_PROTECT(x) + + if (errno == ENOMEM) { + PyErr_NoMemory(); + fail_pos = (char *)s; + } + else if (!endptr && (fail_pos == s || *fail_pos != '\0')) + PyErr_Format(PyExc_ValueError, + "could not convert string to float: " + "%.200s", s); + else if (fail_pos == s) + PyErr_Format(PyExc_ValueError, + "could not convert string to float: " + "%.200s", s); + else if (errno == ERANGE && fabs(x) >= 1.0 && overflow_exception) + PyErr_Format(overflow_exception, + "value too large to convert to float: " + "%.200s", s); + else + result = x; + + if (endptr != NULL) + *endptr = fail_pos; + return result; } #ifdef PY_NO_SHORT_FLOAT_REPR @@ -339,30 +339,30 @@ PyOS_string_to_double(const char *s, Py_LOCAL_INLINE(void) change_decimal_from_locale_to_dot(char* buffer) { - struct lconv *locale_data = localeconv(); - const char *decimal_point = locale_data->decimal_point; - - if (decimal_point[0] != '.' || decimal_point[1] != 0) { - size_t decimal_point_len = strlen(decimal_point); - - if (*buffer == '+' || *buffer == '-') - buffer++; - while (Py_ISDIGIT(*buffer)) - buffer++; - if (strncmp(buffer, decimal_point, decimal_point_len) == 0) { - *buffer = '.'; - buffer++; - if (decimal_point_len > 1) { - /* buffer needs to get smaller */ - size_t rest_len = strlen(buffer + - (decimal_point_len - 1)); - memmove(buffer, - buffer + (decimal_point_len - 1), - rest_len); - buffer[rest_len] = 0; - } - } - } + struct lconv *locale_data = localeconv(); + const char *decimal_point = locale_data->decimal_point; + + if (decimal_point[0] != '.' || decimal_point[1] != 0) { + size_t decimal_point_len = strlen(decimal_point); + + if (*buffer == '+' || *buffer == '-') + buffer++; + while (Py_ISDIGIT(*buffer)) + buffer++; + if (strncmp(buffer, decimal_point, decimal_point_len) == 0) { + *buffer = '.'; + buffer++; + if (decimal_point_len > 1) { + /* buffer needs to get smaller */ + size_t rest_len = strlen(buffer + + (decimal_point_len - 1)); + memmove(buffer, + buffer + (decimal_point_len - 1), + rest_len); + buffer[rest_len] = 0; + } + } + } } @@ -377,65 +377,65 @@ as necessary to represent the exponent. Py_LOCAL_INLINE(void) ensure_minimum_exponent_length(char* buffer, size_t buf_size) { - char *p = strpbrk(buffer, "eE"); - if (p && (*(p + 1) == '-' || *(p + 1) == '+')) { - char *start = p + 2; - int exponent_digit_cnt = 0; - int leading_zero_cnt = 0; - int in_leading_zeros = 1; - int significant_digit_cnt; - - /* Skip over the exponent and the sign. */ - p += 2; - - /* Find the end of the exponent, keeping track of leading - zeros. */ - while (*p && Py_ISDIGIT(*p)) { - if (in_leading_zeros && *p == '0') - ++leading_zero_cnt; - if (*p != '0') - in_leading_zeros = 0; - ++p; - ++exponent_digit_cnt; - } - - significant_digit_cnt = exponent_digit_cnt - leading_zero_cnt; - if (exponent_digit_cnt == MIN_EXPONENT_DIGITS) { - /* If there are 2 exactly digits, we're done, - regardless of what they contain */ - } - else if (exponent_digit_cnt > MIN_EXPONENT_DIGITS) { - int extra_zeros_cnt; - - /* There are more than 2 digits in the exponent. See - if we can delete some of the leading zeros */ - if (significant_digit_cnt < MIN_EXPONENT_DIGITS) - significant_digit_cnt = MIN_EXPONENT_DIGITS; - extra_zeros_cnt = exponent_digit_cnt - - significant_digit_cnt; - - /* Delete extra_zeros_cnt worth of characters from the - front of the exponent */ - assert(extra_zeros_cnt >= 0); - - /* Add one to significant_digit_cnt to copy the - trailing 0 byte, thus setting the length */ - memmove(start, - start + extra_zeros_cnt, - significant_digit_cnt + 1); - } - else { - /* If there are fewer than 2 digits, add zeros - until there are 2, if there's enough room */ - int zeros = MIN_EXPONENT_DIGITS - exponent_digit_cnt; - if (start + zeros + exponent_digit_cnt + 1 - < buffer + buf_size) { - memmove(start + zeros, start, - exponent_digit_cnt + 1); - memset(start, '0', zeros); - } - } - } + char *p = strpbrk(buffer, "eE"); + if (p && (*(p + 1) == '-' || *(p + 1) == '+')) { + char *start = p + 2; + int exponent_digit_cnt = 0; + int leading_zero_cnt = 0; + int in_leading_zeros = 1; + int significant_digit_cnt; + + /* Skip over the exponent and the sign. */ + p += 2; + + /* Find the end of the exponent, keeping track of leading + zeros. */ + while (*p && Py_ISDIGIT(*p)) { + if (in_leading_zeros && *p == '0') + ++leading_zero_cnt; + if (*p != '0') + in_leading_zeros = 0; + ++p; + ++exponent_digit_cnt; + } + + significant_digit_cnt = exponent_digit_cnt - leading_zero_cnt; + if (exponent_digit_cnt == MIN_EXPONENT_DIGITS) { + /* If there are 2 exactly digits, we're done, + regardless of what they contain */ + } + else if (exponent_digit_cnt > MIN_EXPONENT_DIGITS) { + int extra_zeros_cnt; + + /* There are more than 2 digits in the exponent. See + if we can delete some of the leading zeros */ + if (significant_digit_cnt < MIN_EXPONENT_DIGITS) + significant_digit_cnt = MIN_EXPONENT_DIGITS; + extra_zeros_cnt = exponent_digit_cnt - + significant_digit_cnt; + + /* Delete extra_zeros_cnt worth of characters from the + front of the exponent */ + assert(extra_zeros_cnt >= 0); + + /* Add one to significant_digit_cnt to copy the + trailing 0 byte, thus setting the length */ + memmove(start, + start + extra_zeros_cnt, + significant_digit_cnt + 1); + } + else { + /* If there are fewer than 2 digits, add zeros + until there are 2, if there's enough room */ + int zeros = MIN_EXPONENT_DIGITS - exponent_digit_cnt; + if (start + zeros + exponent_digit_cnt + 1 + < buffer + buf_size) { + memmove(start + zeros, start, + exponent_digit_cnt + 1); + memset(start, '0', zeros); + } + } + } } /* Remove trailing zeros after the decimal point from a numeric string; also @@ -445,40 +445,40 @@ ensure_minimum_exponent_length(char* buffer, size_t buf_size) Py_LOCAL_INLINE(void) remove_trailing_zeros(char *buffer) { - char *old_fraction_end, *new_fraction_end, *end, *p; - - p = buffer; - if (*p == '-' || *p == '+') - /* Skip leading sign, if present */ - ++p; - while (Py_ISDIGIT(*p)) - ++p; - - /* if there's no decimal point there's nothing to do */ - if (*p++ != '.') - return; - - /* scan any digits after the point */ - while (Py_ISDIGIT(*p)) - ++p; - old_fraction_end = p; - - /* scan up to ending '\0' */ - while (*p != '\0') - p++; - /* +1 to make sure that we move the null byte as well */ - end = p+1; - - /* scan back from fraction_end, looking for removable zeros */ - p = old_fraction_end; - while (*(p-1) == '0') - --p; - /* and remove point if we've got that far */ - if (*(p-1) == '.') - --p; - new_fraction_end = p; - - memmove(new_fraction_end, old_fraction_end, end-old_fraction_end); + char *old_fraction_end, *new_fraction_end, *end, *p; + + p = buffer; + if (*p == '-' || *p == '+') + /* Skip leading sign, if present */ + ++p; + while (Py_ISDIGIT(*p)) + ++p; + + /* if there's no decimal point there's nothing to do */ + if (*p++ != '.') + return; + + /* scan any digits after the point */ + while (Py_ISDIGIT(*p)) + ++p; + old_fraction_end = p; + + /* scan up to ending '\0' */ + while (*p != '\0') + p++; + /* +1 to make sure that we move the null byte as well */ + end = p+1; + + /* scan back from fraction_end, looking for removable zeros */ + p = old_fraction_end; + while (*(p-1) == '0') + --p; + /* and remove point if we've got that far */ + if (*(p-1) == '.') + --p; + new_fraction_end = p; + + memmove(new_fraction_end, old_fraction_end, end-old_fraction_end); } /* Ensure that buffer has a decimal point in it. The decimal point will not @@ -491,91 +491,91 @@ remove_trailing_zeros(char *buffer) Py_LOCAL_INLINE(char *) ensure_decimal_point(char* buffer, size_t buf_size, int precision) { - int digit_count, insert_count = 0, convert_to_exp = 0; - char *chars_to_insert, *digits_start; - - /* search for the first non-digit character */ - char *p = buffer; - if (*p == '-' || *p == '+') - /* Skip leading sign, if present. I think this could only - ever be '-', but it can't hurt to check for both. */ - ++p; - digits_start = p; - while (*p && Py_ISDIGIT(*p)) - ++p; - digit_count = Py_SAFE_DOWNCAST(p - digits_start, Py_ssize_t, int); - - if (*p == '.') { - if (Py_ISDIGIT(*(p+1))) { - /* Nothing to do, we already have a decimal - point and a digit after it */ - } - else { - /* We have a decimal point, but no following - digit. Insert a zero after the decimal. */ - /* can't ever get here via PyOS_double_to_string */ - assert(precision == -1); - ++p; - chars_to_insert = "0"; - insert_count = 1; - } - } - else if (!(*p == 'e' || *p == 'E')) { - /* Don't add ".0" if we have an exponent. */ - if (digit_count == precision) { - /* issue 5864: don't add a trailing .0 in the case - where the '%g'-formatted result already has as many - significant digits as were requested. Switch to - exponential notation instead. */ - convert_to_exp = 1; - /* no exponent, no point, and we shouldn't land here - for infs and nans, so we must be at the end of the - string. */ - assert(*p == '\0'); - } - else { - assert(precision == -1 || digit_count < precision); - chars_to_insert = ".0"; - insert_count = 2; - } - } - if (insert_count) { - size_t buf_len = strlen(buffer); - if (buf_len + insert_count + 1 >= buf_size) { - /* If there is not enough room in the buffer - for the additional text, just skip it. It's - not worth generating an error over. */ - } - else { - memmove(p + insert_count, p, - buffer + strlen(buffer) - p + 1); - memcpy(p, chars_to_insert, insert_count); - } - } - if (convert_to_exp) { - int written; - size_t buf_avail; - p = digits_start; - /* insert decimal point */ - assert(digit_count >= 1); - memmove(p+2, p+1, digit_count); /* safe, but overwrites nul */ - p[1] = '.'; - p += digit_count+1; - assert(p <= buf_size+buffer); - buf_avail = buf_size+buffer-p; - if (buf_avail == 0) - return NULL; - /* Add exponent. It's okay to use lower case 'e': we only - arrive here as a result of using the empty format code or - repr/str builtins and those never want an upper case 'E' */ - written = PyOS_snprintf(p, buf_avail, "e%+.02d", digit_count-1); - if (!(0 <= written && - written < Py_SAFE_DOWNCAST(buf_avail, size_t, int))) - /* output truncated, or something else bad happened */ - return NULL; - remove_trailing_zeros(buffer); - } - return buffer; + int digit_count, insert_count = 0, convert_to_exp = 0; + char *chars_to_insert, *digits_start; + + /* search for the first non-digit character */ + char *p = buffer; + if (*p == '-' || *p == '+') + /* Skip leading sign, if present. I think this could only + ever be '-', but it can't hurt to check for both. */ + ++p; + digits_start = p; + while (*p && Py_ISDIGIT(*p)) + ++p; + digit_count = Py_SAFE_DOWNCAST(p - digits_start, Py_ssize_t, int); + + if (*p == '.') { + if (Py_ISDIGIT(*(p+1))) { + /* Nothing to do, we already have a decimal + point and a digit after it */ + } + else { + /* We have a decimal point, but no following + digit. Insert a zero after the decimal. */ + /* can't ever get here via PyOS_double_to_string */ + assert(precision == -1); + ++p; + chars_to_insert = "0"; + insert_count = 1; + } + } + else if (!(*p == 'e' || *p == 'E')) { + /* Don't add ".0" if we have an exponent. */ + if (digit_count == precision) { + /* issue 5864: don't add a trailing .0 in the case + where the '%g'-formatted result already has as many + significant digits as were requested. Switch to + exponential notation instead. */ + convert_to_exp = 1; + /* no exponent, no point, and we shouldn't land here + for infs and nans, so we must be at the end of the + string. */ + assert(*p == '\0'); + } + else { + assert(precision == -1 || digit_count < precision); + chars_to_insert = ".0"; + insert_count = 2; + } + } + if (insert_count) { + size_t buf_len = strlen(buffer); + if (buf_len + insert_count + 1 >= buf_size) { + /* If there is not enough room in the buffer + for the additional text, just skip it. It's + not worth generating an error over. */ + } + else { + memmove(p + insert_count, p, + buffer + strlen(buffer) - p + 1); + memcpy(p, chars_to_insert, insert_count); + } + } + if (convert_to_exp) { + int written; + size_t buf_avail; + p = digits_start; + /* insert decimal point */ + assert(digit_count >= 1); + memmove(p+2, p+1, digit_count); /* safe, but overwrites nul */ + p[1] = '.'; + p += digit_count+1; + assert(p <= buf_size+buffer); + buf_avail = buf_size+buffer-p; + if (buf_avail == 0) + return NULL; + /* Add exponent. It's okay to use lower case 'e': we only + arrive here as a result of using the empty format code or + repr/str builtins and those never want an upper case 'E' */ + written = PyOS_snprintf(p, buf_avail, "e%+.02d", digit_count-1); + if (!(0 <= written && + written < Py_SAFE_DOWNCAST(buf_avail, size_t, int))) + /* output truncated, or something else bad happened */ + return NULL; + remove_trailing_zeros(buffer); + } + return buffer; } /* see FORMATBUFLEN in unicodeobject.c */ @@ -586,7 +586,7 @@ ensure_decimal_point(char* buffer, size_t buf_size, int precision) * @buffer: A buffer to place the resulting string in * @buf_size: The length of the buffer. * @format: The printf()-style format to use for the - * code to use for converting. + * code to use for converting. * @d: The #gdouble to convert * @precision: The precision to use when formatting. * @@ -594,7 +594,7 @@ ensure_decimal_point(char* buffer, size_t buf_size, int precision) * decimal point. To format the number you pass in * a printf()-style format string. Allowed conversion * specifiers are 'e', 'E', 'f', 'F', 'g', 'G', and 'Z'. - * + * * 'Z' is the same as 'g', except it always has a decimal and * at least one digit after the decimal. * @@ -602,83 +602,83 @@ ensure_decimal_point(char* buffer, size_t buf_size, int precision) * On failure returns NULL but does not set any Python exception. **/ static char * -_PyOS_ascii_formatd(char *buffer, - size_t buf_size, - const char *format, - double d, - int precision) +_PyOS_ascii_formatd(char *buffer, + size_t buf_size, + const char *format, + double d, + int precision) { - char format_char; - size_t format_len = strlen(format); - - /* Issue 2264: code 'Z' requires copying the format. 'Z' is 'g', but - also with at least one character past the decimal. */ - char tmp_format[FLOAT_FORMATBUFLEN]; - - /* The last character in the format string must be the format char */ - format_char = format[format_len - 1]; - - if (format[0] != '%') - return NULL; - - /* I'm not sure why this test is here. It's ensuring that the format - string after the first character doesn't have a single quote, a - lowercase l, or a percent. This is the reverse of the commented-out - test about 10 lines ago. */ - if (strpbrk(format + 1, "'l%")) - return NULL; - - /* Also curious about this function is that it accepts format strings - like "%xg", which are invalid for floats. In general, the - interface to this function is not very good, but changing it is - difficult because it's a public API. */ - - if (!(format_char == 'e' || format_char == 'E' || - format_char == 'f' || format_char == 'F' || - format_char == 'g' || format_char == 'G' || - format_char == 'Z')) - return NULL; - - /* Map 'Z' format_char to 'g', by copying the format string and - replacing the final char with a 'g' */ - if (format_char == 'Z') { - if (format_len + 1 >= sizeof(tmp_format)) { - /* The format won't fit in our copy. Error out. In - practice, this will never happen and will be - detected by returning NULL */ - return NULL; - } - strcpy(tmp_format, format); - tmp_format[format_len - 1] = 'g'; - format = tmp_format; - } - - - /* Have PyOS_snprintf do the hard work */ - PyOS_snprintf(buffer, buf_size, format, d); - - /* Do various fixups on the return string */ - - /* Get the current locale, and find the decimal point string. - Convert that string back to a dot. */ - change_decimal_from_locale_to_dot(buffer); - - /* If an exponent exists, ensure that the exponent is at least - MIN_EXPONENT_DIGITS digits, providing the buffer is large enough - for the extra zeros. Also, if there are more than - MIN_EXPONENT_DIGITS, remove as many zeros as possible until we get - back to MIN_EXPONENT_DIGITS */ - ensure_minimum_exponent_length(buffer, buf_size); - - /* If format_char is 'Z', make sure we have at least one character - after the decimal point (and make sure we have a decimal point); - also switch to exponential notation in some edge cases where the - extra character would produce more significant digits that we - really want. */ - if (format_char == 'Z') - buffer = ensure_decimal_point(buffer, buf_size, precision); - - return buffer; + char format_char; + size_t format_len = strlen(format); + + /* Issue 2264: code 'Z' requires copying the format. 'Z' is 'g', but + also with at least one character past the decimal. */ + char tmp_format[FLOAT_FORMATBUFLEN]; + + /* The last character in the format string must be the format char */ + format_char = format[format_len - 1]; + + if (format[0] != '%') + return NULL; + + /* I'm not sure why this test is here. It's ensuring that the format + string after the first character doesn't have a single quote, a + lowercase l, or a percent. This is the reverse of the commented-out + test about 10 lines ago. */ + if (strpbrk(format + 1, "'l%")) + return NULL; + + /* Also curious about this function is that it accepts format strings + like "%xg", which are invalid for floats. In general, the + interface to this function is not very good, but changing it is + difficult because it's a public API. */ + + if (!(format_char == 'e' || format_char == 'E' || + format_char == 'f' || format_char == 'F' || + format_char == 'g' || format_char == 'G' || + format_char == 'Z')) + return NULL; + + /* Map 'Z' format_char to 'g', by copying the format string and + replacing the final char with a 'g' */ + if (format_char == 'Z') { + if (format_len + 1 >= sizeof(tmp_format)) { + /* The format won't fit in our copy. Error out. In + practice, this will never happen and will be + detected by returning NULL */ + return NULL; + } + strcpy(tmp_format, format); + tmp_format[format_len - 1] = 'g'; + format = tmp_format; + } + + + /* Have PyOS_snprintf do the hard work */ + PyOS_snprintf(buffer, buf_size, format, d); + + /* Do various fixups on the return string */ + + /* Get the current locale, and find the decimal point string. + Convert that string back to a dot. */ + change_decimal_from_locale_to_dot(buffer); + + /* If an exponent exists, ensure that the exponent is at least + MIN_EXPONENT_DIGITS digits, providing the buffer is large enough + for the extra zeros. Also, if there are more than + MIN_EXPONENT_DIGITS, remove as many zeros as possible until we get + back to MIN_EXPONENT_DIGITS */ + ensure_minimum_exponent_length(buffer, buf_size); + + /* If format_char is 'Z', make sure we have at least one character + after the decimal point (and make sure we have a decimal point); + also switch to exponential notation in some edge cases where the + extra character would produce more significant digits that we + really want. */ + if (format_char == 'Z') + buffer = ensure_decimal_point(buffer, buf_size, precision); + + return buffer; } /* The fallback code to use if _Py_dg_dtoa is not available. */ @@ -689,146 +689,146 @@ PyAPI_FUNC(char *) PyOS_double_to_string(double val, int flags, int *type) { - char format[32]; - Py_ssize_t bufsize; - char *buf; - int t, exp; - int upper = 0; - - /* Validate format_code, and map upper and lower case */ - switch (format_code) { - case 'e': /* exponent */ - case 'f': /* fixed */ - case 'g': /* general */ - break; - case 'E': - upper = 1; - format_code = 'e'; - break; - case 'F': - upper = 1; - format_code = 'f'; - break; - case 'G': - upper = 1; - format_code = 'g'; - break; - case 'r': /* repr format */ - /* Supplied precision is unused, must be 0. */ - if (precision != 0) { - PyErr_BadInternalCall(); - return NULL; - } - /* The repr() precision (17 significant decimal digits) is the - minimal number that is guaranteed to have enough precision - so that if the number is read back in the exact same binary - value is recreated. This is true for IEEE floating point - by design, and also happens to work for all other modern - hardware. */ - precision = 17; - format_code = 'g'; - break; - default: - PyErr_BadInternalCall(); - return NULL; - } - - /* Here's a quick-and-dirty calculation to figure out how big a buffer - we need. In general, for a finite float we need: - - 1 byte for each digit of the decimal significand, and - - 1 for a possible sign - 1 for a possible decimal point - 2 for a possible [eE][+-] - 1 for each digit of the exponent; if we allow 19 digits - total then we're safe up to exponents of 2**63. - 1 for the trailing nul byte - - This gives a total of 24 + the number of digits in the significand, - and the number of digits in the significand is: - - for 'g' format: at most precision, except possibly - when precision == 0, when it's 1. - for 'e' format: precision+1 - for 'f' format: precision digits after the point, at least 1 - before. To figure out how many digits appear before the point - we have to examine the size of the number. If fabs(val) < 1.0 - then there will be only one digit before the point. If - fabs(val) >= 1.0, then there are at most - - 1+floor(log10(ceiling(fabs(val)))) - - digits before the point (where the 'ceiling' allows for the - possibility that the rounding rounds the integer part of val - up). A safe upper bound for the above quantity is - 1+floor(exp/3), where exp is the unique integer such that 0.5 - <= fabs(val)/2**exp < 1.0. This exp can be obtained from - frexp. - - So we allow room for precision+1 digits for all formats, plus an - extra floor(exp/3) digits for 'f' format. - - */ - - if (Py_IS_NAN(val) || Py_IS_INFINITY(val)) - /* 3 for 'inf'/'nan', 1 for sign, 1 for '\0' */ - bufsize = 5; - else { - bufsize = 25 + precision; - if (format_code == 'f' && fabs(val) >= 1.0) { - frexp(val, &exp); - bufsize += exp/3; - } - } - - buf = PyMem_Malloc(bufsize); - if (buf == NULL) { - PyErr_NoMemory(); - return NULL; - } - - /* Handle nan and inf. */ - if (Py_IS_NAN(val)) { - strcpy(buf, "nan"); - t = Py_DTST_NAN; - } else if (Py_IS_INFINITY(val)) { - if (copysign(1., val) == 1.) - strcpy(buf, "inf"); - else - strcpy(buf, "-inf"); - t = Py_DTST_INFINITE; - } else { - t = Py_DTST_FINITE; - if (flags & Py_DTSF_ADD_DOT_0) - format_code = 'Z'; - - PyOS_snprintf(format, sizeof(format), "%%%s.%i%c", - (flags & Py_DTSF_ALT ? "#" : ""), precision, - format_code); - _PyOS_ascii_formatd(buf, bufsize, format, val, precision); - } - - /* Add sign when requested. It's convenient (esp. when formatting - complex numbers) to include a sign even for inf and nan. */ - if (flags & Py_DTSF_SIGN && buf[0] != '-') { - size_t len = strlen(buf); - /* the bufsize calculations above should ensure that we've got - space to add a sign */ - assert((size_t)bufsize >= len+2); - memmove(buf+1, buf, len+1); - buf[0] = '+'; - } - if (upper) { - /* Convert to upper case. */ - char *p1; - for (p1 = buf; *p1; p1++) - *p1 = Py_TOUPPER(*p1); - } - - if (type) - *type = t; - return buf; + char format[32]; + Py_ssize_t bufsize; + char *buf; + int t, exp; + int upper = 0; + + /* Validate format_code, and map upper and lower case */ + switch (format_code) { + case 'e': /* exponent */ + case 'f': /* fixed */ + case 'g': /* general */ + break; + case 'E': + upper = 1; + format_code = 'e'; + break; + case 'F': + upper = 1; + format_code = 'f'; + break; + case 'G': + upper = 1; + format_code = 'g'; + break; + case 'r': /* repr format */ + /* Supplied precision is unused, must be 0. */ + if (precision != 0) { + PyErr_BadInternalCall(); + return NULL; + } + /* The repr() precision (17 significant decimal digits) is the + minimal number that is guaranteed to have enough precision + so that if the number is read back in the exact same binary + value is recreated. This is true for IEEE floating point + by design, and also happens to work for all other modern + hardware. */ + precision = 17; + format_code = 'g'; + break; + default: + PyErr_BadInternalCall(); + return NULL; + } + + /* Here's a quick-and-dirty calculation to figure out how big a buffer + we need. In general, for a finite float we need: + + 1 byte for each digit of the decimal significand, and + + 1 for a possible sign + 1 for a possible decimal point + 2 for a possible [eE][+-] + 1 for each digit of the exponent; if we allow 19 digits + total then we're safe up to exponents of 2**63. + 1 for the trailing nul byte + + This gives a total of 24 + the number of digits in the significand, + and the number of digits in the significand is: + + for 'g' format: at most precision, except possibly + when precision == 0, when it's 1. + for 'e' format: precision+1 + for 'f' format: precision digits after the point, at least 1 + before. To figure out how many digits appear before the point + we have to examine the size of the number. If fabs(val) < 1.0 + then there will be only one digit before the point. If + fabs(val) >= 1.0, then there are at most + + 1+floor(log10(ceiling(fabs(val)))) + + digits before the point (where the 'ceiling' allows for the + possibility that the rounding rounds the integer part of val + up). A safe upper bound for the above quantity is + 1+floor(exp/3), where exp is the unique integer such that 0.5 + <= fabs(val)/2**exp < 1.0. This exp can be obtained from + frexp. + + So we allow room for precision+1 digits for all formats, plus an + extra floor(exp/3) digits for 'f' format. + + */ + + if (Py_IS_NAN(val) || Py_IS_INFINITY(val)) + /* 3 for 'inf'/'nan', 1 for sign, 1 for '\0' */ + bufsize = 5; + else { + bufsize = 25 + precision; + if (format_code == 'f' && fabs(val) >= 1.0) { + frexp(val, &exp); + bufsize += exp/3; + } + } + + buf = PyMem_Malloc(bufsize); + if (buf == NULL) { + PyErr_NoMemory(); + return NULL; + } + + /* Handle nan and inf. */ + if (Py_IS_NAN(val)) { + strcpy(buf, "nan"); + t = Py_DTST_NAN; + } else if (Py_IS_INFINITY(val)) { + if (copysign(1., val) == 1.) + strcpy(buf, "inf"); + else + strcpy(buf, "-inf"); + t = Py_DTST_INFINITE; + } else { + t = Py_DTST_FINITE; + if (flags & Py_DTSF_ADD_DOT_0) + format_code = 'Z'; + + PyOS_snprintf(format, sizeof(format), "%%%s.%i%c", + (flags & Py_DTSF_ALT ? "#" : ""), precision, + format_code); + _PyOS_ascii_formatd(buf, bufsize, format, val, precision); + } + + /* Add sign when requested. It's convenient (esp. when formatting + complex numbers) to include a sign even for inf and nan. */ + if (flags & Py_DTSF_SIGN && buf[0] != '-') { + size_t len = strlen(buf); + /* the bufsize calculations above should ensure that we've got + space to add a sign */ + assert((size_t)bufsize >= len+2); + memmove(buf+1, buf, len+1); + buf[0] = '+'; + } + if (upper) { + /* Convert to upper case. */ + char *p1; + for (p1 = buf; *p1; p1++) + *p1 = Py_TOUPPER(*p1); + } + + if (type) + *type = t; + return buf; } #else @@ -843,14 +843,14 @@ PyAPI_FUNC(char *) PyOS_double_to_string(double val, /* The lengths of these are known to the code below, so don't change them */ static char *lc_float_strings[] = { - "inf", - "nan", - "e", + "inf", + "nan", + "e", }; static char *uc_float_strings[] = { - "INF", - "NAN", - "E", + "INF", + "NAN", + "E", }; @@ -874,9 +874,9 @@ static char *uc_float_strings[] = { be nonzero. type, if non-NULL, will be set to one of these constants to identify the type of the 'd' argument: - Py_DTST_FINITE - Py_DTST_INFINITE - Py_DTST_NAN + Py_DTST_FINITE + Py_DTST_INFINITE + Py_DTST_NAN Returns a PyMem_Malloc'd block of memory containing the resulting string, or NULL on error. If NULL is returned, the Python error has been set. @@ -884,315 +884,315 @@ static char *uc_float_strings[] = { static char * format_float_short(double d, char format_code, - int mode, Py_ssize_t precision, - int always_add_sign, int add_dot_0_if_integer, - int use_alt_formatting, char **float_strings, int *type) + int mode, Py_ssize_t precision, + int always_add_sign, int add_dot_0_if_integer, + int use_alt_formatting, char **float_strings, int *type) { - char *buf = NULL; - char *p = NULL; - Py_ssize_t bufsize = 0; - char *digits, *digits_end; - int decpt_as_int, sign, exp_len, exp = 0, use_exp = 0; - Py_ssize_t decpt, digits_len, vdigits_start, vdigits_end; - _Py_SET_53BIT_PRECISION_HEADER; - - /* _Py_dg_dtoa returns a digit string (no decimal point or exponent). - Must be matched by a call to _Py_dg_freedtoa. */ - _Py_SET_53BIT_PRECISION_START; - digits = _Py_dg_dtoa(d, mode, precision, &decpt_as_int, &sign, - &digits_end); - _Py_SET_53BIT_PRECISION_END; - - decpt = (Py_ssize_t)decpt_as_int; - if (digits == NULL) { - /* The only failure mode is no memory. */ - PyErr_NoMemory(); - goto exit; - } - assert(digits_end != NULL && digits_end >= digits); - digits_len = digits_end - digits; - - if (digits_len && !Py_ISDIGIT(digits[0])) { - /* Infinities and nans here; adapt Gay's output, - so convert Infinity to inf and NaN to nan, and - ignore sign of nan. Then return. */ - - /* ignore the actual sign of a nan */ - if (digits[0] == 'n' || digits[0] == 'N') - sign = 0; - - /* We only need 5 bytes to hold the result "+inf\0" . */ - bufsize = 5; /* Used later in an assert. */ - buf = (char *)PyMem_Malloc(bufsize); - if (buf == NULL) { - PyErr_NoMemory(); - goto exit; - } - p = buf; - - if (sign == 1) { - *p++ = '-'; - } - else if (always_add_sign) { - *p++ = '+'; - } - if (digits[0] == 'i' || digits[0] == 'I') { - strncpy(p, float_strings[OFS_INF], 3); - p += 3; - - if (type) - *type = Py_DTST_INFINITE; - } - else if (digits[0] == 'n' || digits[0] == 'N') { - strncpy(p, float_strings[OFS_NAN], 3); - p += 3; - - if (type) - *type = Py_DTST_NAN; - } - else { - /* shouldn't get here: Gay's code should always return - something starting with a digit, an 'I', or 'N' */ - strncpy(p, "ERR", 3); - p += 3; - assert(0); - } - goto exit; - } - - /* The result must be finite (not inf or nan). */ - if (type) - *type = Py_DTST_FINITE; - - - /* We got digits back, format them. We may need to pad 'digits' - either on the left or right (or both) with extra zeros, so in - general the resulting string has the form - - [][] - - where either of the pieces could be empty, and there's a - decimal point that could appear either in or in the - leading or trailing . - - Imagine an infinite 'virtual' string vdigits, consisting of the - string 'digits' (starting at index 0) padded on both the left and - right with infinite strings of zeros. We want to output a slice - - vdigits[vdigits_start : vdigits_end] - - of this virtual string. Thus if vdigits_start < 0 then we'll end - up producing some leading zeros; if vdigits_end > digits_len there - will be trailing zeros in the output. The next section of code - determines whether to use an exponent or not, figures out the - position 'decpt' of the decimal point, and computes 'vdigits_start' - and 'vdigits_end'. */ - vdigits_end = digits_len; - switch (format_code) { - case 'e': - use_exp = 1; - vdigits_end = precision; - break; - case 'f': - vdigits_end = decpt + precision; - break; - case 'g': - if (decpt <= -4 || decpt > - (add_dot_0_if_integer ? precision-1 : precision)) - use_exp = 1; - if (use_alt_formatting) - vdigits_end = precision; - break; - case 'r': - /* convert to exponential format at 1e16. We used to convert - at 1e17, but that gives odd-looking results for some values - when a 16-digit 'shortest' repr is padded with bogus zeros. - For example, repr(2e16+8) would give 20000000000000010.0; - the true value is 20000000000000008.0. */ - if (decpt <= -4 || decpt > 16) - use_exp = 1; - break; - default: - PyErr_BadInternalCall(); - goto exit; - } - - /* if using an exponent, reset decimal point position to 1 and adjust - exponent accordingly.*/ - if (use_exp) { - exp = decpt - 1; - decpt = 1; - } - /* ensure vdigits_start < decpt <= vdigits_end, or vdigits_start < - decpt < vdigits_end if add_dot_0_if_integer and no exponent */ - vdigits_start = decpt <= 0 ? decpt-1 : 0; - if (!use_exp && add_dot_0_if_integer) - vdigits_end = vdigits_end > decpt ? vdigits_end : decpt + 1; - else - vdigits_end = vdigits_end > decpt ? vdigits_end : decpt; - - /* double check inequalities */ - assert(vdigits_start <= 0 && - 0 <= digits_len && - digits_len <= vdigits_end); - /* decimal point should be in (vdigits_start, vdigits_end] */ - assert(vdigits_start < decpt && decpt <= vdigits_end); - - /* Compute an upper bound how much memory we need. This might be a few - chars too long, but no big deal. */ - bufsize = - /* sign, decimal point and trailing 0 byte */ - 3 + - - /* total digit count (including zero padding on both sides) */ - (vdigits_end - vdigits_start) + - - /* exponent "e+100", max 3 numerical digits */ - (use_exp ? 5 : 0); - - /* Now allocate the memory and initialize p to point to the start of - it. */ - buf = (char *)PyMem_Malloc(bufsize); - if (buf == NULL) { - PyErr_NoMemory(); - goto exit; - } - p = buf; - - /* Add a negative sign if negative, and a plus sign if non-negative - and always_add_sign is true. */ - if (sign == 1) - *p++ = '-'; - else if (always_add_sign) - *p++ = '+'; - - /* note that exactly one of the three 'if' conditions is true, - so we include exactly one decimal point */ - /* Zero padding on left of digit string */ - if (decpt <= 0) { - memset(p, '0', decpt-vdigits_start); - p += decpt - vdigits_start; - *p++ = '.'; - memset(p, '0', 0-decpt); - p += 0-decpt; - } - else { - memset(p, '0', 0-vdigits_start); - p += 0 - vdigits_start; - } - - /* Digits, with included decimal point */ - if (0 < decpt && decpt <= digits_len) { - strncpy(p, digits, decpt-0); - p += decpt-0; - *p++ = '.'; - strncpy(p, digits+decpt, digits_len-decpt); - p += digits_len-decpt; - } - else { - strncpy(p, digits, digits_len); - p += digits_len; - } - - /* And zeros on the right */ - if (digits_len < decpt) { - memset(p, '0', decpt-digits_len); - p += decpt-digits_len; - *p++ = '.'; - memset(p, '0', vdigits_end-decpt); - p += vdigits_end-decpt; - } - else { - memset(p, '0', vdigits_end-digits_len); - p += vdigits_end-digits_len; - } - - /* Delete a trailing decimal pt unless using alternative formatting. */ - if (p[-1] == '.' && !use_alt_formatting) - p--; - - /* Now that we've done zero padding, add an exponent if needed. */ - if (use_exp) { - *p++ = float_strings[OFS_E][0]; - exp_len = sprintf(p, "%+.02d", exp); - p += exp_len; - } + char *buf = NULL; + char *p = NULL; + Py_ssize_t bufsize = 0; + char *digits, *digits_end; + int decpt_as_int, sign, exp_len, exp = 0, use_exp = 0; + Py_ssize_t decpt, digits_len, vdigits_start, vdigits_end; + _Py_SET_53BIT_PRECISION_HEADER; + + /* _Py_dg_dtoa returns a digit string (no decimal point or exponent). + Must be matched by a call to _Py_dg_freedtoa. */ + _Py_SET_53BIT_PRECISION_START; + digits = _Py_dg_dtoa(d, mode, precision, &decpt_as_int, &sign, + &digits_end); + _Py_SET_53BIT_PRECISION_END; + + decpt = (Py_ssize_t)decpt_as_int; + if (digits == NULL) { + /* The only failure mode is no memory. */ + PyErr_NoMemory(); + goto exit; + } + assert(digits_end != NULL && digits_end >= digits); + digits_len = digits_end - digits; + + if (digits_len && !Py_ISDIGIT(digits[0])) { + /* Infinities and nans here; adapt Gay's output, + so convert Infinity to inf and NaN to nan, and + ignore sign of nan. Then return. */ + + /* ignore the actual sign of a nan */ + if (digits[0] == 'n' || digits[0] == 'N') + sign = 0; + + /* We only need 5 bytes to hold the result "+inf\0" . */ + bufsize = 5; /* Used later in an assert. */ + buf = (char *)PyMem_Malloc(bufsize); + if (buf == NULL) { + PyErr_NoMemory(); + goto exit; + } + p = buf; + + if (sign == 1) { + *p++ = '-'; + } + else if (always_add_sign) { + *p++ = '+'; + } + if (digits[0] == 'i' || digits[0] == 'I') { + strncpy(p, float_strings[OFS_INF], 3); + p += 3; + + if (type) + *type = Py_DTST_INFINITE; + } + else if (digits[0] == 'n' || digits[0] == 'N') { + strncpy(p, float_strings[OFS_NAN], 3); + p += 3; + + if (type) + *type = Py_DTST_NAN; + } + else { + /* shouldn't get here: Gay's code should always return + something starting with a digit, an 'I', or 'N' */ + strncpy(p, "ERR", 3); + p += 3; + assert(0); + } + goto exit; + } + + /* The result must be finite (not inf or nan). */ + if (type) + *type = Py_DTST_FINITE; + + + /* We got digits back, format them. We may need to pad 'digits' + either on the left or right (or both) with extra zeros, so in + general the resulting string has the form + + [][] + + where either of the pieces could be empty, and there's a + decimal point that could appear either in or in the + leading or trailing . + + Imagine an infinite 'virtual' string vdigits, consisting of the + string 'digits' (starting at index 0) padded on both the left and + right with infinite strings of zeros. We want to output a slice + + vdigits[vdigits_start : vdigits_end] + + of this virtual string. Thus if vdigits_start < 0 then we'll end + up producing some leading zeros; if vdigits_end > digits_len there + will be trailing zeros in the output. The next section of code + determines whether to use an exponent or not, figures out the + position 'decpt' of the decimal point, and computes 'vdigits_start' + and 'vdigits_end'. */ + vdigits_end = digits_len; + switch (format_code) { + case 'e': + use_exp = 1; + vdigits_end = precision; + break; + case 'f': + vdigits_end = decpt + precision; + break; + case 'g': + if (decpt <= -4 || decpt > + (add_dot_0_if_integer ? precision-1 : precision)) + use_exp = 1; + if (use_alt_formatting) + vdigits_end = precision; + break; + case 'r': + /* convert to exponential format at 1e16. We used to convert + at 1e17, but that gives odd-looking results for some values + when a 16-digit 'shortest' repr is padded with bogus zeros. + For example, repr(2e16+8) would give 20000000000000010.0; + the true value is 20000000000000008.0. */ + if (decpt <= -4 || decpt > 16) + use_exp = 1; + break; + default: + PyErr_BadInternalCall(); + goto exit; + } + + /* if using an exponent, reset decimal point position to 1 and adjust + exponent accordingly.*/ + if (use_exp) { + exp = decpt - 1; + decpt = 1; + } + /* ensure vdigits_start < decpt <= vdigits_end, or vdigits_start < + decpt < vdigits_end if add_dot_0_if_integer and no exponent */ + vdigits_start = decpt <= 0 ? decpt-1 : 0; + if (!use_exp && add_dot_0_if_integer) + vdigits_end = vdigits_end > decpt ? vdigits_end : decpt + 1; + else + vdigits_end = vdigits_end > decpt ? vdigits_end : decpt; + + /* double check inequalities */ + assert(vdigits_start <= 0 && + 0 <= digits_len && + digits_len <= vdigits_end); + /* decimal point should be in (vdigits_start, vdigits_end] */ + assert(vdigits_start < decpt && decpt <= vdigits_end); + + /* Compute an upper bound how much memory we need. This might be a few + chars too long, but no big deal. */ + bufsize = + /* sign, decimal point and trailing 0 byte */ + 3 + + + /* total digit count (including zero padding on both sides) */ + (vdigits_end - vdigits_start) + + + /* exponent "e+100", max 3 numerical digits */ + (use_exp ? 5 : 0); + + /* Now allocate the memory and initialize p to point to the start of + it. */ + buf = (char *)PyMem_Malloc(bufsize); + if (buf == NULL) { + PyErr_NoMemory(); + goto exit; + } + p = buf; + + /* Add a negative sign if negative, and a plus sign if non-negative + and always_add_sign is true. */ + if (sign == 1) + *p++ = '-'; + else if (always_add_sign) + *p++ = '+'; + + /* note that exactly one of the three 'if' conditions is true, + so we include exactly one decimal point */ + /* Zero padding on left of digit string */ + if (decpt <= 0) { + memset(p, '0', decpt-vdigits_start); + p += decpt - vdigits_start; + *p++ = '.'; + memset(p, '0', 0-decpt); + p += 0-decpt; + } + else { + memset(p, '0', 0-vdigits_start); + p += 0 - vdigits_start; + } + + /* Digits, with included decimal point */ + if (0 < decpt && decpt <= digits_len) { + strncpy(p, digits, decpt-0); + p += decpt-0; + *p++ = '.'; + strncpy(p, digits+decpt, digits_len-decpt); + p += digits_len-decpt; + } + else { + strncpy(p, digits, digits_len); + p += digits_len; + } + + /* And zeros on the right */ + if (digits_len < decpt) { + memset(p, '0', decpt-digits_len); + p += decpt-digits_len; + *p++ = '.'; + memset(p, '0', vdigits_end-decpt); + p += vdigits_end-decpt; + } + else { + memset(p, '0', vdigits_end-digits_len); + p += vdigits_end-digits_len; + } + + /* Delete a trailing decimal pt unless using alternative formatting. */ + if (p[-1] == '.' && !use_alt_formatting) + p--; + + /* Now that we've done zero padding, add an exponent if needed. */ + if (use_exp) { + *p++ = float_strings[OFS_E][0]; + exp_len = sprintf(p, "%+.02d", exp); + p += exp_len; + } exit: - if (buf) { - *p = '\0'; - /* It's too late if this fails, as we've already stepped on - memory that isn't ours. But it's an okay debugging test. */ - assert(p-buf < bufsize); - } - if (digits) - _Py_dg_freedtoa(digits); - - return buf; + if (buf) { + *p = '\0'; + /* It's too late if this fails, as we've already stepped on + memory that isn't ours. But it's an okay debugging test. */ + assert(p-buf < bufsize); + } + if (digits) + _Py_dg_freedtoa(digits); + + return buf; } PyAPI_FUNC(char *) PyOS_double_to_string(double val, - char format_code, - int precision, - int flags, - int *type) + char format_code, + int precision, + int flags, + int *type) { - char **float_strings = lc_float_strings; - int mode; - - /* Validate format_code, and map upper and lower case. Compute the - mode and make any adjustments as needed. */ - switch (format_code) { - /* exponent */ - case 'E': - float_strings = uc_float_strings; - format_code = 'e'; - /* Fall through. */ - case 'e': - mode = 2; - precision++; - break; - - /* fixed */ - case 'F': - float_strings = uc_float_strings; - format_code = 'f'; - /* Fall through. */ - case 'f': - mode = 3; - break; - - /* general */ - case 'G': - float_strings = uc_float_strings; - format_code = 'g'; - /* Fall through. */ - case 'g': - mode = 2; - /* precision 0 makes no sense for 'g' format; interpret as 1 */ - if (precision == 0) - precision = 1; - break; - - /* repr format */ - case 'r': - mode = 0; - /* Supplied precision is unused, must be 0. */ - if (precision != 0) { - PyErr_BadInternalCall(); - return NULL; - } - break; - - default: - PyErr_BadInternalCall(); - return NULL; - } - - return format_float_short(val, format_code, mode, precision, - flags & Py_DTSF_SIGN, - flags & Py_DTSF_ADD_DOT_0, - flags & Py_DTSF_ALT, - float_strings, type); + char **float_strings = lc_float_strings; + int mode; + + /* Validate format_code, and map upper and lower case. Compute the + mode and make any adjustments as needed. */ + switch (format_code) { + /* exponent */ + case 'E': + float_strings = uc_float_strings; + format_code = 'e'; + /* Fall through. */ + case 'e': + mode = 2; + precision++; + break; + + /* fixed */ + case 'F': + float_strings = uc_float_strings; + format_code = 'f'; + /* Fall through. */ + case 'f': + mode = 3; + break; + + /* general */ + case 'G': + float_strings = uc_float_strings; + format_code = 'g'; + /* Fall through. */ + case 'g': + mode = 2; + /* precision 0 makes no sense for 'g' format; interpret as 1 */ + if (precision == 0) + precision = 1; + break; + + /* repr format */ + case 'r': + mode = 0; + /* Supplied precision is unused, must be 0. */ + if (precision != 0) { + PyErr_BadInternalCall(); + return NULL; + } + break; + + default: + PyErr_BadInternalCall(); + return NULL; + } + + return format_float_short(val, format_code, mode, precision, + flags & Py_DTSF_SIGN, + flags & Py_DTSF_ADD_DOT_0, + flags & Py_DTSF_ALT, + float_strings, type); } #endif /* ifdef PY_NO_SHORT_FLOAT_REPR */ diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 05a10c61c4..e58b1c8ab9 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -42,9 +42,9 @@ #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()) +#define PRINT_TOTAL_REFS() fprintf(stderr, \ + "[%" PY_FORMAT_SIZE_T "d refs]\n", \ + _Py_GetRefTotal()) #endif #ifdef __cplusplus @@ -61,9 +61,9 @@ static void initsite(void); static int initstdio(void); static void flush_io(void); static PyObject *run_mod(mod_ty, const char *, PyObject *, PyObject *, - PyCompilerFlags *, PyArena *); + PyCompilerFlags *, PyArena *); static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *, - PyCompilerFlags *); + PyCompilerFlags *); static void err_input(perrdetail *); static void initsigs(void); static void call_py_exitfuncs(void); @@ -97,7 +97,7 @@ since _warnings is builtin. This API should not be used. */ PyObject * PyModule_GetWarningsModule(void) { - return PyImport_ImportModule("warnings"); + return PyImport_ImportModule("warnings"); } static int initialized = 0; @@ -107,7 +107,7 @@ static int initialized = 0; int Py_IsInitialized(void) { - return initialized; + return initialized; } /* Global initializations. Can be undone by Py_Finalize(). Don't @@ -125,191 +125,191 @@ Py_IsInitialized(void) 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; + int env = atoi(envs); + if (flag < env) + flag = env; + if (flag < 1) + flag = 1; + return flag; } #if defined(HAVE_LANGINFO_H) && defined(CODESET) static char* get_codeset(void) { - char* codeset; - PyObject *codec, *name; + char* codeset; + PyObject *codec, *name; - codeset = nl_langinfo(CODESET); - if (!codeset || codeset[0] == '\0') - return NULL; + codeset = nl_langinfo(CODESET); + if (!codeset || codeset[0] == '\0') + return NULL; - codec = _PyCodec_Lookup(codeset); - if (!codec) - goto error; + codec = _PyCodec_Lookup(codeset); + if (!codec) + goto error; - name = PyObject_GetAttrString(codec, "name"); - Py_CLEAR(codec); - if (!name) - goto error; + name = PyObject_GetAttrString(codec, "name"); + Py_CLEAR(codec); + if (!name) + goto error; - codeset = strdup(_PyUnicode_AsString(name)); - Py_DECREF(name); - return codeset; + codeset = strdup(_PyUnicode_AsString(name)); + Py_DECREF(name); + return codeset; error: - Py_XDECREF(codec); - PyErr_Clear(); - return NULL; + Py_XDECREF(codec); + PyErr_Clear(); + return NULL; } #endif void Py_InitializeEx(int install_sigs) { - PyInterpreterState *interp; - PyThreadState *tstate; - PyObject *bimod, *sysmod, *pstderr; - char *p; + PyInterpreterState *interp; + PyThreadState *tstate; + PyObject *bimod, *sysmod, *pstderr; + char *p; #if defined(HAVE_LANGINFO_H) && defined(CODESET) - char *codeset; + char *codeset; #endif - extern void _Py_ReadyTypes(void); + extern void _Py_ReadyTypes(void); - if (initialized) - return; - initialized = 1; + if (initialized) + return; + initialized = 1; #if defined(HAVE_LANGINFO_H) && defined(HAVE_SETLOCALE) - /* Set up the LC_CTYPE locale, so we can obtain - the locale's charset without having to switch - locales. */ - setlocale(LC_CTYPE, ""); + /* Set up the LC_CTYPE locale, so we can obtain + the locale's charset without having to switch + locales. */ + setlocale(LC_CTYPE, ""); #endif - 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); - if ((p = Py_GETENV("PYTHONDONTWRITEBYTECODE")) && *p != '\0') - Py_DontWriteBytecodeFlag = add_flag(Py_DontWriteBytecodeFlag, 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 (!_PyLong_Init()) - Py_FatalError("Py_Initialize: can't init longs"); - - if (!PyByteArray_Init()) - Py_FatalError("Py_Initialize: can't init bytearray"); - - _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"); - - /* Init Unicode implementation; relies on the codec registry */ - _PyUnicode_Init(); - - bimod = _PyBuiltin_Init(); - if (bimod == NULL) - Py_FatalError("Py_Initialize: can't initialize builtins modules"); - _PyImport_FixupExtension(bimod, "builtins", "builtins"); - interp->builtins = PyModule_GetDict(bimod); - if (interp->builtins == NULL) - Py_FatalError("Py_Initialize: can't initialize builtins dict"); - Py_INCREF(interp->builtins); - - /* initialize builtin exceptions */ - _PyExc_Init(); - - 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(sysmod, "sys", "sys"); - PySys_SetPath(Py_GetPath()); - PyDict_SetItemString(interp->sysdict, "modules", - interp->modules); - - /* Set up a preliminary stderr printer until we have enough - infrastructure for the io module in place. */ - pstderr = PyFile_NewStdPrinter(fileno(stderr)); - if (pstderr == NULL) - Py_FatalError("Py_Initialize: can't set preliminary stderr"); - PySys_SetObject("stderr", pstderr); - PySys_SetObject("__stderr__", pstderr); - - _PyImport_Init(); - - _PyImportHooks_Init(); + 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); + if ((p = Py_GETENV("PYTHONDONTWRITEBYTECODE")) && *p != '\0') + Py_DontWriteBytecodeFlag = add_flag(Py_DontWriteBytecodeFlag, 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 (!_PyLong_Init()) + Py_FatalError("Py_Initialize: can't init longs"); + + if (!PyByteArray_Init()) + Py_FatalError("Py_Initialize: can't init bytearray"); + + _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"); + + /* Init Unicode implementation; relies on the codec registry */ + _PyUnicode_Init(); + + bimod = _PyBuiltin_Init(); + if (bimod == NULL) + Py_FatalError("Py_Initialize: can't initialize builtins modules"); + _PyImport_FixupExtension(bimod, "builtins", "builtins"); + interp->builtins = PyModule_GetDict(bimod); + if (interp->builtins == NULL) + Py_FatalError("Py_Initialize: can't initialize builtins dict"); + Py_INCREF(interp->builtins); + + /* initialize builtin exceptions */ + _PyExc_Init(); + + 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(sysmod, "sys", "sys"); + PySys_SetPath(Py_GetPath()); + PyDict_SetItemString(interp->sysdict, "modules", + interp->modules); + + /* Set up a preliminary stderr printer until we have enough + infrastructure for the io module in place. */ + pstderr = PyFile_NewStdPrinter(fileno(stderr)); + if (pstderr == NULL) + Py_FatalError("Py_Initialize: can't set preliminary stderr"); + PySys_SetObject("stderr", pstderr); + PySys_SetObject("__stderr__", pstderr); + + _PyImport_Init(); + + _PyImportHooks_Init(); #if 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. */ - - codeset = get_codeset(); - if (codeset) { - if (!Py_FileSystemDefaultEncoding) - Py_FileSystemDefaultEncoding = codeset; - else - free(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. */ + + codeset = get_codeset(); + if (codeset) { + if (!Py_FileSystemDefaultEncoding) + Py_FileSystemDefaultEncoding = codeset; + else + free(codeset); + } #endif - if (install_sigs) - initsigs(); /* Signal handling stuff, including initintr() */ - - /* Initialize warnings. */ - _PyWarnings_Init(); - if (PySys_HasWarnOptions()) { - PyObject *warnings_module = PyImport_ImportModule("warnings"); - if (!warnings_module) - PyErr_Clear(); - Py_XDECREF(warnings_module); - } - - initmain(); /* Module __main__ */ - if (initstdio() < 0) - Py_FatalError( - "Py_Initialize: can't initialize sys standard streams"); - - /* auto-thread-state API, if available */ + if (install_sigs) + initsigs(); /* Signal handling stuff, including initintr() */ + + /* Initialize warnings. */ + _PyWarnings_Init(); + if (PySys_HasWarnOptions()) { + PyObject *warnings_module = PyImport_ImportModule("warnings"); + if (!warnings_module) + PyErr_Clear(); + Py_XDECREF(warnings_module); + } + + initmain(); /* Module __main__ */ + if (initstdio() < 0) + Py_FatalError( + "Py_Initialize: can't initialize sys standard streams"); + + /* auto-thread-state API, if available */ #ifdef WITH_THREAD - _PyGILState_Init(interp, tstate); + _PyGILState_Init(interp, tstate); #endif /* WITH_THREAD */ - if (!Py_NoSiteFlag) - initsite(); /* Module site */ + if (!Py_NoSiteFlag) + initsite(); /* Module site */ } void Py_Initialize(void) { - Py_InitializeEx(1); + Py_InitializeEx(1); } @@ -322,25 +322,25 @@ extern void dump_counts(FILE*); static void flush_std_files(void) { - PyObject *fout = PySys_GetObject("stdout"); - PyObject *ferr = PySys_GetObject("stderr"); - PyObject *tmp; + PyObject *fout = PySys_GetObject("stdout"); + PyObject *ferr = PySys_GetObject("stderr"); + PyObject *tmp; - if (fout != NULL && fout != Py_None) { - tmp = PyObject_CallMethod(fout, "flush", ""); - if (tmp == NULL) - PyErr_Clear(); - else - Py_DECREF(tmp); - } + if (fout != NULL && fout != Py_None) { + tmp = PyObject_CallMethod(fout, "flush", ""); + if (tmp == NULL) + PyErr_Clear(); + else + Py_DECREF(tmp); + } - if (ferr != NULL || ferr != Py_None) { - tmp = PyObject_CallMethod(ferr, "flush", ""); - if (tmp == NULL) - PyErr_Clear(); - else - Py_DECREF(tmp); - } + if (ferr != NULL || ferr != Py_None) { + tmp = PyObject_CallMethod(ferr, "flush", ""); + if (tmp == NULL) + PyErr_Clear(); + else + Py_DECREF(tmp); + } } /* Undo the effect of Py_Initialize(). @@ -360,169 +360,169 @@ flush_std_files(void) void Py_Finalize(void) { - PyInterpreterState *interp; - PyThreadState *tstate; - - if (!initialized) - return; - - wait_for_thread_shutdown(); - - /* 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_py_exitfuncs(); - initialized = 0; - - /* Flush stdout+stderr */ - flush_std_files(); - - /* Get current thread state and interpreter pointer */ - tstate = PyThreadState_GET(); - interp = tstate->interp; - - /* Disable signal handling */ - PyOS_FiniInterrupts(); - - /* Clear type lookup cache */ - PyType_ClearCache(); - - /* 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 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(); + PyInterpreterState *interp; + PyThreadState *tstate; + + if (!initialized) + return; + + wait_for_thread_shutdown(); + + /* 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_py_exitfuncs(); + initialized = 0; + + /* Flush stdout+stderr */ + flush_std_files(); + + /* Get current thread state and interpreter pointer */ + tstate = PyThreadState_GET(); + interp = tstate->interp; + + /* Disable signal handling */ + PyOS_FiniInterrupts(); + + /* Clear type lookup cache */ + PyType_ClearCache(); + + /* 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 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 */; + /* 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(); - - /* Flush stdout+stderr (again, in case more was printed) */ - flush_std_files(); - - /* 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. - */ + /* Destroy all modules */ + PyImport_Cleanup(); + + /* Flush stdout+stderr (again, in case more was printed) */ + flush_std_files(); + + /* 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(); + PyGC_Collect(); #endif - /* Destroy the database used by _PyImport_{Fixup,Find}Extension */ - _PyImport_Fini(); + /* Destroy the database used by _PyImport_{Fixup,Find}Extension */ + _PyImport_Fini(); - /* Debugging stuff */ + /* Debugging stuff */ #ifdef COUNT_ALLOCS - dump_counts(stdout); + dump_counts(stdout); #endif - PRINT_TOTAL_REFS(); + 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); + /* 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 */ - /* Clear interpreter state */ - PyInterpreterState_Clear(interp); + /* 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. - */ + /* 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(); + _PyExc_Fini(); - /* Cleanup auto-thread-state */ + /* Cleanup auto-thread-state */ #ifdef WITH_THREAD - _PyGILState_Fini(); + _PyGILState_Fini(); #endif /* WITH_THREAD */ - /* Delete current thread */ - PyThreadState_Swap(NULL); - PyInterpreterState_Delete(interp); - - /* Sundry finalizers */ - PyMethod_Fini(); - PyFrame_Fini(); - PyCFunction_Fini(); - PyTuple_Fini(); - PyList_Fini(); - PySet_Fini(); - PyBytes_Fini(); - PyByteArray_Fini(); - PyLong_Fini(); - PyFloat_Fini(); - PyDict_Fini(); - - /* Cleanup Unicode implementation */ - _PyUnicode_Fini(); - - /* reset file system default encoding */ - if (!Py_HasFileSystemDefaultEncoding) { - free((char*)Py_FileSystemDefaultEncoding); - Py_FileSystemDefaultEncoding = NULL; - } - - /* 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); + /* Delete current thread */ + PyThreadState_Swap(NULL); + PyInterpreterState_Delete(interp); + + /* Sundry finalizers */ + PyMethod_Fini(); + PyFrame_Fini(); + PyCFunction_Fini(); + PyTuple_Fini(); + PyList_Fini(); + PySet_Fini(); + PyBytes_Fini(); + PyByteArray_Fini(); + PyLong_Fini(); + PyFloat_Fini(); + PyDict_Fini(); + + /* Cleanup Unicode implementation */ + _PyUnicode_Fini(); + + /* reset file system default encoding */ + if (!Py_HasFileSystemDefaultEncoding) { + free((char*)Py_FileSystemDefaultEncoding); + Py_FileSystemDefaultEncoding = NULL; + } + + /* 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); + /* 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(); + if (Py_GETENV("PYTHONMALLOCSTATS")) + _PyObject_DebugMallocStats(); #endif - call_ll_exitfuncs(); + call_ll_exitfuncs(); } /* Create and initialize a new interpreter and thread, and return the @@ -541,81 +541,81 @@ Py_Finalize(void) 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("builtins", "builtins"); - if (bimod != NULL) { - interp->builtins = PyModule_GetDict(bimod); - if (interp->builtins == NULL) - goto handle_error; - Py_INCREF(interp->builtins); - } - - /* initialize builtin exceptions */ - _PyExc_Init(); - - sysmod = _PyImport_FindExtension("sys", "sys"); - if (bimod != NULL && sysmod != NULL) { - PyObject *pstderr; - 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); - /* Set up a preliminary stderr printer until we have enough - infrastructure for the io module in place. */ - pstderr = PyFile_NewStdPrinter(fileno(stderr)); - if (pstderr == NULL) - Py_FatalError("Py_Initialize: can't set preliminary stderr"); - PySys_SetObject("stderr", pstderr); - PySys_SetObject("__stderr__", pstderr); - - _PyImportHooks_Init(); - if (initstdio() < 0) - Py_FatalError( - "Py_Initialize: can't initialize sys standard streams"); - initmain(); - if (!Py_NoSiteFlag) - initsite(); - } - - if (!PyErr_Occurred()) - return tstate; + 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("builtins", "builtins"); + if (bimod != NULL) { + interp->builtins = PyModule_GetDict(bimod); + if (interp->builtins == NULL) + goto handle_error; + Py_INCREF(interp->builtins); + } + + /* initialize builtin exceptions */ + _PyExc_Init(); + + sysmod = _PyImport_FindExtension("sys", "sys"); + if (bimod != NULL && sysmod != NULL) { + PyObject *pstderr; + 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); + /* Set up a preliminary stderr printer until we have enough + infrastructure for the io module in place. */ + pstderr = PyFile_NewStdPrinter(fileno(stderr)); + if (pstderr == NULL) + Py_FatalError("Py_Initialize: can't set preliminary stderr"); + PySys_SetObject("stderr", pstderr); + PySys_SetObject("__stderr__", pstderr); + + _PyImportHooks_Init(); + if (initstdio() < 0) + Py_FatalError( + "Py_Initialize: can't initialize sys standard streams"); + initmain(); + if (!Py_NoSiteFlag) + initsite(); + } + + if (!PyErr_Occurred()) + return tstate; handle_error: - /* Oops, it didn't work. Undo it all. */ + /* Oops, it didn't work. Undo it all. */ - PyErr_Print(); - PyThreadState_Clear(tstate); - PyThreadState_Swap(save_tstate); - PyThreadState_Delete(tstate); - PyInterpreterState_Delete(interp); + PyErr_Print(); + PyThreadState_Clear(tstate); + PyThreadState_Swap(save_tstate); + PyThreadState_Delete(tstate); + PyInterpreterState_Delete(interp); - return NULL; + return NULL; } /* Delete an interpreter and its last thread. This requires that the @@ -633,19 +633,19 @@ handle_error: void Py_EndInterpreter(PyThreadState *tstate) { - PyInterpreterState *interp = tstate->interp; + 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"); + 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); + PyImport_Cleanup(); + PyInterpreterState_Clear(interp); + PyThreadState_Swap(NULL); + PyInterpreterState_Delete(interp); } static wchar_t *progname = L"python"; @@ -653,14 +653,14 @@ static wchar_t *progname = L"python"; void Py_SetProgramName(wchar_t *pn) { - if (pn && *pn) - progname = pn; + if (pn && *pn) + progname = pn; } wchar_t * Py_GetProgramName(void) { - return progname; + return progname; } static wchar_t *default_home = NULL; @@ -669,23 +669,23 @@ static wchar_t env_home[PATH_MAX+1]; void Py_SetPythonHome(wchar_t *home) { - default_home = home; + default_home = home; } wchar_t * Py_GetPythonHome(void) { - wchar_t *home = default_home; - if (home == NULL && !Py_IgnoreEnvironmentFlag) { - char* chome = Py_GETENV("PYTHONHOME"); - if (chome) { - size_t r = mbstowcs(env_home, chome, PATH_MAX+1); - if (r != (size_t)-1 && r <= PATH_MAX) - home = env_home; - } + wchar_t *home = default_home; + if (home == NULL && !Py_IgnoreEnvironmentFlag) { + char* chome = Py_GETENV("PYTHONHOME"); + if (chome) { + size_t r = mbstowcs(env_home, chome, PATH_MAX+1); + if (r != (size_t)-1 && r <= PATH_MAX) + home = env_home; + } - } - return home; + } + return home; } /* Create __main__ module */ @@ -693,18 +693,18 @@ Py_GetPythonHome(void) 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("builtins"); - if (bimod == NULL || - PyDict_SetItemString(d, "__builtins__", bimod) != 0) - Py_FatalError("can't add __builtins__ to __main__"); - Py_DECREF(bimod); - } + 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("builtins"); + 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) */ @@ -712,386 +712,386 @@ initmain(void) static void initsite(void) { - PyObject *m; - m = PyImport_ImportModule("site"); - if (m == NULL) { - PyErr_Print(); - Py_Finalize(); - exit(1); - } - else { - Py_DECREF(m); - } + PyObject *m; + m = PyImport_ImportModule("site"); + if (m == NULL) { + PyErr_Print(); + Py_Finalize(); + exit(1); + } + else { + Py_DECREF(m); + } } static PyObject* create_stdio(PyObject* io, - int fd, int write_mode, char* name, - char* encoding, char* errors) -{ - PyObject *buf = NULL, *stream = NULL, *text = NULL, *raw = NULL, *res; - const char* mode; - PyObject *line_buffering; - int buffering, isatty; - - /* stdin is always opened in buffered mode, first because it shouldn't - make a difference in common use cases, second because TextIOWrapper - depends on the presence of a read1() method which only exists on - buffered streams. - */ - if (Py_UnbufferedStdioFlag && write_mode) - buffering = 0; - else - buffering = -1; - if (write_mode) - mode = "wb"; - else - mode = "rb"; - buf = PyObject_CallMethod(io, "open", "isiOOOi", - fd, mode, buffering, - Py_None, Py_None, Py_None, 0); - if (buf == NULL) - goto error; - - if (buffering) { - raw = PyObject_GetAttrString(buf, "raw"); - if (raw == NULL) - goto error; - } - else { - raw = buf; - Py_INCREF(raw); - } - - text = PyUnicode_FromString(name); - if (text == NULL || PyObject_SetAttrString(raw, "name", text) < 0) - goto error; - res = PyObject_CallMethod(raw, "isatty", ""); - if (res == NULL) - goto error; - isatty = PyObject_IsTrue(res); - Py_DECREF(res); - if (isatty == -1) - goto error; - if (isatty || Py_UnbufferedStdioFlag) - line_buffering = Py_True; - else - line_buffering = Py_False; - - Py_CLEAR(raw); - Py_CLEAR(text); - - stream = PyObject_CallMethod(io, "TextIOWrapper", "OsssO", - buf, encoding, errors, - "\n", line_buffering); - Py_CLEAR(buf); - if (stream == NULL) - goto error; - - if (write_mode) - mode = "w"; - else - mode = "r"; - text = PyUnicode_FromString(mode); - if (!text || PyObject_SetAttrString(stream, "mode", text) < 0) - goto error; - Py_CLEAR(text); - return stream; + int fd, int write_mode, char* name, + char* encoding, char* errors) +{ + PyObject *buf = NULL, *stream = NULL, *text = NULL, *raw = NULL, *res; + const char* mode; + PyObject *line_buffering; + int buffering, isatty; + + /* stdin is always opened in buffered mode, first because it shouldn't + make a difference in common use cases, second because TextIOWrapper + depends on the presence of a read1() method which only exists on + buffered streams. + */ + if (Py_UnbufferedStdioFlag && write_mode) + buffering = 0; + else + buffering = -1; + if (write_mode) + mode = "wb"; + else + mode = "rb"; + buf = PyObject_CallMethod(io, "open", "isiOOOi", + fd, mode, buffering, + Py_None, Py_None, Py_None, 0); + if (buf == NULL) + goto error; + + if (buffering) { + raw = PyObject_GetAttrString(buf, "raw"); + if (raw == NULL) + goto error; + } + else { + raw = buf; + Py_INCREF(raw); + } + + text = PyUnicode_FromString(name); + if (text == NULL || PyObject_SetAttrString(raw, "name", text) < 0) + goto error; + res = PyObject_CallMethod(raw, "isatty", ""); + if (res == NULL) + goto error; + isatty = PyObject_IsTrue(res); + Py_DECREF(res); + if (isatty == -1) + goto error; + if (isatty || Py_UnbufferedStdioFlag) + line_buffering = Py_True; + else + line_buffering = Py_False; + + Py_CLEAR(raw); + Py_CLEAR(text); + + stream = PyObject_CallMethod(io, "TextIOWrapper", "OsssO", + buf, encoding, errors, + "\n", line_buffering); + Py_CLEAR(buf); + if (stream == NULL) + goto error; + + if (write_mode) + mode = "w"; + else + mode = "r"; + text = PyUnicode_FromString(mode); + if (!text || PyObject_SetAttrString(stream, "mode", text) < 0) + goto error; + Py_CLEAR(text); + return stream; error: - Py_XDECREF(buf); - Py_XDECREF(stream); - Py_XDECREF(text); - Py_XDECREF(raw); - return NULL; + Py_XDECREF(buf); + Py_XDECREF(stream); + Py_XDECREF(text); + Py_XDECREF(raw); + return NULL; } /* Initialize sys.stdin, stdout, stderr and builtins.open */ static int initstdio(void) { - PyObject *iomod = NULL, *wrapper; - PyObject *bimod = NULL; - PyObject *m; - PyObject *std = NULL; - int status = 0, fd; - PyObject * encoding_attr; - char *encoding = NULL, *errors; - - /* Hack to avoid a nasty recursion issue when Python is invoked - in verbose mode: pre-import the Latin-1 and UTF-8 codecs */ - if ((m = PyImport_ImportModule("encodings.utf_8")) == NULL) { - goto error; - } - Py_DECREF(m); - - if (!(m = PyImport_ImportModule("encodings.latin_1"))) { - goto error; - } - Py_DECREF(m); - - if (!(bimod = PyImport_ImportModule("builtins"))) { - goto error; - } - - if (!(iomod = PyImport_ImportModule("io"))) { - goto error; - } - if (!(wrapper = PyObject_GetAttrString(iomod, "OpenWrapper"))) { - goto error; - } - - /* Set builtins.open */ - if (PyObject_SetAttrString(bimod, "open", wrapper) == -1) { - goto error; - } - - encoding = Py_GETENV("PYTHONIOENCODING"); - errors = NULL; - if (encoding) { - encoding = strdup(encoding); - errors = strchr(encoding, ':'); - if (errors) { - *errors = '\0'; - errors++; - } - } - - /* Set sys.stdin */ - fd = fileno(stdin); - /* Under some conditions stdin, stdout and stderr may not be connected - * and fileno() may point to an invalid file descriptor. For example - * GUI apps don't have valid standard streams by default. - */ - if (fd < 0) { + PyObject *iomod = NULL, *wrapper; + PyObject *bimod = NULL; + PyObject *m; + PyObject *std = NULL; + int status = 0, fd; + PyObject * encoding_attr; + char *encoding = NULL, *errors; + + /* Hack to avoid a nasty recursion issue when Python is invoked + in verbose mode: pre-import the Latin-1 and UTF-8 codecs */ + if ((m = PyImport_ImportModule("encodings.utf_8")) == NULL) { + goto error; + } + Py_DECREF(m); + + if (!(m = PyImport_ImportModule("encodings.latin_1"))) { + goto error; + } + Py_DECREF(m); + + if (!(bimod = PyImport_ImportModule("builtins"))) { + goto error; + } + + if (!(iomod = PyImport_ImportModule("io"))) { + goto error; + } + if (!(wrapper = PyObject_GetAttrString(iomod, "OpenWrapper"))) { + goto error; + } + + /* Set builtins.open */ + if (PyObject_SetAttrString(bimod, "open", wrapper) == -1) { + goto error; + } + + encoding = Py_GETENV("PYTHONIOENCODING"); + errors = NULL; + if (encoding) { + encoding = strdup(encoding); + errors = strchr(encoding, ':'); + if (errors) { + *errors = '\0'; + errors++; + } + } + + /* Set sys.stdin */ + fd = fileno(stdin); + /* Under some conditions stdin, stdout and stderr may not be connected + * and fileno() may point to an invalid file descriptor. For example + * GUI apps don't have valid standard streams by default. + */ + if (fd < 0) { #ifdef MS_WINDOWS - std = Py_None; - Py_INCREF(std); + std = Py_None; + Py_INCREF(std); #else - goto error; + goto error; #endif - } - else { - std = create_stdio(iomod, fd, 0, "", encoding, errors); - if (std == NULL) - goto error; - } /* if (fd < 0) */ - PySys_SetObject("__stdin__", std); - PySys_SetObject("stdin", std); - Py_DECREF(std); - - /* Set sys.stdout */ - fd = fileno(stdout); - if (fd < 0) { + } + else { + std = create_stdio(iomod, fd, 0, "", encoding, errors); + if (std == NULL) + goto error; + } /* if (fd < 0) */ + PySys_SetObject("__stdin__", std); + PySys_SetObject("stdin", std); + Py_DECREF(std); + + /* Set sys.stdout */ + fd = fileno(stdout); + if (fd < 0) { #ifdef MS_WINDOWS - std = Py_None; - Py_INCREF(std); + std = Py_None; + Py_INCREF(std); #else - goto error; + goto error; #endif - } - else { - std = create_stdio(iomod, fd, 1, "", encoding, errors); - if (std == NULL) - goto error; - } /* if (fd < 0) */ - PySys_SetObject("__stdout__", std); - PySys_SetObject("stdout", std); - Py_DECREF(std); + } + else { + std = create_stdio(iomod, fd, 1, "", encoding, errors); + if (std == NULL) + goto error; + } /* if (fd < 0) */ + PySys_SetObject("__stdout__", std); + PySys_SetObject("stdout", std); + Py_DECREF(std); #if 1 /* Disable this if you have trouble debugging bootstrap stuff */ - /* Set sys.stderr, replaces the preliminary stderr */ - fd = fileno(stderr); - if (fd < 0) { + /* Set sys.stderr, replaces the preliminary stderr */ + fd = fileno(stderr); + if (fd < 0) { #ifdef MS_WINDOWS - std = Py_None; - Py_INCREF(std); + std = Py_None; + Py_INCREF(std); #else - goto error; + goto error; #endif - } - else { - std = create_stdio(iomod, fd, 1, "", encoding, "backslashreplace"); - if (std == NULL) - goto error; - } /* if (fd < 0) */ - - /* Same as hack above, pre-import stderr's codec to avoid recursion - when import.c tries to write to stderr in verbose mode. */ - encoding_attr = PyObject_GetAttrString(std, "encoding"); - if (encoding_attr != NULL) { - const char * encoding; - encoding = _PyUnicode_AsString(encoding_attr); - if (encoding != NULL) { - _PyCodec_Lookup(encoding); - } - } - PyErr_Clear(); /* Not a fatal error if codec isn't available */ - - PySys_SetObject("__stderr__", std); - PySys_SetObject("stderr", std); - Py_DECREF(std); + } + else { + std = create_stdio(iomod, fd, 1, "", encoding, "backslashreplace"); + if (std == NULL) + goto error; + } /* if (fd < 0) */ + + /* Same as hack above, pre-import stderr's codec to avoid recursion + when import.c tries to write to stderr in verbose mode. */ + encoding_attr = PyObject_GetAttrString(std, "encoding"); + if (encoding_attr != NULL) { + const char * encoding; + encoding = _PyUnicode_AsString(encoding_attr); + if (encoding != NULL) { + _PyCodec_Lookup(encoding); + } + } + PyErr_Clear(); /* Not a fatal error if codec isn't available */ + + PySys_SetObject("__stderr__", std); + PySys_SetObject("stderr", std); + Py_DECREF(std); #endif - if (0) { + if (0) { error: - status = -1; - } + status = -1; + } - if (encoding) - free(encoding); - Py_XDECREF(bimod); - Py_XDECREF(iomod); - return status; + if (encoding) + free(encoding); + Py_XDECREF(bimod); + Py_XDECREF(iomod); + return status; } /* Parse input from a file and execute it */ int PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit, - PyCompilerFlags *flags) + 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); + 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 = PyUnicode_FromString(">>> ")); - Py_XDECREF(v); - } - v = PySys_GetObject("ps2"); - if (v == NULL) { - PySys_SetObject("ps2", v = PyUnicode_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; - */ - } + 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 = PyUnicode_FromString(">>> ")); + Py_XDECREF(v); + } + v = PySys_GetObject("ps2"); + if (v == NULL) { + PySys_SetObject("ps2", v = PyUnicode_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 */ static int PARSER_FLAGS(PyCompilerFlags *flags) { - int parser_flags = 0; - if (!flags) - return 0; - if (flags->cf_flags & PyCF_DONT_IMPLY_DEDENT) - parser_flags |= PyPARSE_DONT_IMPLY_DEDENT; - if (flags->cf_flags & PyCF_IGNORE_COOKIE) - parser_flags |= PyPARSE_IGNORE_COOKIE; - if (flags->cf_flags & CO_FUTURE_BARRY_AS_BDFL) - parser_flags |= PyPARSE_BARRY_AS_BDFL; - return parser_flags; + int parser_flags = 0; + if (!flags) + return 0; + if (flags->cf_flags & PyCF_DONT_IMPLY_DEDENT) + parser_flags |= PyPARSE_DONT_IMPLY_DEDENT; + if (flags->cf_flags & PyCF_IGNORE_COOKIE) + parser_flags |= PyPARSE_IGNORE_COOKIE; + if (flags->cf_flags & CO_FUTURE_BARRY_AS_BDFL) + parser_flags |= PyPARSE_BARRY_AS_BDFL; + return parser_flags; } #if 0 /* Keep an example of flags with future keyword support. */ #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) + ((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) #endif int PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags) { - PyObject *m, *d, *v, *w, *oenc = NULL; - mod_ty mod; - PyArena *arena; - char *ps1 = "", *ps2 = "", *enc = NULL; - int errcode = 0; - - if (fp == stdin) { - /* Fetch encoding from sys.stdin */ - v = PySys_GetObject("stdin"); - if (v == NULL || v == Py_None) - return -1; - oenc = PyObject_GetAttrString(v, "encoding"); - if (!oenc) - return -1; - enc = _PyUnicode_AsString(oenc); - } - v = PySys_GetObject("ps1"); - if (v != NULL) { - v = PyObject_Str(v); - if (v == NULL) - PyErr_Clear(); - else if (PyUnicode_Check(v)) - ps1 = _PyUnicode_AsString(v); - } - w = PySys_GetObject("ps2"); - if (w != NULL) { - w = PyObject_Str(w); - if (w == NULL) - PyErr_Clear(); - else if (PyUnicode_Check(w)) - ps2 = _PyUnicode_AsString(w); - } - arena = PyArena_New(); - if (arena == NULL) { - Py_XDECREF(v); - Py_XDECREF(w); - Py_XDECREF(oenc); - return -1; - } - mod = PyParser_ASTFromFile(fp, filename, enc, - Py_single_input, ps1, ps2, - flags, &errcode, arena); - Py_XDECREF(v); - Py_XDECREF(w); - Py_XDECREF(oenc); - 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); - flush_io(); - if (v == NULL) { - PyErr_Print(); - return -1; - } - Py_DECREF(v); - return 0; + PyObject *m, *d, *v, *w, *oenc = NULL; + mod_ty mod; + PyArena *arena; + char *ps1 = "", *ps2 = "", *enc = NULL; + int errcode = 0; + + if (fp == stdin) { + /* Fetch encoding from sys.stdin */ + v = PySys_GetObject("stdin"); + if (v == NULL || v == Py_None) + return -1; + oenc = PyObject_GetAttrString(v, "encoding"); + if (!oenc) + return -1; + enc = _PyUnicode_AsString(oenc); + } + v = PySys_GetObject("ps1"); + if (v != NULL) { + v = PyObject_Str(v); + if (v == NULL) + PyErr_Clear(); + else if (PyUnicode_Check(v)) + ps1 = _PyUnicode_AsString(v); + } + w = PySys_GetObject("ps2"); + if (w != NULL) { + w = PyObject_Str(w); + if (w == NULL) + PyErr_Clear(); + else if (PyUnicode_Check(w)) + ps2 = _PyUnicode_AsString(w); + } + arena = PyArena_New(); + if (arena == NULL) { + Py_XDECREF(v); + Py_XDECREF(w); + Py_XDECREF(oenc); + return -1; + } + mod = PyParser_ASTFromFile(fp, filename, enc, + Py_single_input, ps1, ps2, + flags, &errcode, arena); + Py_XDECREF(v); + Py_XDECREF(w); + Py_XDECREF(oenc); + 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); + flush_io(); + if (v == NULL) { + PyErr_Print(); + return -1; + } + Py_DECREF(v); + return 0; } /* Check whether a file maybe a pyc file: Look at the extension, @@ -1100,739 +1100,739 @@ PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags 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; + 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; - int set_file_name = 0, ret, len; - - m = PyImport_AddModule("__main__"); - if (m == NULL) - return -1; - d = PyModule_GetDict(m); - if (PyDict_GetItemString(d, "__file__") == NULL) { - PyObject *f; - f = PyUnicode_DecodeFSDefault(filename); - if (f == NULL) - return -1; - if (PyDict_SetItemString(d, "__file__", f) < 0) { - Py_DECREF(f); - return -1; - } - if (PyDict_SetItemString(d, "__cached__", Py_None) < 0) - return -1; - set_file_name = 1; - Py_DECREF(f); - } - len = strlen(filename); - ext = filename + len - (len > 4 ? 4 : 0); - 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"); - ret = -1; - goto done; - } - /* 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); - } - flush_io(); - if (v == NULL) { - PyErr_Print(); - ret = -1; - goto done; - } - Py_DECREF(v); - ret = 0; + PyCompilerFlags *flags) +{ + PyObject *m, *d, *v; + const char *ext; + int set_file_name = 0, ret, len; + + m = PyImport_AddModule("__main__"); + if (m == NULL) + return -1; + d = PyModule_GetDict(m); + if (PyDict_GetItemString(d, "__file__") == NULL) { + PyObject *f; + f = PyUnicode_DecodeFSDefault(filename); + if (f == NULL) + return -1; + if (PyDict_SetItemString(d, "__file__", f) < 0) { + Py_DECREF(f); + return -1; + } + if (PyDict_SetItemString(d, "__cached__", Py_None) < 0) + return -1; + set_file_name = 1; + Py_DECREF(f); + } + len = strlen(filename); + ext = filename + len - (len > 4 ? 4 : 0); + 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"); + ret = -1; + goto done; + } + /* 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); + } + flush_io(); + if (v == NULL) { + PyErr_Print(); + ret = -1; + goto done; + } + Py_DECREF(v); + ret = 0; done: - if (set_file_name && PyDict_DelItemString(d, "__file__")) - PyErr_Clear(); - return ret; + if (set_file_name && PyDict_DelItemString(d, "__file__")) + PyErr_Clear(); + return ret; } 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); - return 0; + 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); + 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 = _PyUnicode_AsString(v))) - goto finally; - - Py_DECREF(v); - if (!(v = PyObject_GetAttrString(err, "lineno"))) - goto finally; - hold = PyLong_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 = PyLong_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 (!PyUnicode_Check(v) || - !(*text = _PyUnicode_AsString(v))) - goto finally; - Py_DECREF(v); - return 1; + 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 = _PyUnicode_AsString(v))) + goto finally; + + Py_DECREF(v); + if (!(v = PyObject_GetAttrString(err, "lineno"))) + goto finally; + hold = PyLong_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 = PyLong_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 (!PyUnicode_Check(v) || + !(*text = _PyUnicode_AsString(v))) + goto finally; + Py_DECREF(v); + return 1; finally: - Py_XDECREF(v); - return 0; + Py_XDECREF(v); + return 0; } void PyErr_Print(void) { - PyErr_PrintEx(1); + 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); + 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; - - if (Py_InspectFlag) - /* Don't exit if -i flag was given. This flag is set to 0 - * when entering interactive mode for inspecting. */ - return; - - PyErr_Fetch(&exception, &value, &tb); - 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 (PyLong_Check(value)) - exitcode = (int)PyLong_AsLong(value); - else { - PyObject_Print(value, stderr, Py_PRINT_RAW); - PySys_WriteStderr("\n"); - exitcode = 1; - } + PyObject *exception, *value, *tb; + int exitcode = 0; + + if (Py_InspectFlag) + /* Don't exit if -i flag was given. This flag is set to 0 + * when entering interactive mode for inspecting. */ + return; + + PyErr_Fetch(&exception, &value, &tb); + 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 (PyLong_Check(value)) + exitcode = (int)PyLong_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 */ + /* 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 (tb == NULL) { - tb = Py_None; - Py_INCREF(tb); - } - PyException_SetTraceback(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); - 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); - } - 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); + 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 (tb == NULL) { + tb = Py_None; + Py_INCREF(tb); + } + PyException_SetTraceback(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); + 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); + } + 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); } static void print_exception(PyObject *f, PyObject *value) { - int err = 0; - PyObject *type, *tb; - - if (!PyExceptionInstance_Check(value)) { - PyFile_WriteString("TypeError: print_exception(): Exception expected for value, ", f); - PyFile_WriteString(Py_TYPE(value)->tp_name, f); - PyFile_WriteString(" found\n", f); - return; - } - - Py_INCREF(value); - fflush(stdout); - type = (PyObject *) Py_TYPE(value); - tb = PyException_GetTraceback(value); - 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("", 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 { - PyObject* moduleName; - char* className; - assert(PyExceptionClass_Check(type)); - className = PyExceptionClass_Name(type); - if (className != NULL) { - char *dot = strrchr(className, '.'); - if (dot != NULL) - className = dot+1; - } - - moduleName = PyObject_GetAttrString(type, "__module__"); - if (moduleName == NULL || !PyUnicode_Check(moduleName)) - { - Py_DECREF(moduleName); - err = PyFile_WriteString("", f); - } - else { - char* modstr = _PyUnicode_AsString(moduleName); - if (modstr && strcmp(modstr, "builtins")) - { - err = PyFile_WriteString(modstr, f); - err += PyFile_WriteString(".", f); - } - Py_DECREF(moduleName); - } - if (err == 0) { - if (className == NULL) - err = PyFile_WriteString("", f); - else - err = PyFile_WriteString(className, f); - } - } - 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 (!PyUnicode_Check(s) || - PyUnicode_GetSize(s) != 0) - err = PyFile_WriteString(": ", f); - if (err == 0) - err = PyFile_WriteObject(s, f, Py_PRINT_RAW); - Py_XDECREF(s); - } - /* try to write a newline in any case */ - err += PyFile_WriteString("\n", f); - Py_XDECREF(tb); - 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(); + int err = 0; + PyObject *type, *tb; + + if (!PyExceptionInstance_Check(value)) { + PyFile_WriteString("TypeError: print_exception(): Exception expected for value, ", f); + PyFile_WriteString(Py_TYPE(value)->tp_name, f); + PyFile_WriteString(" found\n", f); + return; + } + + Py_INCREF(value); + fflush(stdout); + type = (PyObject *) Py_TYPE(value); + tb = PyException_GetTraceback(value); + 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("", 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 { + PyObject* moduleName; + char* className; + assert(PyExceptionClass_Check(type)); + className = PyExceptionClass_Name(type); + if (className != NULL) { + char *dot = strrchr(className, '.'); + if (dot != NULL) + className = dot+1; + } + + moduleName = PyObject_GetAttrString(type, "__module__"); + if (moduleName == NULL || !PyUnicode_Check(moduleName)) + { + Py_DECREF(moduleName); + err = PyFile_WriteString("", f); + } + else { + char* modstr = _PyUnicode_AsString(moduleName); + if (modstr && strcmp(modstr, "builtins")) + { + err = PyFile_WriteString(modstr, f); + err += PyFile_WriteString(".", f); + } + Py_DECREF(moduleName); + } + if (err == 0) { + if (className == NULL) + err = PyFile_WriteString("", f); + else + err = PyFile_WriteString(className, f); + } + } + 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 (!PyUnicode_Check(s) || + PyUnicode_GetSize(s) != 0) + err = PyFile_WriteString(": ", f); + if (err == 0) + err = PyFile_WriteObject(s, f, Py_PRINT_RAW); + Py_XDECREF(s); + } + /* try to write a newline in any case */ + err += PyFile_WriteString("\n", f); + Py_XDECREF(tb); + 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(); } static const char *cause_message = - "\nThe above exception was the direct cause " - "of the following exception:\n\n"; + "\nThe above exception was the direct cause " + "of the following exception:\n\n"; static const char *context_message = - "\nDuring handling of the above exception, " - "another exception occurred:\n\n"; + "\nDuring handling of the above exception, " + "another exception occurred:\n\n"; static void print_exception_recursive(PyObject *f, PyObject *value, PyObject *seen) { - int err = 0, res; - PyObject *cause, *context; - - if (seen != NULL) { - /* Exception chaining */ - if (PySet_Add(seen, value) == -1) - PyErr_Clear(); - else if (PyExceptionInstance_Check(value)) { - cause = PyException_GetCause(value); - context = PyException_GetContext(value); - if (cause) { - res = PySet_Contains(seen, cause); - if (res == -1) - PyErr_Clear(); - if (res == 0) { - print_exception_recursive( - f, cause, seen); - err |= PyFile_WriteString( - cause_message, f); - } - } - else if (context) { - res = PySet_Contains(seen, context); - if (res == -1) - PyErr_Clear(); - if (res == 0) { - print_exception_recursive( - f, context, seen); - err |= PyFile_WriteString( - context_message, f); - } - } - Py_XDECREF(context); - Py_XDECREF(cause); - } - } - print_exception(f, value); - if (err != 0) - PyErr_Clear(); + int err = 0, res; + PyObject *cause, *context; + + if (seen != NULL) { + /* Exception chaining */ + if (PySet_Add(seen, value) == -1) + PyErr_Clear(); + else if (PyExceptionInstance_Check(value)) { + cause = PyException_GetCause(value); + context = PyException_GetContext(value); + if (cause) { + res = PySet_Contains(seen, cause); + if (res == -1) + PyErr_Clear(); + if (res == 0) { + print_exception_recursive( + f, cause, seen); + err |= PyFile_WriteString( + cause_message, f); + } + } + else if (context) { + res = PySet_Contains(seen, context); + if (res == -1) + PyErr_Clear(); + if (res == 0) { + print_exception_recursive( + f, context, seen); + err |= PyFile_WriteString( + context_message, f); + } + } + Py_XDECREF(context); + Py_XDECREF(cause); + } + } + print_exception(f, value); + if (err != 0) + PyErr_Clear(); } void PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb) { - PyObject *seen; - PyObject *f = PySys_GetObject("stderr"); - if (f == Py_None) { - /* pass */ - } - else if (f == NULL) { - _PyObject_Dump(value); - fprintf(stderr, "lost sys.stderr\n"); - } - else { - /* We choose to ignore seen being possibly NULL, and report - at least the main exception (it could be a MemoryError). - */ - seen = PySet_New(NULL); - if (seen == NULL) - PyErr_Clear(); - print_exception_recursive(f, value, seen); - Py_XDECREF(seen); - } + PyObject *seen; + PyObject *f = PySys_GetObject("stderr"); + if (f == Py_None) { + /* pass */ + } + else if (f == NULL) { + _PyObject_Dump(value); + fprintf(stderr, "lost sys.stderr\n"); + } + else { + /* We choose to ignore seen being possibly NULL, and report + at least the main exception (it could be a MemoryError). + */ + seen = PySet_New(NULL); + if (seen == NULL) + PyErr_Clear(); + print_exception_recursive(f, value, seen); + Py_XDECREF(seen); + } } PyObject * PyRun_StringFlags(const char *str, int start, PyObject *globals, - PyObject *locals, PyCompilerFlags *flags) + PyObject *locals, PyCompilerFlags *flags) { - PyObject *ret = NULL; - mod_ty mod; - PyArena *arena = PyArena_New(); - if (arena == NULL) - return NULL; + PyObject *ret = NULL; + mod_ty mod; + PyArena *arena = PyArena_New(); + if (arena == NULL) + return NULL; - mod = PyParser_ASTFromString(str, "", start, flags, arena); - if (mod != NULL) - ret = run_mod(mod, "", globals, locals, flags, arena); - PyArena_Free(arena); - return ret; + mod = PyParser_ASTFromString(str, "", start, flags, arena); + if (mod != NULL) + ret = run_mod(mod, "", 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, NULL, 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; + 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, NULL, 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 void flush_io(void) { - PyObject *f, *r; - PyObject *type, *value, *traceback; + PyObject *f, *r; + PyObject *type, *value, *traceback; - /* Save the current exception */ - PyErr_Fetch(&type, &value, &traceback); + /* Save the current exception */ + PyErr_Fetch(&type, &value, &traceback); - f = PySys_GetObject("stderr"); - if (f != NULL) { - r = PyObject_CallMethod(f, "flush", ""); - if (r) - Py_DECREF(r); - else - PyErr_Clear(); - } - f = PySys_GetObject("stdout"); - if (f != NULL) { - r = PyObject_CallMethod(f, "flush", ""); - if (r) - Py_DECREF(r); - else - PyErr_Clear(); - } + f = PySys_GetObject("stderr"); + if (f != NULL) { + r = PyObject_CallMethod(f, "flush", ""); + if (r) + Py_DECREF(r); + else + PyErr_Clear(); + } + f = PySys_GetObject("stdout"); + if (f != NULL) { + r = PyObject_CallMethod(f, "flush", ""); + if (r) + Py_DECREF(r); + else + PyErr_Clear(); + } - PyErr_Restore(type, value, traceback); + PyErr_Restore(type, value, traceback); } static PyObject * run_mod(mod_ty mod, const char *filename, PyObject *globals, PyObject *locals, - PyCompilerFlags *flags, PyArena *arena) + 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; + 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 *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; + 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; - PyCompilerFlags flags; - PyArena *arena = PyArena_New(); - if (arena == NULL) - return NULL; + struct symtable *st; + mod_ty mod; + PyCompilerFlags flags; + PyArena *arena = PyArena_New(); + if (arena == NULL) + return NULL; - flags.cf_flags = 0; - mod = PyParser_ASTFromString(str, filename, start, &flags, arena); - if (mod == NULL) { - PyArena_Free(arena); - return NULL; - } - st = PySymtable_Build(mod, filename, 0); - PyArena_Free(arena); - return st; + flags.cf_flags = 0; + mod = PyParser_ASTFromString(str, filename, start, &flags, 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; - PyCompilerFlags localflags; - perrdetail err; - int iflags = PARSER_FLAGS(flags); - - node *n = PyParser_ParseStringFlagsFilenameEx(s, filename, - &_PyParser_Grammar, start, &err, - &iflags); - if (flags == NULL) { - localflags.cf_flags = 0; - flags = &localflags; - } - if (n) { - flags->cf_flags |= iflags & PyCF_MASK; - mod = PyAST_FromNode(n, flags, filename, arena); - PyNode_Free(n); - return mod; - } - else { - err_input(&err); - return NULL; - } + PyCompilerFlags *flags, PyArena *arena) +{ + mod_ty mod; + PyCompilerFlags localflags; + perrdetail err; + int iflags = PARSER_FLAGS(flags); + + node *n = PyParser_ParseStringFlagsFilenameEx(s, filename, + &_PyParser_Grammar, start, &err, + &iflags); + if (flags == NULL) { + localflags.cf_flags = 0; + flags = &localflags; + } + if (n) { + flags->cf_flags |= iflags & PyCF_MASK; + 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, const char* enc, - int start, char *ps1, - char *ps2, PyCompilerFlags *flags, int *errcode, - PyArena *arena) -{ - mod_ty mod; - PyCompilerFlags localflags; - perrdetail err; - int iflags = PARSER_FLAGS(flags); - - node *n = PyParser_ParseFileFlagsEx(fp, filename, enc, - &_PyParser_Grammar, - start, ps1, ps2, &err, &iflags); - if (flags == NULL) { - localflags.cf_flags = 0; - flags = &localflags; - } - if (n) { - flags->cf_flags |= iflags & PyCF_MASK; - mod = PyAST_FromNode(n, flags, filename, arena); - PyNode_Free(n); - return mod; - } - else { - err_input(&err); - if (errcode) - *errcode = err.error; - return NULL; - } + int start, char *ps1, + char *ps2, PyCompilerFlags *flags, int *errcode, + PyArena *arena) +{ + mod_ty mod; + PyCompilerFlags localflags; + perrdetail err; + int iflags = PARSER_FLAGS(flags); + + node *n = PyParser_ParseFileFlagsEx(fp, filename, enc, + &_PyParser_Grammar, + start, ps1, ps2, &err, &iflags); + if (flags == NULL) { + localflags.cf_flags = 0; + flags = &localflags; + } + if (n) { + flags->cf_flags |= iflags & PyCF_MASK; + 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 */ @@ -1840,14 +1840,14 @@ PyParser_ASTFromFile(FILE *fp, const char *filename, const char* enc, node * PyParser_SimpleParseFileFlags(FILE *fp, const char *filename, int start, int flags) { - perrdetail err; - node *n = PyParser_ParseFileFlags(fp, filename, NULL, - &_PyParser_Grammar, - start, NULL, NULL, &err, flags); - if (n == NULL) - err_input(&err); + perrdetail err; + node *n = PyParser_ParseFileFlags(fp, filename, NULL, + &_PyParser_Grammar, + start, NULL, NULL, &err, flags); + if (n == NULL) + err_input(&err); - return n; + return n; } /* Simplified interface to parsestring -- return node or set exception */ @@ -1855,30 +1855,30 @@ PyParser_SimpleParseFileFlags(FILE *fp, const char *filename, int start, int fla 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; + 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) + 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; + 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); + return PyParser_SimpleParseStringFlagsFilename(str, filename, start, 0); } /* May want to move a more generalized form of this to parsetok.c or @@ -1887,7 +1887,7 @@ PyParser_SimpleParseStringFilename(const char *str, const char *filename, int st void PyParser_SetError(perrdetail *err) { - err_input(err); + err_input(err); } /* Set the error appropriate to the given input error code (see errcode.h) */ @@ -1895,110 +1895,110 @@ PyParser_SetError(perrdetail *err) static void err_input(perrdetail *err) { - PyObject *v, *w, *errtype, *errtext; - PyObject *msg_obj = NULL; - char *msg = NULL; - errtype = PyExc_SyntaxError; - switch (err->error) { - case E_ERROR: - return; - 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 literal"; - break; - case E_EOLS: - msg = "EOL while scanning string literal"; - break; - case E_INTR: - if (!PyErr_Occurred()) - PyErr_SetNone(PyExc_KeyboardInterrupt); - goto cleanup; - case E_NOMEM: - PyErr_NoMemory(); - goto cleanup; - 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); - msg = "unknown decode error"; - if (value != NULL) - msg_obj = PyObject_Str(value); - Py_XDECREF(type); - Py_XDECREF(value); - Py_XDECREF(tb); - break; - } - case E_LINECONT: - msg = "unexpected character after line continuation character"; - break; - - case E_IDENTIFIER: - msg = "invalid character in identifier"; - break; - default: - fprintf(stderr, "error=%d\n", err->error); - msg = "unknown parsing error"; - break; - } - /* err->text may not be UTF-8 in case of decoding errors. - Explicitly convert to an object. */ - if (!err->text) { - errtext = Py_None; - Py_INCREF(Py_None); - } else { - errtext = PyUnicode_DecodeUTF8(err->text, strlen(err->text), - "replace"); - } - v = Py_BuildValue("(ziiN)", err->filename, - err->lineno, err->offset, errtext); - if (v != NULL) { - if (msg_obj) - w = Py_BuildValue("(OO)", msg_obj, v); - else - w = Py_BuildValue("(sO)", msg, v); - } else - w = NULL; - Py_XDECREF(v); - PyErr_SetObject(errtype, w); - Py_XDECREF(w); + PyObject *v, *w, *errtype, *errtext; + PyObject *msg_obj = NULL; + char *msg = NULL; + errtype = PyExc_SyntaxError; + switch (err->error) { + case E_ERROR: + return; + 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 literal"; + break; + case E_EOLS: + msg = "EOL while scanning string literal"; + break; + case E_INTR: + if (!PyErr_Occurred()) + PyErr_SetNone(PyExc_KeyboardInterrupt); + goto cleanup; + case E_NOMEM: + PyErr_NoMemory(); + goto cleanup; + 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); + msg = "unknown decode error"; + if (value != NULL) + msg_obj = PyObject_Str(value); + Py_XDECREF(type); + Py_XDECREF(value); + Py_XDECREF(tb); + break; + } + case E_LINECONT: + msg = "unexpected character after line continuation character"; + break; + + case E_IDENTIFIER: + msg = "invalid character in identifier"; + break; + default: + fprintf(stderr, "error=%d\n", err->error); + msg = "unknown parsing error"; + break; + } + /* err->text may not be UTF-8 in case of decoding errors. + Explicitly convert to an object. */ + if (!err->text) { + errtext = Py_None; + Py_INCREF(Py_None); + } else { + errtext = PyUnicode_DecodeUTF8(err->text, strlen(err->text), + "replace"); + } + v = Py_BuildValue("(ziiN)", err->filename, + err->lineno, err->offset, errtext); + if (v != NULL) { + if (msg_obj) + w = Py_BuildValue("(OO)", msg_obj, v); + else + w = Py_BuildValue("(sO)", msg, v); + } else + w = NULL; + Py_XDECREF(v); + PyErr_SetObject(errtype, w); + Py_XDECREF(w); cleanup: - Py_XDECREF(msg_obj); - if (err->text != NULL) { - PyObject_FREE(err->text); - err->text = NULL; - } + Py_XDECREF(msg_obj); + if (err->text != NULL) { + PyObject_FREE(err->text); + err->text = NULL; + } } /* Print fatal error message and abort */ @@ -2006,32 +2006,32 @@ cleanup: void Py_FatalError(const char *msg) { - fprintf(stderr, "Fatal Python error: %s\n", msg); - fflush(stderr); /* it helps in Windows debug build */ - if (PyErr_Occurred()) { - PyErr_Print(); - } + fprintf(stderr, "Fatal Python error: %s\n", msg); + fflush(stderr); /* it helps in Windows debug build */ + if (PyErr_Occurred()) { + PyErr_Print(); + } #ifdef MS_WINDOWS - { - size_t len = strlen(msg); - WCHAR* buffer; - size_t i; - - /* Convert the message to wchar_t. This uses a simple one-to-one - conversion, assuming that the this error message actually uses ASCII - only. If this ceases to be true, we will have to convert. */ - buffer = alloca( (len+1) * (sizeof *buffer)); - for( i=0; i<=len; ++i) - buffer[i] = msg[i]; - OutputDebugStringW(L"Fatal Python error: "); - OutputDebugStringW(buffer); - OutputDebugStringW(L"\n"); - } + { + size_t len = strlen(msg); + WCHAR* buffer; + size_t i; + + /* Convert the message to wchar_t. This uses a simple one-to-one + conversion, assuming that the this error message actually uses ASCII + only. If this ceases to be true, we will have to convert. */ + buffer = alloca( (len+1) * (sizeof *buffer)); + for( i=0; i<=len; ++i) + buffer[i] = msg[i]; + OutputDebugStringW(L"Fatal Python error: "); + OutputDebugStringW(buffer); + OutputDebugStringW(L"\n"); + } #ifdef _DEBUG - DebugBreak(); + DebugBreak(); #endif #endif /* MS_WINDOWS */ - abort(); + abort(); } /* Clean up and exit */ @@ -2044,17 +2044,17 @@ static void (*pyexitfunc)(void) = NULL; /* For the atexit module. */ void _Py_PyAtExit(void (*func)(void)) { - pyexitfunc = func; + pyexitfunc = func; } static void call_py_exitfuncs(void) { - if (pyexitfunc == NULL) - return; + if (pyexitfunc == NULL) + return; - (*pyexitfunc)(); - PyErr_Clear(); + (*pyexitfunc)(); + PyErr_Clear(); } /* Wait until threading._shutdown completes, provided @@ -2065,23 +2065,23 @@ static void wait_for_thread_shutdown(void) { #ifdef WITH_THREAD - PyObject *result; - PyThreadState *tstate = PyThreadState_GET(); - PyObject *threading = PyMapping_GetItemString(tstate->interp->modules, - "threading"); - if (threading == NULL) { - /* threading not imported */ - PyErr_Clear(); - return; - } - result = PyObject_CallMethod(threading, "_shutdown", ""); - if (result == NULL) { - PyErr_WriteUnraisable(threading); - } - else { - Py_DECREF(result); - } - Py_DECREF(threading); + PyObject *result; + PyThreadState *tstate = PyThreadState_GET(); + PyObject *threading = PyMapping_GetItemString(tstate->interp->modules, + "threading"); + if (threading == NULL) { + /* threading not imported */ + PyErr_Clear(); + return; + } + result = PyObject_CallMethod(threading, "_shutdown", ""); + if (result == NULL) { + PyErr_WriteUnraisable(threading); + } + else { + Py_DECREF(result); + } + Py_DECREF(threading); #endif } @@ -2091,43 +2091,43 @@ static int nexitfuncs = 0; int Py_AtExit(void (*func)(void)) { - if (nexitfuncs >= NEXITFUNCS) - return -1; - exitfuncs[nexitfuncs++] = func; - return 0; + if (nexitfuncs >= NEXITFUNCS) + return -1; + exitfuncs[nexitfuncs++] = func; + return 0; } static void call_ll_exitfuncs(void) { - while (nexitfuncs > 0) - (*exitfuncs[--nexitfuncs])(); + while (nexitfuncs > 0) + (*exitfuncs[--nexitfuncs])(); - fflush(stdout); - fflush(stderr); + fflush(stdout); + fflush(stderr); } void Py_Exit(int sts) { - Py_Finalize(); + Py_Finalize(); - exit(sts); + exit(sts); } static void initsigs(void) { #ifdef SIGPIPE - PyOS_setsig(SIGPIPE, SIG_IGN); + PyOS_setsig(SIGPIPE, SIG_IGN); #endif #ifdef SIGXFZ - PyOS_setsig(SIGXFZ, SIG_IGN); + PyOS_setsig(SIGXFZ, SIG_IGN); #endif #ifdef SIGXFSZ - PyOS_setsig(SIGXFSZ, SIG_IGN); + PyOS_setsig(SIGXFSZ, SIG_IGN); #endif - PyOS_InitInterrupts(); /* May imply initsignal() */ + PyOS_InitInterrupts(); /* May imply initsignal() */ } @@ -2141,13 +2141,13 @@ void _Py_RestoreSignals(void) { #ifdef SIGPIPE - PyOS_setsig(SIGPIPE, SIG_DFL); + PyOS_setsig(SIGPIPE, SIG_DFL); #endif #ifdef SIGXFZ - PyOS_setsig(SIGXFZ, SIG_DFL); + PyOS_setsig(SIGXFZ, SIG_DFL); #endif #ifdef SIGXFSZ - PyOS_setsig(SIGXFSZ, SIG_DFL); + PyOS_setsig(SIGXFSZ, SIG_DFL); #endif } @@ -2161,13 +2161,13 @@ _Py_RestoreSignals(void) 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, "") == 0) || - (strcmp(filename, "???") == 0); + if (isatty((int)fileno(fp))) + return 1; + if (!Py_InteractiveFlag) + return 0; + return (filename == NULL) || + (strcmp(filename, "") == 0) || + (strcmp(filename, "???") == 0); } @@ -2185,21 +2185,21 @@ Py_FdIsInteractive(FILE *fp, const char *filename) 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 (GetExceptionCode() == STATUS_STACK_OVERFLOW ? - EXCEPTION_EXECUTE_HANDLER : - EXCEPTION_CONTINUE_SEARCH) { - int errcode = _resetstkoflw(); - if (errcode == 0) - { - Py_FatalError("Could not reset the stack!"); - } - } - return 1; + __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 (GetExceptionCode() == STATUS_STACK_OVERFLOW ? + EXCEPTION_EXECUTE_HANDLER : + EXCEPTION_CONTINUE_SEARCH) { + int errcode = _resetstkoflw(); + if (errcode == 0) + { + Py_FatalError("Could not reset the stack!"); + } + } + return 1; } #endif /* WIN32 && _MSC_VER */ @@ -2215,33 +2215,33 @@ 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; + struct sigaction context; + if (sigaction(sig, NULL, &context) == -1) + return SIG_ERR; + return context.sa_handler; #else - PyOS_sighandler_t handler; + 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; - } + 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; + handler = signal(sig, SIG_IGN); + if (handler != SIG_ERR) + signal(sig, handler); + return handler; #endif } @@ -2254,24 +2254,24 @@ PyOS_sighandler_t PyOS_setsig(int sig, PyOS_sighandler_t handler) { #ifdef HAVE_SIGACTION - /* Some code in Modules/signalmodule.c depends on sigaction() being - * used here if HAVE_SIGACTION is defined. Fix that if this code - * changes to invalidate that assumption. - */ - 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; + /* Some code in Modules/signalmodule.c depends on sigaction() being + * used here if HAVE_SIGACTION is defined. Fix that if this code + * changes to invalidate that assumption. + */ + 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); + PyOS_sighandler_t oldhandler; + oldhandler = signal(sig, handler); #ifdef HAVE_SIGINTERRUPT - siginterrupt(sig, 1); + siginterrupt(sig, 1); #endif - return oldhandler; + return oldhandler; #endif } @@ -2281,71 +2281,71 @@ PyOS_setsig(int sig, PyOS_sighandler_t handler) PyAPI_FUNC(node *) PyParser_SimpleParseFile(FILE *fp, const char *filename, int start) { - return PyParser_SimpleParseFileFlags(fp, filename, start, 0); + 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); + 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); + 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); + 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); + 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); + 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); + 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) + PyCompilerFlags *flags) { - return PyRun_FileExFlags(fp, p, s, g, l, 0, 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); + 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); + return PyRun_SimpleFileExFlags(f, p, c, NULL); } @@ -2353,35 +2353,35 @@ PyRun_SimpleFileEx(FILE *f, const char *p, int c) PyAPI_FUNC(PyObject *) PyRun_String(const char *str, int s, PyObject *g, PyObject *l) { - return PyRun_StringFlags(str, s, g, l, NULL); + return PyRun_StringFlags(str, s, g, l, NULL); } #undef PyRun_SimpleString PyAPI_FUNC(int) PyRun_SimpleString(const char *s) { - return PyRun_SimpleStringFlags(s, NULL); + 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); + 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); + 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); + return PyRun_InteractiveLoopFlags(f, p, NULL); } #ifdef __cplusplus diff --git a/Python/structmember.c b/Python/structmember.c index 9109f23540..ddedea5419 100644 --- a/Python/structmember.c +++ b/Python/structmember.c @@ -8,293 +8,293 @@ PyObject * PyMember_GetOne(const char *addr, PyMemberDef *l) { - PyObject *v; + PyObject *v; - addr += l->offset; - switch (l->type) { - case T_BOOL: - v = PyBool_FromLong(*(char*)addr); - break; - case T_BYTE: - v = PyLong_FromLong(*(char*)addr); - break; - case T_UBYTE: - v = PyLong_FromUnsignedLong(*(unsigned char*)addr); - break; - case T_SHORT: - v = PyLong_FromLong(*(short*)addr); - break; - case T_USHORT: - v = PyLong_FromUnsignedLong(*(unsigned short*)addr); - break; - case T_INT: - v = PyLong_FromLong(*(int*)addr); - break; - case T_UINT: - v = PyLong_FromUnsignedLong(*(unsigned int*)addr); - break; - case T_LONG: - v = PyLong_FromLong(*(long*)addr); - break; - case T_ULONG: - v = PyLong_FromUnsignedLong(*(unsigned long*)addr); - break; - case T_PYSSIZET: - v = PyLong_FromSsize_t(*(Py_ssize_t*)addr); - break; - case T_FLOAT: - v = PyFloat_FromDouble((double)*(float*)addr); - break; - case T_DOUBLE: - v = PyFloat_FromDouble(*(double*)addr); - break; - case T_STRING: - if (*(char**)addr == NULL) { - Py_INCREF(Py_None); - v = Py_None; - } - else - v = PyUnicode_FromString(*(char**)addr); - break; - case T_STRING_INPLACE: - v = PyUnicode_FromString((char*)addr); - break; - case T_CHAR: - v = PyUnicode_FromStringAndSize((char*)addr, 1); - break; - case T_OBJECT: - v = *(PyObject **)addr; - if (v == NULL) - v = Py_None; - Py_INCREF(v); - break; - case T_OBJECT_EX: - v = *(PyObject **)addr; - if (v == NULL) - PyErr_SetString(PyExc_AttributeError, l->name); - Py_XINCREF(v); - break; + addr += l->offset; + switch (l->type) { + case T_BOOL: + v = PyBool_FromLong(*(char*)addr); + break; + case T_BYTE: + v = PyLong_FromLong(*(char*)addr); + break; + case T_UBYTE: + v = PyLong_FromUnsignedLong(*(unsigned char*)addr); + break; + case T_SHORT: + v = PyLong_FromLong(*(short*)addr); + break; + case T_USHORT: + v = PyLong_FromUnsignedLong(*(unsigned short*)addr); + break; + case T_INT: + v = PyLong_FromLong(*(int*)addr); + break; + case T_UINT: + v = PyLong_FromUnsignedLong(*(unsigned int*)addr); + break; + case T_LONG: + v = PyLong_FromLong(*(long*)addr); + break; + case T_ULONG: + v = PyLong_FromUnsignedLong(*(unsigned long*)addr); + break; + case T_PYSSIZET: + v = PyLong_FromSsize_t(*(Py_ssize_t*)addr); + break; + case T_FLOAT: + v = PyFloat_FromDouble((double)*(float*)addr); + break; + case T_DOUBLE: + v = PyFloat_FromDouble(*(double*)addr); + break; + case T_STRING: + if (*(char**)addr == NULL) { + Py_INCREF(Py_None); + v = Py_None; + } + else + v = PyUnicode_FromString(*(char**)addr); + break; + case T_STRING_INPLACE: + v = PyUnicode_FromString((char*)addr); + break; + case T_CHAR: + v = PyUnicode_FromStringAndSize((char*)addr, 1); + break; + case T_OBJECT: + v = *(PyObject **)addr; + if (v == NULL) + v = Py_None; + Py_INCREF(v); + break; + case T_OBJECT_EX: + v = *(PyObject **)addr; + if (v == NULL) + PyErr_SetString(PyExc_AttributeError, l->name); + Py_XINCREF(v); + break; #ifdef HAVE_LONG_LONG - case T_LONGLONG: - v = PyLong_FromLongLong(*(PY_LONG_LONG *)addr); - break; - case T_ULONGLONG: - v = PyLong_FromUnsignedLongLong(*(unsigned PY_LONG_LONG *)addr); - break; + case T_LONGLONG: + v = PyLong_FromLongLong(*(PY_LONG_LONG *)addr); + break; + case T_ULONGLONG: + v = PyLong_FromUnsignedLongLong(*(unsigned PY_LONG_LONG *)addr); + break; #endif /* HAVE_LONG_LONG */ - case T_NONE: - v = Py_None; - Py_INCREF(v); - break; - default: - PyErr_SetString(PyExc_SystemError, "bad memberdescr type"); - v = NULL; - } - return v; + case T_NONE: + v = Py_None; + Py_INCREF(v); + break; + default: + PyErr_SetString(PyExc_SystemError, "bad memberdescr type"); + v = NULL; + } + return v; } -#define WARN(msg) \ - do { \ - if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1) < 0) \ - return -1; \ +#define WARN(msg) \ + do { \ + if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1) < 0) \ + return -1; \ } while (0) int PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v) { - PyObject *oldv; + PyObject *oldv; - addr += l->offset; + addr += l->offset; - if ((l->flags & READONLY)) - { - PyErr_SetString(PyExc_AttributeError, "readonly attribute"); - return -1; - } - if (v == NULL) { - if (l->type == T_OBJECT_EX) { - /* Check if the attribute is set. */ - if (*(PyObject **)addr == NULL) { - PyErr_SetString(PyExc_AttributeError, l->name); - return -1; - } - } - else if (l->type != T_OBJECT) { - PyErr_SetString(PyExc_TypeError, - "can't delete numeric/char attribute"); - return -1; - } - } - switch (l->type) { - case T_BOOL:{ - if (!PyBool_Check(v)) { - PyErr_SetString(PyExc_TypeError, - "attribute value type must be bool"); - return -1; - } - if (v == Py_True) - *(char*)addr = (char) 1; - else - *(char*)addr = (char) 0; - break; - } - case T_BYTE:{ - long long_val = PyLong_AsLong(v); - if ((long_val == -1) && PyErr_Occurred()) - return -1; - *(char*)addr = (char)long_val; - /* XXX: For compatibility, only warn about truncations - for now. */ - if ((long_val > CHAR_MAX) || (long_val < CHAR_MIN)) - WARN("Truncation of value to char"); - break; - } - case T_UBYTE:{ - long long_val = PyLong_AsLong(v); - if ((long_val == -1) && PyErr_Occurred()) - return -1; - *(unsigned char*)addr = (unsigned char)long_val; - if ((long_val > UCHAR_MAX) || (long_val < 0)) - WARN("Truncation of value to unsigned char"); - break; - } - case T_SHORT:{ - long long_val = PyLong_AsLong(v); - if ((long_val == -1) && PyErr_Occurred()) - return -1; - *(short*)addr = (short)long_val; - if ((long_val > SHRT_MAX) || (long_val < SHRT_MIN)) - WARN("Truncation of value to short"); - break; - } - case T_USHORT:{ - long long_val = PyLong_AsLong(v); - if ((long_val == -1) && PyErr_Occurred()) - return -1; - *(unsigned short*)addr = (unsigned short)long_val; - if ((long_val > USHRT_MAX) || (long_val < 0)) - WARN("Truncation of value to unsigned short"); - break; - } - case T_INT:{ - long long_val = PyLong_AsLong(v); - if ((long_val == -1) && PyErr_Occurred()) - return -1; - *(int *)addr = (int)long_val; - if ((long_val > INT_MAX) || (long_val < INT_MIN)) - WARN("Truncation of value to int"); - break; - } - case T_UINT:{ - unsigned long ulong_val = PyLong_AsUnsignedLong(v); - if ((ulong_val == (unsigned long)-1) && PyErr_Occurred()) { - /* XXX: For compatibility, accept negative int values - as well. */ - PyErr_Clear(); - ulong_val = PyLong_AsLong(v); - if ((ulong_val == (unsigned long)-1) && - PyErr_Occurred()) - return -1; - *(unsigned int *)addr = (unsigned int)ulong_val; - WARN("Writing negative value into unsigned field"); - } else - *(unsigned int *)addr = (unsigned int)ulong_val; - if (ulong_val > UINT_MAX) - WARN("Truncation of value to unsigned int"); - break; - } - case T_LONG:{ - *(long*)addr = PyLong_AsLong(v); - if ((*(long*)addr == -1) && PyErr_Occurred()) - return -1; - break; - } - case T_ULONG:{ - *(unsigned long*)addr = PyLong_AsUnsignedLong(v); - if ((*(unsigned long*)addr == (unsigned long)-1) - && PyErr_Occurred()) { - /* XXX: For compatibility, accept negative int values - as well. */ - PyErr_Clear(); - *(unsigned long*)addr = PyLong_AsLong(v); - if ((*(unsigned long*)addr == (unsigned long)-1) - && PyErr_Occurred()) - return -1; - WARN("Writing negative value into unsigned field"); - } - break; - } - case T_PYSSIZET:{ - *(Py_ssize_t*)addr = PyLong_AsSsize_t(v); - if ((*(Py_ssize_t*)addr == (Py_ssize_t)-1) - && PyErr_Occurred()) - return -1; - break; - } - case T_FLOAT:{ - double double_val = PyFloat_AsDouble(v); - if ((double_val == -1) && PyErr_Occurred()) - return -1; - *(float*)addr = (float)double_val; - break; - } - case T_DOUBLE: - *(double*)addr = PyFloat_AsDouble(v); - if ((*(double*)addr == -1) && PyErr_Occurred()) - return -1; - break; - case T_OBJECT: - case T_OBJECT_EX: - Py_XINCREF(v); - oldv = *(PyObject **)addr; - *(PyObject **)addr = v; - Py_XDECREF(oldv); - break; - case T_CHAR: { - char *string; - Py_ssize_t len; + if ((l->flags & READONLY)) + { + PyErr_SetString(PyExc_AttributeError, "readonly attribute"); + return -1; + } + if (v == NULL) { + if (l->type == T_OBJECT_EX) { + /* Check if the attribute is set. */ + if (*(PyObject **)addr == NULL) { + PyErr_SetString(PyExc_AttributeError, l->name); + return -1; + } + } + else if (l->type != T_OBJECT) { + PyErr_SetString(PyExc_TypeError, + "can't delete numeric/char attribute"); + return -1; + } + } + switch (l->type) { + case T_BOOL:{ + if (!PyBool_Check(v)) { + PyErr_SetString(PyExc_TypeError, + "attribute value type must be bool"); + return -1; + } + if (v == Py_True) + *(char*)addr = (char) 1; + else + *(char*)addr = (char) 0; + break; + } + case T_BYTE:{ + long long_val = PyLong_AsLong(v); + if ((long_val == -1) && PyErr_Occurred()) + return -1; + *(char*)addr = (char)long_val; + /* XXX: For compatibility, only warn about truncations + for now. */ + if ((long_val > CHAR_MAX) || (long_val < CHAR_MIN)) + WARN("Truncation of value to char"); + break; + } + case T_UBYTE:{ + long long_val = PyLong_AsLong(v); + if ((long_val == -1) && PyErr_Occurred()) + return -1; + *(unsigned char*)addr = (unsigned char)long_val; + if ((long_val > UCHAR_MAX) || (long_val < 0)) + WARN("Truncation of value to unsigned char"); + break; + } + case T_SHORT:{ + long long_val = PyLong_AsLong(v); + if ((long_val == -1) && PyErr_Occurred()) + return -1; + *(short*)addr = (short)long_val; + if ((long_val > SHRT_MAX) || (long_val < SHRT_MIN)) + WARN("Truncation of value to short"); + break; + } + case T_USHORT:{ + long long_val = PyLong_AsLong(v); + if ((long_val == -1) && PyErr_Occurred()) + return -1; + *(unsigned short*)addr = (unsigned short)long_val; + if ((long_val > USHRT_MAX) || (long_val < 0)) + WARN("Truncation of value to unsigned short"); + break; + } + case T_INT:{ + long long_val = PyLong_AsLong(v); + if ((long_val == -1) && PyErr_Occurred()) + return -1; + *(int *)addr = (int)long_val; + if ((long_val > INT_MAX) || (long_val < INT_MIN)) + WARN("Truncation of value to int"); + break; + } + case T_UINT:{ + unsigned long ulong_val = PyLong_AsUnsignedLong(v); + if ((ulong_val == (unsigned long)-1) && PyErr_Occurred()) { + /* XXX: For compatibility, accept negative int values + as well. */ + PyErr_Clear(); + ulong_val = PyLong_AsLong(v); + if ((ulong_val == (unsigned long)-1) && + PyErr_Occurred()) + return -1; + *(unsigned int *)addr = (unsigned int)ulong_val; + WARN("Writing negative value into unsigned field"); + } else + *(unsigned int *)addr = (unsigned int)ulong_val; + if (ulong_val > UINT_MAX) + WARN("Truncation of value to unsigned int"); + break; + } + case T_LONG:{ + *(long*)addr = PyLong_AsLong(v); + if ((*(long*)addr == -1) && PyErr_Occurred()) + return -1; + break; + } + case T_ULONG:{ + *(unsigned long*)addr = PyLong_AsUnsignedLong(v); + if ((*(unsigned long*)addr == (unsigned long)-1) + && PyErr_Occurred()) { + /* XXX: For compatibility, accept negative int values + as well. */ + PyErr_Clear(); + *(unsigned long*)addr = PyLong_AsLong(v); + if ((*(unsigned long*)addr == (unsigned long)-1) + && PyErr_Occurred()) + return -1; + WARN("Writing negative value into unsigned field"); + } + break; + } + case T_PYSSIZET:{ + *(Py_ssize_t*)addr = PyLong_AsSsize_t(v); + if ((*(Py_ssize_t*)addr == (Py_ssize_t)-1) + && PyErr_Occurred()) + return -1; + break; + } + case T_FLOAT:{ + double double_val = PyFloat_AsDouble(v); + if ((double_val == -1) && PyErr_Occurred()) + return -1; + *(float*)addr = (float)double_val; + break; + } + case T_DOUBLE: + *(double*)addr = PyFloat_AsDouble(v); + if ((*(double*)addr == -1) && PyErr_Occurred()) + return -1; + break; + case T_OBJECT: + case T_OBJECT_EX: + Py_XINCREF(v); + oldv = *(PyObject **)addr; + *(PyObject **)addr = v; + Py_XDECREF(oldv); + break; + case T_CHAR: { + char *string; + Py_ssize_t len; - if (!PyUnicode_Check(v)) { - PyErr_BadArgument(); - return -1; - } - string = _PyUnicode_AsStringAndSize(v, &len); - if (len != 1) { - PyErr_BadArgument(); - return -1; - } - *(char*)addr = string[0]; - break; - } - case T_STRING: - case T_STRING_INPLACE: - PyErr_SetString(PyExc_TypeError, "readonly attribute"); - return -1; + if (!PyUnicode_Check(v)) { + PyErr_BadArgument(); + return -1; + } + string = _PyUnicode_AsStringAndSize(v, &len); + if (len != 1) { + PyErr_BadArgument(); + return -1; + } + *(char*)addr = string[0]; + break; + } + case T_STRING: + case T_STRING_INPLACE: + PyErr_SetString(PyExc_TypeError, "readonly attribute"); + return -1; #ifdef HAVE_LONG_LONG - case T_LONGLONG:{ - PY_LONG_LONG value; - *(PY_LONG_LONG*)addr = value = PyLong_AsLongLong(v); - if ((value == -1) && PyErr_Occurred()) - return -1; - break; - } - case T_ULONGLONG:{ - unsigned PY_LONG_LONG value; - /* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong - doesn't ??? */ - if (PyLong_Check(v)) - *(unsigned PY_LONG_LONG*)addr = value = PyLong_AsUnsignedLongLong(v); - else - *(unsigned PY_LONG_LONG*)addr = value = PyLong_AsLong(v); - if ((value == (unsigned PY_LONG_LONG)-1) && PyErr_Occurred()) - return -1; - break; - } + case T_LONGLONG:{ + PY_LONG_LONG value; + *(PY_LONG_LONG*)addr = value = PyLong_AsLongLong(v); + if ((value == -1) && PyErr_Occurred()) + return -1; + break; + } + case T_ULONGLONG:{ + unsigned PY_LONG_LONG value; + /* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong + doesn't ??? */ + if (PyLong_Check(v)) + *(unsigned PY_LONG_LONG*)addr = value = PyLong_AsUnsignedLongLong(v); + else + *(unsigned PY_LONG_LONG*)addr = value = PyLong_AsLong(v); + if ((value == (unsigned PY_LONG_LONG)-1) && PyErr_Occurred()) + return -1; + break; + } #endif /* HAVE_LONG_LONG */ - default: - PyErr_Format(PyExc_SystemError, - "bad memberdescr type for %s", l->name); - return -1; - } - return 0; + default: + PyErr_Format(PyExc_SystemError, + "bad memberdescr type for %s", l->name); + return -1; + } + return 0; } diff --git a/Python/symtable.c b/Python/symtable.c index 7fa01b899e..83f02315b6 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -25,145 +25,145 @@ static PySTEntryObject * ste_new(struct symtable *st, identifier name, _Py_block_ty block, - void *key, int lineno) + void *key, int lineno) { - PySTEntryObject *ste = NULL; - PyObject *k; - - k = PyLong_FromVoidPtr(key); - if (k == NULL) - goto fail; - ste = PyObject_New(PySTEntryObject, &PySTEntry_Type); - if (ste == NULL) - goto fail; - ste->ste_table = st; - ste->ste_id = k; - - 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_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_blocks, ste->ste_id, (PyObject *)ste) < 0) - goto fail; - - return ste; + PySTEntryObject *ste = NULL; + PyObject *k; + + k = PyLong_FromVoidPtr(key); + if (k == NULL) + goto fail; + ste = PyObject_New(PySTEntryObject, &PySTEntry_Type); + if (ste == NULL) + goto fail; + ste->ste_table = st; + ste->ste_id = k; + + 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_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_blocks, ste->ste_id, (PyObject *)ste) < 0) + goto fail; + + return ste; fail: - Py_XDECREF(ste); - return NULL; + Py_XDECREF(ste); + return NULL; } static PyObject * ste_repr(PySTEntryObject *ste) { - return PyUnicode_FromFormat("", - ste->ste_name, - PyLong_AS_LONG(ste->ste_id), ste->ste_lineno); + return PyUnicode_FromFormat("", + ste->ste_name, + PyLong_AS_LONG(ste->ste_id), ste->ste_lineno); } 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); + 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}, - {"optimized",T_INT, OFF(ste_unoptimized), READONLY}, - {"nested", T_INT, OFF(ste_nested), READONLY}, - {"type", T_INT, OFF(ste_type), READONLY}, - {"lineno", T_INT, OFF(ste_lineno), READONLY}, - {NULL} + {"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}, + {"optimized",T_INT, OFF(ste_unoptimized), READONLY}, + {"nested", T_INT, OFF(ste_nested), READONLY}, + {"type", T_INT, OFF(ste_type), READONLY}, + {"lineno", T_INT, OFF(ste_lineno), READONLY}, + {NULL} }; PyTypeObject PySTEntry_Type = { - PyVarObject_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_reserved */ - (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 */ + PyVarObject_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_reserved */ + (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_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); @@ -184,11 +184,11 @@ static int symtable_visit_annotations(struct symtable *st, stmt_ty s); static identifier top = NULL, lambda = NULL, genexpr = NULL, - listcomp = NULL, setcomp = NULL, dictcomp = NULL, - __class__ = NULL, __locals__ = NULL; + listcomp = NULL, setcomp = NULL, dictcomp = NULL, + __class__ = NULL, __locals__ = NULL; #define GET_IDENTIFIER(VAR) \ - ((VAR) ? (VAR) : ((VAR) = PyUnicode_InternFromString(# VAR))) + ((VAR) ? (VAR) : ((VAR) = PyUnicode_InternFromString(# VAR))) #define DUPLICATE_ARGUMENT \ "duplicate argument '%U' in function definition" @@ -196,135 +196,135 @@ static identifier top = NULL, lambda = NULL, genexpr = NULL, 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_blocks = NULL; - - if ((st->st_stack = PyList_New(0)) == NULL) - goto fail; - if ((st->st_blocks = PyDict_New()) == NULL) - goto fail; - st->st_cur = NULL; - st->st_private = NULL; - return st; + struct symtable *st; + + st = (struct symtable *)PyMem_Malloc(sizeof(struct symtable)); + if (st == NULL) + return NULL; + + st->st_filename = NULL; + st->st_blocks = NULL; + + if ((st->st_stack = PyList_New(0)) == NULL) + goto fail; + if ((st->st_blocks = PyDict_New()) == NULL) + goto fail; + st->st_cur = NULL; + st->st_private = NULL; + return st; fail: - PySymtable_Free(st); - return NULL; + 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; - /* Make the initial symbol information gathering pass */ - if (!GET_IDENTIFIER(top) || - !symtable_enter_block(st, top, ModuleBlock, (void *)mod, 0)) { - PySymtable_Free(st); - return NULL; - } - - st->st_top = st->st_cur; - st->st_cur->ste_unoptimized = OPT_TOPLEVEL; - 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; - } - /* Make the second symbol analysis pass */ - if (symtable_analyze(st)) - return st; - PySymtable_Free(st); - return NULL; + struct symtable *st = symtable_new(); + asdl_seq *seq; + int i; + + if (st == NULL) + return st; + st->st_filename = filename; + st->st_future = future; + /* Make the initial symbol information gathering pass */ + if (!GET_IDENTIFIER(top) || + !symtable_enter_block(st, top, ModuleBlock, (void *)mod, 0)) { + PySymtable_Free(st); + return NULL; + } + + st->st_top = st->st_cur; + st->st_cur->ste_unoptimized = OPT_TOPLEVEL; + 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; + } + /* Make the second symbol analysis pass */ + 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) symtable_exit_block(st, (void *)mod); + PySymtable_Free(st); + return NULL; } void PySymtable_Free(struct symtable *st) { - Py_XDECREF(st->st_blocks); - Py_XDECREF(st->st_stack); - PyMem_Free((void *)st); + Py_XDECREF(st->st_blocks); + 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_blocks, 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; + PyObject *k, *v; + + k = PyLong_FromVoidPtr(key); + if (k == NULL) + return NULL; + v = PyDict_GetItem(st->st_blocks, 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 +int PyST_GetScope(PySTEntryObject *ste, PyObject *name) { - PyObject *v = PyDict_GetItem(ste->ste_symbols, name); - if (!v) - return 0; - assert(PyLong_Check(v)); - return (PyLong_AS_LONG(v) >> SCOPE_OFFSET) & SCOPE_MASK; + PyObject *v = PyDict_GetItem(ste->ste_symbols, name); + if (!v) + return 0; + assert(PyLong_Check(v)); + return (PyLong_AS_LONG(v) >> SCOPE_OFFSET) & SCOPE_MASK; } /* Analyze raw symbol information to determine scope of each name. The next several functions are helpers for symtable_analyze(), - which determines whether a name is local, global, or free. In addition, + 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. + bindings that are used for free variables in enclosed blocks. - There are also two kinds of global variables, implicit and explicit. An + There are also two kinds of global 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 @@ -340,7 +340,7 @@ PyST_GetScope(PySTEntryObject *ste, PyObject *name) 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 + the set of all name bindings visible to its children. These bindings are used to determine if non-local variables are free or implicit globals. Names which are explicitly declared nonlocal must exist in this set of visible names - if they do not, a syntax error is raised. After doing @@ -363,14 +363,14 @@ PyST_GetScope(PySTEntryObject *ste, PyObject *name) */ #define SET_SCOPE(DICT, NAME, I) { \ - PyObject *o = PyLong_FromLong(I); \ - if (!o) \ - return 0; \ - if (PyDict_SetItem((DICT), (NAME), o) < 0) { \ - Py_DECREF(o); \ - return 0; \ - } \ - Py_DECREF(o); \ + PyObject *o = PyLong_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. @@ -380,86 +380,86 @@ PyST_GetScope(PySTEntryObject *ste, PyObject *name) global. A name that was global can be changed to local. */ -static int +static int analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags, - PyObject *bound, PyObject *local, PyObject *free, - PyObject *global) + PyObject *bound, PyObject *local, PyObject *free, + PyObject *global) { - if (flags & DEF_GLOBAL) { - if (flags & DEF_PARAM) { - PyErr_Format(PyExc_SyntaxError, - "name '%U' is parameter and global", - name); - PyErr_SyntaxLocation(ste->ste_table->st_filename, - ste->ste_lineno); - - return 0; - } - if (flags & DEF_NONLOCAL) { - PyErr_Format(PyExc_SyntaxError, - "name '%U' is nonlocal and global", - name); - return 0; - } - SET_SCOPE(scopes, name, GLOBAL_EXPLICIT); - if (PySet_Add(global, name) < 0) - return 0; - if (bound && (PySet_Discard(bound, name) < 0)) - return 0; - return 1; - } + if (flags & DEF_GLOBAL) { + if (flags & DEF_PARAM) { + PyErr_Format(PyExc_SyntaxError, + "name '%U' is parameter and global", + name); + PyErr_SyntaxLocation(ste->ste_table->st_filename, + ste->ste_lineno); + + return 0; + } if (flags & DEF_NONLOCAL) { - if (flags & DEF_PARAM) { - PyErr_Format(PyExc_SyntaxError, - "name '%U' is parameter and nonlocal", - name); - return 0; - } - if (!bound) { - PyErr_Format(PyExc_SyntaxError, - "nonlocal declaration not allowed at module level"); - return 0; - } - if (!PySet_Contains(bound, name)) { - PyErr_Format(PyExc_SyntaxError, - "no binding for nonlocal '%U' found", - name); - - return 0; - } - SET_SCOPE(scopes, name, FREE); - ste->ste_free = 1; - return PySet_Add(free, name) >= 0; + PyErr_Format(PyExc_SyntaxError, + "name '%U' is nonlocal and global", + name); + return 0; + } + SET_SCOPE(scopes, name, GLOBAL_EXPLICIT); + if (PySet_Add(global, name) < 0) + return 0; + if (bound && (PySet_Discard(bound, name) < 0)) + return 0; + return 1; + } + if (flags & DEF_NONLOCAL) { + if (flags & DEF_PARAM) { + PyErr_Format(PyExc_SyntaxError, + "name '%U' is parameter and nonlocal", + name); + return 0; } - if (flags & DEF_BOUND) { - SET_SCOPE(scopes, name, LOCAL); - if (PySet_Add(local, name) < 0) - return 0; - if (PySet_Discard(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 && PySet_Contains(bound, name)) { - SET_SCOPE(scopes, name, FREE); - ste->ste_free = 1; - return PySet_Add(free, name) >= 0; - } - /* If a parent has a global statement, then call it global - explicit? It could also be global implicit. - */ - if (global && PySet_Contains(global, name)) { - SET_SCOPE(scopes, name, GLOBAL_IMPLICIT); - return 1; - } - if (ste->ste_nested) - ste->ste_free = 1; - SET_SCOPE(scopes, name, GLOBAL_IMPLICIT); - return 1; + if (!bound) { + PyErr_Format(PyExc_SyntaxError, + "nonlocal declaration not allowed at module level"); + return 0; + } + if (!PySet_Contains(bound, name)) { + PyErr_Format(PyExc_SyntaxError, + "no binding for nonlocal '%U' found", + name); + + return 0; + } + SET_SCOPE(scopes, name, FREE); + ste->ste_free = 1; + return PySet_Add(free, name) >= 0; + } + if (flags & DEF_BOUND) { + SET_SCOPE(scopes, name, LOCAL); + if (PySet_Add(local, name) < 0) + return 0; + if (PySet_Discard(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 && PySet_Contains(bound, name)) { + SET_SCOPE(scopes, name, FREE); + ste->ste_free = 1; + return PySet_Add(free, name) >= 0; + } + /* If a parent has a global statement, then call it global + explicit? It could also be global implicit. + */ + if (global && PySet_Contains(global, name)) { + SET_SCOPE(scopes, name, GLOBAL_IMPLICIT); + return 1; + } + if (ste->ste_nested) + ste->ste_free = 1; + SET_SCOPE(scopes, name, GLOBAL_IMPLICIT); + return 1; } #undef SET_SCOPE @@ -478,153 +478,153 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags, static int analyze_cells(PyObject *scopes, PyObject *free, const char *restricted) { - PyObject *name, *v, *v_cell; - int success = 0; - Py_ssize_t pos = 0; - - v_cell = PyLong_FromLong(CELL); - if (!v_cell) - return 0; - while (PyDict_Next(scopes, &pos, &name, &v)) { - long scope; - assert(PyLong_Check(v)); - scope = PyLong_AS_LONG(v); - if (scope != LOCAL) - continue; - if (!PySet_Contains(free, name)) - continue; - if (restricted != NULL && - PyUnicode_CompareWithASCIIString(name, restricted)) - 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(scopes, name, v_cell) < 0) - goto error; - if (PySet_Discard(free, name) < 0) - goto error; - } - success = 1; + PyObject *name, *v, *v_cell; + int success = 0; + Py_ssize_t pos = 0; + + v_cell = PyLong_FromLong(CELL); + if (!v_cell) + return 0; + while (PyDict_Next(scopes, &pos, &name, &v)) { + long scope; + assert(PyLong_Check(v)); + scope = PyLong_AS_LONG(v); + if (scope != LOCAL) + continue; + if (!PySet_Contains(free, name)) + continue; + if (restricted != NULL && + PyUnicode_CompareWithASCIIString(name, restricted)) + 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(scopes, name, v_cell) < 0) + goto error; + if (PySet_Discard(free, name) < 0) + goto error; + } + success = 1; error: - Py_DECREF(v_cell); - return success; + Py_DECREF(v_cell); + return success; } /* Check for illegal statements in unoptimized namespaces */ static int check_unoptimized(const PySTEntryObject* ste) { - 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: /* import * at top-level is fine */ - return 1; - case OPT_IMPORT_STAR: - PyErr_Format(PyExc_SyntaxError, - "import * is not allowed in function '%U' because it %s", - ste->ste_name, trailer); - break; - } - - PyErr_SyntaxLocation(ste->ste_table->st_filename, - ste->ste_opt_lineno); - return 0; + 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: /* import * at top-level is fine */ + return 1; + case OPT_IMPORT_STAR: + PyErr_Format(PyExc_SyntaxError, + "import * is not allowed in function '%U' because it %s", + ste->ste_name, trailer); + break; + } + + PyErr_SyntaxLocation(ste->ste_table->st_filename, + ste->ste_opt_lineno); + return 0; } -/* Enter the final scope information into the ste_symbols dict. - * +/* Enter the final scope information into the ste_symbols dict. + * * All arguments are dicts. Modifies symbols, others are read-only. */ static int -update_symbols(PyObject *symbols, PyObject *scopes, +update_symbols(PyObject *symbols, PyObject *scopes, PyObject *bound, PyObject *free, int classflag) { - PyObject *name = NULL, *itr = NULL; - PyObject *v = NULL, *v_scope = NULL, *v_new = NULL, *v_free = NULL; - Py_ssize_t pos = 0; - - /* Update scope information for all symbols in this scope */ - while (PyDict_Next(symbols, &pos, &name, &v)) { - long scope, flags; - assert(PyLong_Check(v)); - flags = PyLong_AS_LONG(v); - v_scope = PyDict_GetItem(scopes, name); - assert(v_scope && PyLong_Check(v_scope)); - scope = PyLong_AS_LONG(v_scope); - flags |= (scope << SCOPE_OFFSET); - v_new = PyLong_FromLong(flags); - if (!v_new) - return 0; - if (PyDict_SetItem(symbols, name, v_new) < 0) { - Py_DECREF(v_new); - return 0; - } - Py_DECREF(v_new); - } - - /* Record not yet resolved free variables from children (if any) */ - v_free = PyLong_FromLong(FREE << SCOPE_OFFSET); - if (!v_free) - return 0; - - itr = PyObject_GetIter(free); - if (!itr) - goto error; - - while ((name = PyIter_Next(itr))) { - v = PyDict_GetItem(symbols, name); - - /* Handle symbol that already exists in this scope */ - if (v) { - /* Handle 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 && - PyLong_AS_LONG(v) & (DEF_BOUND | DEF_GLOBAL)) { - long flags = PyLong_AS_LONG(v) | DEF_FREE_CLASS; - v_new = PyLong_FromLong(flags); - if (!v_new) { - goto error; - } - if (PyDict_SetItem(symbols, name, v_new) < 0) { - Py_DECREF(v_new); - goto error; - } - Py_DECREF(v_new); - } - /* It's a cell, or already free in this scope */ - Py_DECREF(name); - continue; - } - /* Handle global symbol */ - if (!PySet_Contains(bound, name)) { - Py_DECREF(name); - continue; /* it's a global */ - } - /* Propagate new free symbol up the lexical stack */ - if (PyDict_SetItem(symbols, name, v_free) < 0) { - goto error; - } - Py_DECREF(name); + PyObject *name = NULL, *itr = NULL; + PyObject *v = NULL, *v_scope = NULL, *v_new = NULL, *v_free = NULL; + Py_ssize_t pos = 0; + + /* Update scope information for all symbols in this scope */ + while (PyDict_Next(symbols, &pos, &name, &v)) { + long scope, flags; + assert(PyLong_Check(v)); + flags = PyLong_AS_LONG(v); + v_scope = PyDict_GetItem(scopes, name); + assert(v_scope && PyLong_Check(v_scope)); + scope = PyLong_AS_LONG(v_scope); + flags |= (scope << SCOPE_OFFSET); + v_new = PyLong_FromLong(flags); + if (!v_new) + return 0; + if (PyDict_SetItem(symbols, name, v_new) < 0) { + Py_DECREF(v_new); + return 0; } - Py_DECREF(itr); - Py_DECREF(v_free); - return 1; + Py_DECREF(v_new); + } + + /* Record not yet resolved free variables from children (if any) */ + v_free = PyLong_FromLong(FREE << SCOPE_OFFSET); + if (!v_free) + return 0; + + itr = PyObject_GetIter(free); + if (!itr) + goto error; + + while ((name = PyIter_Next(itr))) { + v = PyDict_GetItem(symbols, name); + + /* Handle symbol that already exists in this scope */ + if (v) { + /* Handle 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 && + PyLong_AS_LONG(v) & (DEF_BOUND | DEF_GLOBAL)) { + long flags = PyLong_AS_LONG(v) | DEF_FREE_CLASS; + v_new = PyLong_FromLong(flags); + if (!v_new) { + goto error; + } + if (PyDict_SetItem(symbols, name, v_new) < 0) { + Py_DECREF(v_new); + goto error; + } + Py_DECREF(v_new); + } + /* It's a cell, or already free in this scope */ + Py_DECREF(name); + continue; + } + /* Handle global symbol */ + if (!PySet_Contains(bound, name)) { + Py_DECREF(name); + continue; /* it's a global */ + } + /* Propagate new free symbol up the lexical stack */ + if (PyDict_SetItem(symbols, name, v_free) < 0) { + goto error; + } + Py_DECREF(name); + } + Py_DECREF(itr); + Py_DECREF(v_free); + return 1; error: - Py_XDECREF(v_free); - Py_XDECREF(itr); - Py_XDECREF(name); - return 0; -} + Py_XDECREF(v_free); + Py_XDECREF(itr); + Py_XDECREF(name); + return 0; +} /* Make final symbol table decisions for block of ste. @@ -647,238 +647,238 @@ error: */ static int -analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free, - PyObject *global, PyObject* child_free); +analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free, + PyObject *global, PyObject* child_free); static int -analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, - PyObject *global) +analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, + PyObject *global) { - PyObject *name, *v, *local = NULL, *scopes = NULL, *newbound = NULL; - PyObject *newglobal = NULL, *newfree = NULL, *allfree = NULL; - PyObject *temp; - int i, success = 0; - Py_ssize_t pos = 0; - - local = PySet_New(NULL); /* collect new names bound in block */ - if (!local) - goto error; - scopes = PyDict_New(); /* collect scopes defined for each name */ - if (!scopes) - goto error; - - /* Allocate new global and bound variable dictionaries. These - dictionaries hold the names visible in nested blocks. For - ClassBlocks, the bound and global names are initialized - before analyzing names, because class bindings aren't - visible in methods. For other blocks, they are initialized - after names are analyzed. - */ - - /* TODO(jhylton): Package these dicts in a struct so that we - can write reasonable helper functions? - */ - newglobal = PySet_New(NULL); - if (!newglobal) - goto error; - newfree = PySet_New(NULL); - if (!newfree) - goto error; - newbound = PySet_New(NULL); - if (!newbound) - goto error; - - /* Class namespace has no effect on names visible in - nested functions, so populate the global and bound - sets to be passed to child blocks before analyzing - this one. - */ - if (ste->ste_type == ClassBlock) { - /* Pass down known globals */ - temp = PyNumber_InPlaceOr(newglobal, global); - if (!temp) - goto error; - Py_DECREF(temp); - /* Pass down previously bound symbols */ - if (bound) { - temp = PyNumber_InPlaceOr(newbound, bound); - if (!temp) - goto error; - Py_DECREF(temp); - } - } - - while (PyDict_Next(ste->ste_symbols, &pos, &name, &v)) { - long flags = PyLong_AS_LONG(v); - if (!analyze_name(ste, scopes, name, flags, - bound, local, free, global)) - goto error; - } - - /* Populate global and bound sets to be passed to children. */ - if (ste->ste_type != ClassBlock) { - /* Add function locals to bound set */ - if (ste->ste_type == FunctionBlock) { - temp = PyNumber_InPlaceOr(newbound, local); - if (!temp) - goto error; - Py_DECREF(temp); - } - /* Pass down previously bound symbols */ - if (bound) { - temp = PyNumber_InPlaceOr(newbound, bound); - if (!temp) - goto error; - Py_DECREF(temp); - } - /* Pass down known globals */ - temp = PyNumber_InPlaceOr(newglobal, global); - if (!temp) - goto error; - Py_DECREF(temp); - } - else { - /* Special-case __class__ */ - if (!GET_IDENTIFIER(__class__)) - goto error; - assert(PySet_Contains(local, __class__) == 1); - if (PySet_Add(newbound, __class__) < 0) - goto error; - } - - /* Recursively call analyze_block() on each child block. - - newbound, newglobal now contain the names visible in - nested blocks. The free variables in the children will - be collected in allfree. - */ - allfree = PySet_New(NULL); - if (!allfree) - goto error; - 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_child_block(entry, newbound, newfree, newglobal, - allfree)) - goto error; - /* Check if any children have free variables */ - if (entry->ste_free || entry->ste_child_free) - ste->ste_child_free = 1; - } - - temp = PyNumber_InPlaceOr(newfree, allfree); - if (!temp) - goto error; - Py_DECREF(temp); - - /* Check if any local variables must be converted to cell variables */ - if (ste->ste_type == FunctionBlock && !analyze_cells(scopes, newfree, - NULL)) - goto error; - else if (ste->ste_type == ClassBlock && !analyze_cells(scopes, newfree, - "__class__")) - goto error; - /* Records the results of the analysis in the symbol table entry */ - if (!update_symbols(ste->ste_symbols, scopes, bound, newfree, - ste->ste_type == ClassBlock)) - goto error; - if (!check_unoptimized(ste)) - goto error; - - temp = PyNumber_InPlaceOr(free, newfree); - if (!temp) - goto error; - Py_DECREF(temp); - success = 1; + PyObject *name, *v, *local = NULL, *scopes = NULL, *newbound = NULL; + PyObject *newglobal = NULL, *newfree = NULL, *allfree = NULL; + PyObject *temp; + int i, success = 0; + Py_ssize_t pos = 0; + + local = PySet_New(NULL); /* collect new names bound in block */ + if (!local) + goto error; + scopes = PyDict_New(); /* collect scopes defined for each name */ + if (!scopes) + goto error; + + /* Allocate new global and bound variable dictionaries. These + dictionaries hold the names visible in nested blocks. For + ClassBlocks, the bound and global names are initialized + before analyzing names, because class bindings aren't + visible in methods. For other blocks, they are initialized + after names are analyzed. + */ + + /* TODO(jhylton): Package these dicts in a struct so that we + can write reasonable helper functions? + */ + newglobal = PySet_New(NULL); + if (!newglobal) + goto error; + newfree = PySet_New(NULL); + if (!newfree) + goto error; + newbound = PySet_New(NULL); + if (!newbound) + goto error; + + /* Class namespace has no effect on names visible in + nested functions, so populate the global and bound + sets to be passed to child blocks before analyzing + this one. + */ + if (ste->ste_type == ClassBlock) { + /* Pass down known globals */ + temp = PyNumber_InPlaceOr(newglobal, global); + if (!temp) + goto error; + Py_DECREF(temp); + /* Pass down previously bound symbols */ + if (bound) { + temp = PyNumber_InPlaceOr(newbound, bound); + if (!temp) + goto error; + Py_DECREF(temp); + } + } + + while (PyDict_Next(ste->ste_symbols, &pos, &name, &v)) { + long flags = PyLong_AS_LONG(v); + if (!analyze_name(ste, scopes, name, flags, + bound, local, free, global)) + goto error; + } + + /* Populate global and bound sets to be passed to children. */ + if (ste->ste_type != ClassBlock) { + /* Add function locals to bound set */ + if (ste->ste_type == FunctionBlock) { + temp = PyNumber_InPlaceOr(newbound, local); + if (!temp) + goto error; + Py_DECREF(temp); + } + /* Pass down previously bound symbols */ + if (bound) { + temp = PyNumber_InPlaceOr(newbound, bound); + if (!temp) + goto error; + Py_DECREF(temp); + } + /* Pass down known globals */ + temp = PyNumber_InPlaceOr(newglobal, global); + if (!temp) + goto error; + Py_DECREF(temp); + } + else { + /* Special-case __class__ */ + if (!GET_IDENTIFIER(__class__)) + goto error; + assert(PySet_Contains(local, __class__) == 1); + if (PySet_Add(newbound, __class__) < 0) + goto error; + } + + /* Recursively call analyze_block() on each child block. + + newbound, newglobal now contain the names visible in + nested blocks. The free variables in the children will + be collected in allfree. + */ + allfree = PySet_New(NULL); + if (!allfree) + goto error; + 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_child_block(entry, newbound, newfree, newglobal, + allfree)) + goto error; + /* Check if any children have free variables */ + if (entry->ste_free || entry->ste_child_free) + ste->ste_child_free = 1; + } + + temp = PyNumber_InPlaceOr(newfree, allfree); + if (!temp) + goto error; + Py_DECREF(temp); + + /* Check if any local variables must be converted to cell variables */ + if (ste->ste_type == FunctionBlock && !analyze_cells(scopes, newfree, + NULL)) + goto error; + else if (ste->ste_type == ClassBlock && !analyze_cells(scopes, newfree, + "__class__")) + goto error; + /* Records the results of the analysis in the symbol table entry */ + if (!update_symbols(ste->ste_symbols, scopes, bound, newfree, + ste->ste_type == ClassBlock)) + goto error; + if (!check_unoptimized(ste)) + goto error; + + temp = PyNumber_InPlaceOr(free, newfree); + if (!temp) + goto error; + Py_DECREF(temp); + success = 1; error: - Py_XDECREF(scopes); - Py_XDECREF(local); - Py_XDECREF(newbound); - Py_XDECREF(newglobal); - Py_XDECREF(newfree); - Py_XDECREF(allfree); - if (!success) - assert(PyErr_Occurred()); - return success; + Py_XDECREF(scopes); + Py_XDECREF(local); + Py_XDECREF(newbound); + Py_XDECREF(newglobal); + Py_XDECREF(newfree); + Py_XDECREF(allfree); + if (!success) + assert(PyErr_Occurred()); + return success; } static int -analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free, - PyObject *global, PyObject* child_free) +analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free, + PyObject *global, PyObject* child_free) { - PyObject *temp_bound = NULL, *temp_global = NULL, *temp_free = NULL; - PyObject *temp; - - /* Copy the bound and global dictionaries. - - These dictionary are used by all blocks enclosed by the - current block. The analyze_block() call modifies these - dictionaries. - - */ - temp_bound = PySet_New(bound); - if (!temp_bound) - goto error; - temp_free = PySet_New(free); - if (!temp_free) - goto error; - temp_global = PySet_New(global); - if (!temp_global) - goto error; - - if (!analyze_block(entry, temp_bound, temp_free, temp_global)) - goto error; - temp = PyNumber_InPlaceOr(child_free, temp_free); - if (!temp) - goto error; - Py_DECREF(temp); - Py_DECREF(temp_bound); - Py_DECREF(temp_free); - Py_DECREF(temp_global); - return 1; + PyObject *temp_bound = NULL, *temp_global = NULL, *temp_free = NULL; + PyObject *temp; + + /* Copy the bound and global dictionaries. + + These dictionary are used by all blocks enclosed by the + current block. The analyze_block() call modifies these + dictionaries. + + */ + temp_bound = PySet_New(bound); + if (!temp_bound) + goto error; + temp_free = PySet_New(free); + if (!temp_free) + goto error; + temp_global = PySet_New(global); + if (!temp_global) + goto error; + + if (!analyze_block(entry, temp_bound, temp_free, temp_global)) + goto error; + temp = PyNumber_InPlaceOr(child_free, temp_free); + if (!temp) + goto error; + Py_DECREF(temp); + Py_DECREF(temp_bound); + Py_DECREF(temp_free); + Py_DECREF(temp_global); + return 1; error: - Py_XDECREF(temp_bound); - Py_XDECREF(temp_free); - Py_XDECREF(temp_global); - return 0; + Py_XDECREF(temp_bound); + Py_XDECREF(temp_free); + Py_XDECREF(temp_global); + return 0; } static int symtable_analyze(struct symtable *st) { - PyObject *free, *global; - int r; - - free = PySet_New(NULL); - if (!free) - return 0; - global = PySet_New(NULL); - if (!global) { - Py_DECREF(free); - return 0; - } - r = analyze_block(st->st_top, NULL, free, global); - Py_DECREF(free); - Py_DECREF(global); - return r; + PyObject *free, *global; + int r; + + free = PySet_New(NULL); + if (!free) + return 0; + global = PySet_New(NULL); + 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; + 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 ste_new. @@ -889,792 +889,792 @@ symtable_warn(struct symtable *st, char *msg, int lineno) 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; + 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) +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 = ste_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; + 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 = ste_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 PyLong_AsLong(o); + 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 PyLong_AsLong(o); } static int -symtable_add_def(struct symtable *st, PyObject *name, int flag) +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 = PyLong_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, name); - PyErr_SyntaxLocation(st->st_filename, - st->st_cur->ste_lineno); - goto error; - } - val |= flag; - } else - val = flag; - o = PyLong_FromLong(val); + 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 = PyLong_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, name); + PyErr_SyntaxLocation(st->st_filename, + st->st_cur->ste_lineno); + goto error; + } + val |= flag; + } else + val = flag; + o = PyLong_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 |= PyLong_AS_LONG(o); + } + o = PyLong_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 |= PyLong_AS_LONG(o); - } - o = PyLong_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; + 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; + 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. - + 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; + 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; \ - } + 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; \ - } \ + 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; \ - } \ - } \ + 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; \ - } \ + 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; \ - } \ - } \ + 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; \ + } \ + } \ } #define VISIT_KWONLYDEFAULTS(ST, KW_DEFAULTS) { \ - int i = 0; \ - asdl_seq *seq = (KW_DEFAULTS); /* avoid variable capture */ \ - for (i = 0; i < asdl_seq_LEN(seq); i++) { \ - expr_ty elt = (expr_ty)asdl_seq_GET(seq, i); \ - if (!elt) continue; /* can be NULL */ \ - if (!symtable_visit_expr((ST), elt)) \ - return 0; \ - } \ + int i = 0; \ + asdl_seq *seq = (KW_DEFAULTS); /* avoid variable capture */ \ + for (i = 0; i < asdl_seq_LEN(seq); i++) { \ + expr_ty elt = (expr_ty)asdl_seq_GET(seq, i); \ + if (!elt) continue; /* can be NULL */ \ + if (!symtable_visit_expr((ST), elt)) \ + 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 = PyUnicode_InternFromString(tmpname); - if (!tmp) - return 0; - if (!symtable_add_def(st, tmp, DEF_LOCAL)) - return 0; - Py_DECREF(tmp); - return 1; + char tmpname[256]; + identifier tmp; + + PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]", + ++st->st_cur->ste_tmpname); + tmp = PyUnicode_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.args->kw_defaults) - VISIT_KWONLYDEFAULTS(st, - s->v.FunctionDef.args->kw_defaults); - if (!symtable_visit_annotations(st, s)) - return 0; - if (s->v.FunctionDef.decorator_list) - VISIT_SEQ(st, expr, s->v.FunctionDef.decorator_list); - 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); - VISIT_SEQ(st, keyword, s->v.ClassDef.keywords); - if (s->v.ClassDef.starargs) - VISIT(st, expr, s->v.ClassDef.starargs); - if (s->v.ClassDef.kwargs) - VISIT(st, expr, s->v.ClassDef.kwargs); - if (s->v.ClassDef.decorator_list) - VISIT_SEQ(st, expr, s->v.ClassDef.decorator_list); - if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock, - (void *)s, s->lineno)) - return 0; - if (!GET_IDENTIFIER(__class__) || - !symtable_add_def(st, __class__, DEF_LOCAL) || - !GET_IDENTIFIER(__locals__) || - !symtable_add_def(st, __locals__, DEF_PARAM)) { - symtable_exit_block(st, s); - 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 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.exc) { - VISIT(st, expr, s->v.Raise.exc); - if (s->v.Raise.cause) { - VISIT(st, expr, s->v.Raise.cause); + 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.args->kw_defaults) + VISIT_KWONLYDEFAULTS(st, + s->v.FunctionDef.args->kw_defaults); + if (!symtable_visit_annotations(st, s)) + return 0; + if (s->v.FunctionDef.decorator_list) + VISIT_SEQ(st, expr, s->v.FunctionDef.decorator_list); + 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); + VISIT_SEQ(st, keyword, s->v.ClassDef.keywords); + if (s->v.ClassDef.starargs) + VISIT(st, expr, s->v.ClassDef.starargs); + if (s->v.ClassDef.kwargs) + VISIT(st, expr, s->v.ClassDef.kwargs); + if (s->v.ClassDef.decorator_list) + VISIT_SEQ(st, expr, s->v.ClassDef.decorator_list); + if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock, + (void *)s, s->lineno)) + return 0; + if (!GET_IDENTIFIER(__class__) || + !symtable_add_def(st, __class__, DEF_LOCAL) || + !GET_IDENTIFIER(__locals__) || + !symtable_add_def(st, __locals__, DEF_PARAM)) { + symtable_exit_block(st, s); + 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 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 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 = _PyUnicode_AsString(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 Nonlocal_kind: { - int i; - asdl_seq *seq = s->v.Nonlocal.names; - for (i = 0; i < asdl_seq_LEN(seq); i++) { - identifier name = (identifier)asdl_seq_GET(seq, i); - char *c_name = _PyUnicode_AsString(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), - NONLOCAL_AFTER_ASSIGN, - c_name); - else - PyOS_snprintf(buf, sizeof(buf), - NONLOCAL_AFTER_USE, - c_name); - if (!symtable_warn(st, buf, s->lineno)) - return 0; - } - if (!symtable_add_def(st, name, DEF_NONLOCAL)) - 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: - VISIT(st, expr, s->v.With.context_expr); - if (s->v.With.optional_vars) { - VISIT(st, expr, s->v.With.optional_vars); - } - VISIT_SEQ(st, stmt, s->v.With.body); - break; - } - return 1; + } + 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 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.exc) { + VISIT(st, expr, s->v.Raise.exc); + if (s->v.Raise.cause) { + VISIT(st, expr, s->v.Raise.cause); + } + } + 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 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 = _PyUnicode_AsString(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 Nonlocal_kind: { + int i; + asdl_seq *seq = s->v.Nonlocal.names; + for (i = 0; i < asdl_seq_LEN(seq); i++) { + identifier name = (identifier)asdl_seq_GET(seq, i); + char *c_name = _PyUnicode_AsString(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), + NONLOCAL_AFTER_ASSIGN, + c_name); + else + PyOS_snprintf(buf, sizeof(buf), + NONLOCAL_AFTER_USE, + c_name); + if (!symtable_warn(st, buf, s->lineno)) + return 0; + } + if (!symtable_add_def(st, name, DEF_NONLOCAL)) + 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: + VISIT(st, expr, s->v.With.context_expr); + if (s->v.With.optional_vars) { + VISIT(st, expr, s->v.With.optional_vars); + } + VISIT_SEQ(st, stmt, s->v.With.body); + break; + } + return 1; } -static int +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 (!GET_IDENTIFIER(lambda)) - return 0; - if (e->v.Lambda.args->defaults) - VISIT_SEQ(st, expr, e->v.Lambda.args->defaults); - if (!symtable_enter_block(st, lambda, - FunctionBlock, (void *)e, e->lineno)) - 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 Set_kind: - VISIT_SEQ(st, expr, e->v.Set.elts); - break; - case GeneratorExp_kind: - if (!symtable_visit_genexp(st, e)) - return 0; - break; - case ListComp_kind: - if (!symtable_visit_listcomp(st, e)) - return 0; - break; - case SetComp_kind: - if (!symtable_visit_setcomp(st, e)) - return 0; - break; - case DictComp_kind: - if (!symtable_visit_dictcomp(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 Num_kind: - case Str_kind: - case Bytes_kind: - case Ellipsis_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 Starred_kind: - VISIT(st, expr, e->v.Starred.value); - break; - case Name_kind: - if (!symtable_add_def(st, e->v.Name.id, - e->v.Name.ctx == Load ? USE : DEF_LOCAL)) - return 0; - /* Special-case super: it counts as a use of __class__ */ - if (e->v.Name.ctx == Load && - st->st_cur->ste_type == FunctionBlock && - !PyUnicode_CompareWithASCIIString(e->v.Name.id, "super")) { - if (!GET_IDENTIFIER(__class__) || - !symtable_add_def(st, __class__, USE)) - 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; + 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 (!GET_IDENTIFIER(lambda)) + return 0; + if (e->v.Lambda.args->defaults) + VISIT_SEQ(st, expr, e->v.Lambda.args->defaults); + if (!symtable_enter_block(st, lambda, + FunctionBlock, (void *)e, e->lineno)) + 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 Set_kind: + VISIT_SEQ(st, expr, e->v.Set.elts); + break; + case GeneratorExp_kind: + if (!symtable_visit_genexp(st, e)) + return 0; + break; + case ListComp_kind: + if (!symtable_visit_listcomp(st, e)) + return 0; + break; + case SetComp_kind: + if (!symtable_visit_setcomp(st, e)) + return 0; + break; + case DictComp_kind: + if (!symtable_visit_dictcomp(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 Num_kind: + case Str_kind: + case Bytes_kind: + case Ellipsis_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 Starred_kind: + VISIT(st, expr, e->v.Starred.value); + break; + case Name_kind: + if (!symtable_add_def(st, e->v.Name.id, + e->v.Name.ctx == Load ? USE : DEF_LOCAL)) + return 0; + /* Special-case super: it counts as a use of __class__ */ + if (e->v.Name.ctx == Load && + st->st_cur->ste_type == FunctionBlock && + !PyUnicode_CompareWithASCIIString(e->v.Name.id, "super")) { + if (!GET_IDENTIFIER(__class__) || + !symtable_add_def(st, __class__, USE)) + 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 = PyUnicode_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; + PyObject *id = PyUnicode_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 +static int symtable_visit_params(struct symtable *st, asdl_seq *args) { - int i; - - if (!args) - return -1; - - for (i = 0; i < asdl_seq_LEN(args); i++) { - arg_ty arg = (arg_ty)asdl_seq_GET(args, i); - if (!symtable_add_def(st, arg->arg, DEF_PARAM)) - return 0; - } - - return 1; + int i; + + if (!args) + return -1; + + for (i = 0; i < asdl_seq_LEN(args); i++) { + arg_ty arg = (arg_ty)asdl_seq_GET(args, i); + if (!symtable_add_def(st, arg->arg, DEF_PARAM)) + return 0; + } + + return 1; } -static int +static int symtable_visit_argannotations(struct symtable *st, asdl_seq *args) { - int i; - - if (!args) - return -1; - - for (i = 0; i < asdl_seq_LEN(args); i++) { - arg_ty arg = (arg_ty)asdl_seq_GET(args, i); - if (arg->annotation) - VISIT(st, expr, arg->annotation); - } - - return 1; + int i; + + if (!args) + return -1; + + for (i = 0; i < asdl_seq_LEN(args); i++) { + arg_ty arg = (arg_ty)asdl_seq_GET(args, i); + if (arg->annotation) + VISIT(st, expr, arg->annotation); + } + + return 1; } static int symtable_visit_annotations(struct symtable *st, stmt_ty s) { - arguments_ty a = s->v.FunctionDef.args; - - if (a->args && !symtable_visit_argannotations(st, a->args)) - return 0; - if (a->varargannotation) - VISIT(st, expr, a->varargannotation); - if (a->kwargannotation) - VISIT(st, expr, a->kwargannotation); - if (a->kwonlyargs && !symtable_visit_argannotations(st, a->kwonlyargs)) - return 0; - if (s->v.FunctionDef.returns) - VISIT(st, expr, s->v.FunctionDef.returns); - return 1; + arguments_ty a = s->v.FunctionDef.args; + + if (a->args && !symtable_visit_argannotations(st, a->args)) + return 0; + if (a->varargannotation) + VISIT(st, expr, a->varargannotation); + if (a->kwargannotation) + VISIT(st, expr, a->kwargannotation); + if (a->kwonlyargs && !symtable_visit_argannotations(st, a->kwonlyargs)) + return 0; + if (s->v.FunctionDef.returns) + VISIT(st, expr, s->v.FunctionDef.returns); + return 1; } -static int +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)) - return 0; - if (a->kwonlyargs && !symtable_visit_params(st, a->kwonlyargs)) - 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; - } - return 1; + /* skip default arguments inside function block + XXX should ast be different? + */ + if (a->args && !symtable_visit_params(st, a->args)) + return 0; + if (a->kwonlyargs && !symtable_visit_params(st, a->kwonlyargs)) + 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; + } + return 1; } -static int +static int symtable_visit_excepthandler(struct symtable *st, excepthandler_ty eh) { - if (eh->v.ExceptHandler.type) - VISIT(st, expr, eh->v.ExceptHandler.type); - if (eh->v.ExceptHandler.name) - if (!symtable_add_def(st, eh->v.ExceptHandler.name, DEF_LOCAL)) - return 0; - VISIT_SEQ(st, stmt, eh->v.ExceptHandler.body); - return 1; + if (eh->v.ExceptHandler.type) + VISIT(st, expr, eh->v.ExceptHandler.type); + if (eh->v.ExceptHandler.name) + if (!symtable_add_def(st, eh->v.ExceptHandler.name, DEF_LOCAL)) + return 0; + VISIT_SEQ(st, stmt, eh->v.ExceptHandler.body); + return 1; } -static int +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 Py_UNICODE *base = PyUnicode_AS_UNICODE(name); - Py_UNICODE *dot = Py_UNICODE_strchr(base, '.'); - if (dot) { - store_name = PyUnicode_FromUnicode(base, dot - base); - if (!store_name) - return 0; - } - else { - store_name = name; - Py_INCREF(store_name); - } - if (PyUnicode_CompareWithASCIIString(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; - PyErr_SetString(PyExc_SyntaxError, IMPORT_STAR_WARNING); - PyErr_SyntaxLocation(st->st_filename, lineno); - Py_DECREF(store_name); - return 0; - } - st->st_cur->ste_unoptimized |= OPT_IMPORT_STAR; - Py_DECREF(store_name); - return 1; - } + /* 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 Py_UNICODE *base = PyUnicode_AS_UNICODE(name); + Py_UNICODE *dot = Py_UNICODE_strchr(base, '.'); + if (dot) { + store_name = PyUnicode_FromUnicode(base, dot - base); + if (!store_name) + return 0; + } + else { + store_name = name; + Py_INCREF(store_name); + } + if (PyUnicode_CompareWithASCIIString(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; + PyErr_SetString(PyExc_SyntaxError, IMPORT_STAR_WARNING); + PyErr_SyntaxLocation(st->st_filename, lineno); + Py_DECREF(store_name); + return 0; + } + st->st_cur->ste_unoptimized |= OPT_IMPORT_STAR; + Py_DECREF(store_name); + return 1; + } } -static int +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; + VISIT(st, expr, lc->target); + VISIT(st, expr, lc->iter); + VISIT_SEQ(st, expr, lc->ifs); + return 1; } -static int +static int symtable_visit_keyword(struct symtable *st, keyword_ty k) { - VISIT(st, expr, k->value); - return 1; + VISIT(st, expr, k->value); + return 1; } -static int +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; - } - return 1; + 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; + } + return 1; } -static int +static int symtable_handle_comprehension(struct symtable *st, expr_ty e, identifier scope_name, asdl_seq *generators, expr_ty elt, expr_ty value) { - int is_generator = (e->kind == GeneratorExp_kind); - int needs_tmp = !is_generator; - comprehension_ty outermost = ((comprehension_ty) - asdl_seq_GET(generators, 0)); - /* Outermost iterator is evaluated in current scope */ - VISIT(st, expr, outermost->iter); - /* Create comprehension scope for the rest */ - if (!scope_name || - !symtable_enter_block(st, scope_name, FunctionBlock, (void *)e, e->lineno)) { - return 0; - } - st->st_cur->ste_generator = is_generator; - /* Outermost iter is received as an argument */ - if (!symtable_implicit_arg(st, 0)) { - symtable_exit_block(st, (void *)e); - return 0; - } - /* Allocate temporary name if needed */ - if (needs_tmp && !symtable_new_tmpname(st)) { - 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, - generators, 1, (void*)e); - if (value) - VISIT_IN_BLOCK(st, expr, value, (void*)e); - VISIT_IN_BLOCK(st, expr, elt, (void*)e); - return symtable_exit_block(st, (void *)e); + int is_generator = (e->kind == GeneratorExp_kind); + int needs_tmp = !is_generator; + comprehension_ty outermost = ((comprehension_ty) + asdl_seq_GET(generators, 0)); + /* Outermost iterator is evaluated in current scope */ + VISIT(st, expr, outermost->iter); + /* Create comprehension scope for the rest */ + if (!scope_name || + !symtable_enter_block(st, scope_name, FunctionBlock, (void *)e, e->lineno)) { + return 0; + } + st->st_cur->ste_generator = is_generator; + /* Outermost iter is received as an argument */ + if (!symtable_implicit_arg(st, 0)) { + symtable_exit_block(st, (void *)e); + return 0; + } + /* Allocate temporary name if needed */ + if (needs_tmp && !symtable_new_tmpname(st)) { + 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, + generators, 1, (void*)e); + if (value) + VISIT_IN_BLOCK(st, expr, value, (void*)e); + VISIT_IN_BLOCK(st, expr, elt, (void*)e); + return symtable_exit_block(st, (void *)e); } -static int +static int symtable_visit_genexp(struct symtable *st, expr_ty e) { - return symtable_handle_comprehension(st, e, GET_IDENTIFIER(genexpr), - e->v.GeneratorExp.generators, - e->v.GeneratorExp.elt, NULL); + return symtable_handle_comprehension(st, e, GET_IDENTIFIER(genexpr), + e->v.GeneratorExp.generators, + e->v.GeneratorExp.elt, NULL); } -static int +static int symtable_visit_listcomp(struct symtable *st, expr_ty e) { - return symtable_handle_comprehension(st, e, GET_IDENTIFIER(listcomp), - e->v.ListComp.generators, - e->v.ListComp.elt, NULL); + return symtable_handle_comprehension(st, e, GET_IDENTIFIER(listcomp), + e->v.ListComp.generators, + e->v.ListComp.elt, NULL); } static int symtable_visit_setcomp(struct symtable *st, expr_ty e) { - return symtable_handle_comprehension(st, e, GET_IDENTIFIER(setcomp), - e->v.SetComp.generators, - e->v.SetComp.elt, NULL); + return symtable_handle_comprehension(st, e, GET_IDENTIFIER(setcomp), + e->v.SetComp.generators, + e->v.SetComp.elt, NULL); } static int symtable_visit_dictcomp(struct symtable *st, expr_ty e) { - return symtable_handle_comprehension(st, e, GET_IDENTIFIER(dictcomp), - e->v.DictComp.generators, - e->v.DictComp.key, - e->v.DictComp.value); + return symtable_handle_comprehension(st, e, GET_IDENTIFIER(dictcomp), + e->v.DictComp.generators, + e->v.DictComp.key, + e->v.DictComp.value); } diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 8267369584..ac14751506 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -45,63 +45,63 @@ extern const char *PyWin_DLLVersionString; PyObject * PySys_GetObject(const char *name) { - PyThreadState *tstate = PyThreadState_GET(); - PyObject *sd = tstate->interp->sysdict; - if (sd == NULL) - return NULL; - return PyDict_GetItemString(sd, name); + PyThreadState *tstate = PyThreadState_GET(); + PyObject *sd = tstate->interp->sysdict; + if (sd == NULL) + return NULL; + return PyDict_GetItemString(sd, name); } int PySys_SetObject(const 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); + 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, "builtins"); - - if (builtins == NULL) { - PyErr_SetString(PyExc_RuntimeError, "lost builtins module"); - 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; - outf = PySys_GetObject("stdout"); - if (outf == NULL || outf == Py_None) { - PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout"); - return NULL; - } - if (PyFile_WriteObject(o, outf, 0) != 0) - return NULL; - if (PyFile_WriteString("\n", outf) != 0) - return NULL; - if (PyObject_SetAttrString(builtins, "_", o) != 0) - return NULL; - Py_INCREF(Py_None); - return Py_None; + PyObject *outf; + PyInterpreterState *interp = PyThreadState_GET()->interp; + PyObject *modules = interp->modules; + PyObject *builtins = PyDict_GetItemString(modules, "builtins"); + + if (builtins == NULL) { + PyErr_SetString(PyExc_RuntimeError, "lost builtins module"); + 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; + outf = PySys_GetObject("stdout"); + if (outf == NULL || outf == Py_None) { + PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout"); + return NULL; + } + if (PyFile_WriteObject(o, outf, 0) != 0) + return NULL; + if (PyFile_WriteString("\n", outf) != 0) + return NULL; + if (PyObject_SetAttrString(builtins, "_", o) != 0) + return NULL; + Py_INCREF(Py_None); + return Py_None; } PyDoc_STRVAR(displayhook_doc, @@ -113,12 +113,12 @@ PyDoc_STRVAR(displayhook_doc, 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; + 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, @@ -130,14 +130,14 @@ PyDoc_STRVAR(excepthook_doc, 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); + 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, @@ -150,12 +150,12 @@ clause in the current stack frame or in an older stack frame." 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; + 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, @@ -172,7 +172,7 @@ exit status will be one (i.e., failure)." static PyObject * sys_getdefaultencoding(PyObject *self) { - return PyUnicode_FromString(PyUnicode_GetDefaultEncoding()); + return PyUnicode_FromString(PyUnicode_GetDefaultEncoding()); } PyDoc_STRVAR(getdefaultencoding_doc, @@ -185,13 +185,13 @@ 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; + 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, @@ -203,10 +203,10 @@ Set the current default string encoding used by the Unicode implementation." static PyObject * sys_getfilesystemencoding(PyObject *self) { - if (Py_FileSystemDefaultEncoding) - return PyUnicode_FromString(Py_FileSystemDefaultEncoding); - Py_INCREF(Py_None); - return Py_None; + if (Py_FileSystemDefaultEncoding) + return PyUnicode_FromString(Py_FileSystemDefaultEncoding); + Py_INCREF(Py_None); + return Py_None; } PyDoc_STRVAR(getfilesystemencoding_doc, @@ -219,13 +219,13 @@ operating system filenames." static PyObject * sys_setfilesystemencoding(PyObject *self, PyObject *args) { - PyObject *new_encoding; - if (!PyArg_ParseTuple(args, "U:setfilesystemencoding", &new_encoding)) - return NULL; - if (_Py_SetFileSystemEncoding(new_encoding)) - return NULL; - Py_INCREF(Py_None); - return Py_None; + PyObject *new_encoding; + if (!PyArg_ParseTuple(args, "U:setfilesystemencoding", &new_encoding)) + return NULL; + if (_Py_SetFileSystemEncoding(new_encoding)) + return NULL; + Py_INCREF(Py_None); + return Py_None; } PyDoc_STRVAR(setfilesystemencoding_doc, @@ -238,19 +238,19 @@ operating system filenames." static PyObject * sys_intern(PyObject *self, PyObject *args) { - PyObject *s; - if (!PyArg_ParseTuple(args, "U:intern", &s)) - return NULL; - if (PyUnicode_CheckExact(s)) { - Py_INCREF(s); - PyUnicode_InternInPlace(&s); - return s; - } - else { - PyErr_Format(PyExc_TypeError, - "can't intern %.400s", s->ob_type->tp_name); - return NULL; - } + PyObject *s; + if (!PyArg_ParseTuple(args, "U:intern", &s)) + return NULL; + if (PyUnicode_CheckExact(s)) { + Py_INCREF(s); + PyUnicode_InternInPlace(&s); + return s; + } + else { + PyErr_Format(PyExc_TypeError, + "can't intern %.400s", s->ob_type->tp_name); + return NULL; + } } PyDoc_STRVAR(intern_doc, @@ -271,116 +271,116 @@ 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 = PyUnicode_InternFromString(whatnames[i]); - if (name == NULL) - return -1; - whatstrings[i] = name; - } - } - return 0; + 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 = PyUnicode_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) + 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; + 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) + 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; + 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) + 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; + 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; + 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, @@ -393,13 +393,13 @@ function call. See the debugger chapter in the library manual." static PyObject * sys_gettrace(PyObject *self, PyObject *args) { - PyThreadState *tstate = PyThreadState_GET(); - PyObject *temp = tstate->c_traceobj; + PyThreadState *tstate = PyThreadState_GET(); + PyObject *temp = tstate->c_traceobj; - if (temp == NULL) - temp = Py_None; - Py_INCREF(temp); - return temp; + if (temp == NULL) + temp = Py_None; + Py_INCREF(temp); + return temp; } PyDoc_STRVAR(gettrace_doc, @@ -412,14 +412,14 @@ 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; + 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, @@ -432,13 +432,13 @@ and return. See the profiler chapter in the library manual." static PyObject * sys_getprofile(PyObject *self, PyObject *args) { - PyThreadState *tstate = PyThreadState_GET(); - PyObject *temp = tstate->c_profileobj; + PyThreadState *tstate = PyThreadState_GET(); + PyObject *temp = tstate->c_profileobj; - if (temp == NULL) - temp = Py_None; - Py_INCREF(temp); - return temp; + if (temp == NULL) + temp = Py_None; + Py_INCREF(temp); + return temp; } PyDoc_STRVAR(getprofile_doc, @@ -453,15 +453,15 @@ static int _check_interval = 100; static PyObject * sys_setcheckinterval(PyObject *self, PyObject *args) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "sys.getcheckinterval() and sys.setcheckinterval() " - "are deprecated. Use sys.setswitchinterval() " - "instead.", 1) < 0) - return NULL; - if (!PyArg_ParseTuple(args, "i:setcheckinterval", &_check_interval)) - return NULL; - Py_INCREF(Py_None); - return Py_None; + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "sys.getcheckinterval() and sys.setcheckinterval() " + "are deprecated. Use sys.setswitchinterval() " + "instead.", 1) < 0) + return NULL; + if (!PyArg_ParseTuple(args, "i:setcheckinterval", &_check_interval)) + return NULL; + Py_INCREF(Py_None); + return Py_None; } PyDoc_STRVAR(setcheckinterval_doc, @@ -474,12 +474,12 @@ n instructions. This also affects how often thread switches occur." static PyObject * sys_getcheckinterval(PyObject *self, PyObject *args) { - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "sys.getcheckinterval() and sys.setcheckinterval() " - "are deprecated. Use sys.getswitchinterval() " - "instead.", 1) < 0) - return NULL; - return PyLong_FromLong(_check_interval); + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "sys.getcheckinterval() and sys.setcheckinterval() " + "are deprecated. Use sys.getswitchinterval() " + "instead.", 1) < 0) + return NULL; + return PyLong_FromLong(_check_interval); } PyDoc_STRVAR(getcheckinterval_doc, @@ -490,17 +490,17 @@ PyDoc_STRVAR(getcheckinterval_doc, static PyObject * sys_setswitchinterval(PyObject *self, PyObject *args) { - double d; - if (!PyArg_ParseTuple(args, "d:setswitchinterval", &d)) - return NULL; - if (d <= 0.0) { - PyErr_SetString(PyExc_ValueError, - "switch interval must be strictly positive"); - return NULL; - } - _PyEval_SetSwitchInterval((unsigned long) (1e6 * d)); - Py_INCREF(Py_None); - return Py_None; + double d; + if (!PyArg_ParseTuple(args, "d:setswitchinterval", &d)) + return NULL; + if (d <= 0.0) { + PyErr_SetString(PyExc_ValueError, + "switch interval must be strictly positive"); + return NULL; + } + _PyEval_SetSwitchInterval((unsigned long) (1e6 * d)); + Py_INCREF(Py_None); + return Py_None; } PyDoc_STRVAR(setswitchinterval_doc, @@ -518,7 +518,7 @@ A typical value is 0.005 (5 milliseconds)." static PyObject * sys_getswitchinterval(PyObject *self, PyObject *args) { - return PyFloat_FromDouble(1e-6 * _PyEval_GetSwitchInterval()); + return PyFloat_FromDouble(1e-6 * _PyEval_GetSwitchInterval()); } PyDoc_STRVAR(getswitchinterval_doc, @@ -531,17 +531,17 @@ PyDoc_STRVAR(getswitchinterval_doc, 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; + 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; } @@ -557,17 +557,17 @@ processor's time-stamp counter." 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; + 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, @@ -582,7 +582,7 @@ dependent." static PyObject * sys_getrecursionlimit(PyObject *self) { - return PyLong_FromLong(Py_GetRecursionLimit()); + return PyLong_FromLong(Py_GetRecursionLimit()); } PyDoc_STRVAR(getrecursionlimit_doc, @@ -610,52 +610,52 @@ controller, 3 for a server." static PyTypeObject WindowsVersionType = {0, 0, 0, 0, 0, 0}; static PyStructSequence_Field windows_version_fields[] = { - {"major", "Major version number"}, - {"minor", "Minor version number"}, - {"build", "Build number"}, - {"platform", "Operating system platform"}, - {"service_pack", "Latest Service Pack installed on the system"}, - {"service_pack_major", "Service Pack major version number"}, - {"service_pack_minor", "Service Pack minor version number"}, - {"suite_mask", "Bit mask identifying available product suites"}, - {"product_type", "System product type"}, - {0} + {"major", "Major version number"}, + {"minor", "Minor version number"}, + {"build", "Build number"}, + {"platform", "Operating system platform"}, + {"service_pack", "Latest Service Pack installed on the system"}, + {"service_pack_major", "Service Pack major version number"}, + {"service_pack_minor", "Service Pack minor version number"}, + {"suite_mask", "Bit mask identifying available product suites"}, + {"product_type", "System product type"}, + {0} }; static PyStructSequence_Desc windows_version_desc = { - "sys.getwindowsversion", /* name */ - getwindowsversion_doc, /* doc */ - windows_version_fields, /* fields */ - 5 /* For backward compatibility, - only the first 5 items are accessible - via indexing, the rest are name only */ + "sys.getwindowsversion", /* name */ + getwindowsversion_doc, /* doc */ + windows_version_fields, /* fields */ + 5 /* For backward compatibility, + only the first 5 items are accessible + via indexing, the rest are name only */ }; static PyObject * sys_getwindowsversion(PyObject *self) { - PyObject *version; - int pos = 0; - OSVERSIONINFOEX ver; - ver.dwOSVersionInfoSize = sizeof(ver); - if (!GetVersionEx((OSVERSIONINFO*) &ver)) - return PyErr_SetFromWindowsErr(0); - - version = PyStructSequence_New(&WindowsVersionType); - if (version == NULL) - return NULL; - - PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwMajorVersion)); - PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwMinorVersion)); - PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwBuildNumber)); - PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwPlatformId)); - PyStructSequence_SET_ITEM(version, pos++, PyUnicode_FromString(ver.szCSDVersion)); - PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wServicePackMajor)); - PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wServicePackMinor)); - PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wSuiteMask)); - PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wProductType)); - - return version; + PyObject *version; + int pos = 0; + OSVERSIONINFOEX ver; + ver.dwOSVersionInfoSize = sizeof(ver); + if (!GetVersionEx((OSVERSIONINFO*) &ver)) + return PyErr_SetFromWindowsErr(0); + + version = PyStructSequence_New(&WindowsVersionType); + if (version == NULL) + return NULL; + + PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwMajorVersion)); + PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwMinorVersion)); + PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwBuildNumber)); + PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwPlatformId)); + PyStructSequence_SET_ITEM(version, pos++, PyUnicode_FromString(ver.szCSDVersion)); + PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wServicePackMajor)); + PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wServicePackMinor)); + PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wSuiteMask)); + PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wProductType)); + + return version; } #endif /* MS_WINDOWS */ @@ -664,15 +664,15 @@ sys_getwindowsversion(PyObject *self) 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; + 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, @@ -690,10 +690,10 @@ h2py script."); static PyObject * sys_getdlopenflags(PyObject *self, PyObject *args) { - PyThreadState *tstate = PyThreadState_GET(); - if (!tstate) - return NULL; - return PyLong_FromLong(tstate->interp->dlopenflags); + PyThreadState *tstate = PyThreadState_GET(); + if (!tstate) + return NULL; + return PyLong_FromLong(tstate->interp->dlopenflags); } PyDoc_STRVAR(getdlopenflags_doc, @@ -702,7 +702,7 @@ PyDoc_STRVAR(getdlopenflags_doc, Return the current value of the flags that are used for dlopen calls.\n\ The flag constants are defined in the ctypes and DLFCN modules."); -#endif /* HAVE_DLOPEN */ +#endif /* HAVE_DLOPEN */ #ifdef USE_MALLOPT /* Link with -lmalloc (or -lmpc) on an SGI */ @@ -711,70 +711,70 @@ The flag constants are defined in the ctypes and DLFCN modules."); 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; + 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_getsizeof(PyObject *self, PyObject *args, PyObject *kwds) { - PyObject *res = NULL; - static PyObject *str__sizeof__ = NULL, *gc_head_size = NULL; - static char *kwlist[] = {"object", "default", 0}; - PyObject *o, *dflt = NULL; - PyObject *method; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:getsizeof", - kwlist, &o, &dflt)) - return NULL; - - /* Initialize static variable for GC head size */ - if (gc_head_size == NULL) { - gc_head_size = PyLong_FromSsize_t(sizeof(PyGC_Head)); - if (gc_head_size == NULL) - return NULL; - } - - /* Make sure the type is initialized. float gets initialized late */ - if (PyType_Ready(Py_TYPE(o)) < 0) - return NULL; - - method = _PyObject_LookupSpecial(o, "__sizeof__", - &str__sizeof__); - if (method == NULL) { - if (!PyErr_Occurred()) - PyErr_Format(PyExc_TypeError, - "Type %.100s doesn't define __sizeof__", - Py_TYPE(o)->tp_name); - } - else { - res = PyObject_CallFunctionObjArgs(method, NULL); - Py_DECREF(method); - } - - /* Has a default value been given */ - if ((res == NULL) && (dflt != NULL) && - PyErr_ExceptionMatches(PyExc_TypeError)) - { - PyErr_Clear(); - Py_INCREF(dflt); - return dflt; - } - else if (res == NULL) - return res; - - /* add gc_head size */ - if (PyObject_IS_GC(o)) { - PyObject *tmp = res; - res = PyNumber_Add(tmp, gc_head_size); - Py_DECREF(tmp); - } - return res; + PyObject *res = NULL; + static PyObject *str__sizeof__ = NULL, *gc_head_size = NULL; + static char *kwlist[] = {"object", "default", 0}; + PyObject *o, *dflt = NULL; + PyObject *method; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:getsizeof", + kwlist, &o, &dflt)) + return NULL; + + /* Initialize static variable for GC head size */ + if (gc_head_size == NULL) { + gc_head_size = PyLong_FromSsize_t(sizeof(PyGC_Head)); + if (gc_head_size == NULL) + return NULL; + } + + /* Make sure the type is initialized. float gets initialized late */ + if (PyType_Ready(Py_TYPE(o)) < 0) + return NULL; + + method = _PyObject_LookupSpecial(o, "__sizeof__", + &str__sizeof__); + if (method == NULL) { + if (!PyErr_Occurred()) + PyErr_Format(PyExc_TypeError, + "Type %.100s doesn't define __sizeof__", + Py_TYPE(o)->tp_name); + } + else { + res = PyObject_CallFunctionObjArgs(method, NULL); + Py_DECREF(method); + } + + /* Has a default value been given */ + if ((res == NULL) && (dflt != NULL) && + PyErr_ExceptionMatches(PyExc_TypeError)) + { + PyErr_Clear(); + Py_INCREF(dflt); + return dflt; + } + else if (res == NULL) + return res; + + /* add gc_head size */ + if (PyObject_IS_GC(o)) { + PyObject *tmp = res; + res = PyNumber_Add(tmp, gc_head_size); + Py_DECREF(tmp); + } + return res; } PyDoc_STRVAR(getsizeof_doc, @@ -785,14 +785,14 @@ Return the size of object in bytes."); static PyObject * sys_getrefcount(PyObject *self, PyObject *arg) { - return PyLong_FromSsize_t(arg->ob_refcnt); + return PyLong_FromSsize_t(arg->ob_refcnt); } #ifdef Py_REF_DEBUG static PyObject * sys_gettotalrefcount(PyObject *self) { - return PyLong_FromSsize_t(_Py_GetRefTotal()); + return PyLong_FromSsize_t(_Py_GetRefTotal()); } #endif /* Py_REF_DEBUG */ @@ -808,9 +808,9 @@ reference as an argument to getrefcount()." static PyObject * sys_getcounts(PyObject *self) { - extern PyObject *get_counts(void); + extern PyObject *get_counts(void); - return get_counts(); + return get_counts(); } #endif @@ -829,23 +829,23 @@ 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; + 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, @@ -860,7 +860,7 @@ This function should be used for specialized purposes only." static PyObject * sys_current_frames(PyObject *self, PyObject *noargs) { - return _PyThread_CurrentFrames(); + return _PyThread_CurrentFrames(); } PyDoc_STRVAR(call_tracing_doc, @@ -874,10 +874,10 @@ 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_ParseTuple(args, "OO!:call_tracing", &func, &PyTuple_Type, &funcargs)) - return NULL; - return _PyEval_CallTracing(func, funcargs); + PyObject *func, *funcargs; + if (!PyArg_ParseTuple(args, "OO!:call_tracing", &func, &PyTuple_Type, &funcargs)) + return NULL; + return _PyEval_CallTracing(func, funcargs); } PyDoc_STRVAR(callstats_doc, @@ -924,8 +924,8 @@ extern PyObject *_Py_GetDXProfile(PyObject *, PyObject *); static PyObject * sys_clear_type_cache(PyObject* self, PyObject* args) { - PyType_ClearCache(); - Py_RETURN_NONE; + PyType_ClearCache(); + Py_RETURN_NONE; } PyDoc_STRVAR(sys_clear_type_cache__doc__, @@ -934,107 +934,107 @@ Clear the internal type lookup cache."); static PyMethodDef sys_methods[] = { - /* Might as well keep this in alphabetic order */ - {"callstats", (PyCFunction)PyEval_GetCallStats, METH_NOARGS, - callstats_doc}, - {"_clear_type_cache", sys_clear_type_cache, METH_NOARGS, - sys_clear_type_cache__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}, - {"excepthook", sys_excepthook, METH_VARARGS, excepthook_doc}, - {"exit", sys_exit, METH_VARARGS, exit_doc}, - {"getdefaultencoding", (PyCFunction)sys_getdefaultencoding, - METH_NOARGS, getdefaultencoding_doc}, + /* Might as well keep this in alphabetic order */ + {"callstats", (PyCFunction)PyEval_GetCallStats, METH_NOARGS, + callstats_doc}, + {"_clear_type_cache", sys_clear_type_cache, METH_NOARGS, + sys_clear_type_cache__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}, + {"excepthook", sys_excepthook, METH_VARARGS, excepthook_doc}, + {"exit", sys_exit, METH_VARARGS, exit_doc}, + {"getdefaultencoding", (PyCFunction)sys_getdefaultencoding, + METH_NOARGS, getdefaultencoding_doc}, #ifdef HAVE_DLOPEN - {"getdlopenflags", (PyCFunction)sys_getdlopenflags, METH_NOARGS, - getdlopenflags_doc}, + {"getdlopenflags", (PyCFunction)sys_getdlopenflags, METH_NOARGS, + getdlopenflags_doc}, #endif #ifdef COUNT_ALLOCS - {"getcounts", (PyCFunction)sys_getcounts, METH_NOARGS}, + {"getcounts", (PyCFunction)sys_getcounts, METH_NOARGS}, #endif #ifdef DYNAMIC_EXECUTION_PROFILE - {"getdxp", _Py_GetDXProfile, METH_VARARGS}, + {"getdxp", _Py_GetDXProfile, METH_VARARGS}, #endif - {"getfilesystemencoding", (PyCFunction)sys_getfilesystemencoding, - METH_NOARGS, getfilesystemencoding_doc}, + {"getfilesystemencoding", (PyCFunction)sys_getfilesystemencoding, + METH_NOARGS, getfilesystemencoding_doc}, #ifdef Py_TRACE_REFS - {"getobjects", _Py_GetObjects, METH_VARARGS}, + {"getobjects", _Py_GetObjects, METH_VARARGS}, #endif #ifdef Py_REF_DEBUG - {"gettotalrefcount", (PyCFunction)sys_gettotalrefcount, METH_NOARGS}, + {"gettotalrefcount", (PyCFunction)sys_gettotalrefcount, METH_NOARGS}, #endif - {"getrefcount", (PyCFunction)sys_getrefcount, METH_O, getrefcount_doc}, - {"getrecursionlimit", (PyCFunction)sys_getrecursionlimit, METH_NOARGS, - getrecursionlimit_doc}, - {"getsizeof", (PyCFunction)sys_getsizeof, - METH_VARARGS | METH_KEYWORDS, getsizeof_doc}, - {"_getframe", sys_getframe, METH_VARARGS, getframe_doc}, + {"getrefcount", (PyCFunction)sys_getrefcount, METH_O, getrefcount_doc}, + {"getrecursionlimit", (PyCFunction)sys_getrecursionlimit, METH_NOARGS, + getrecursionlimit_doc}, + {"getsizeof", (PyCFunction)sys_getsizeof, + METH_VARARGS | METH_KEYWORDS, getsizeof_doc}, + {"_getframe", sys_getframe, METH_VARARGS, getframe_doc}, #ifdef MS_WINDOWS - {"getwindowsversion", (PyCFunction)sys_getwindowsversion, METH_NOARGS, - getwindowsversion_doc}, + {"getwindowsversion", (PyCFunction)sys_getwindowsversion, METH_NOARGS, + getwindowsversion_doc}, #endif /* MS_WINDOWS */ - {"intern", sys_intern, METH_VARARGS, intern_doc}, + {"intern", sys_intern, METH_VARARGS, intern_doc}, #ifdef USE_MALLOPT - {"mdebug", sys_mdebug, METH_VARARGS}, + {"mdebug", sys_mdebug, METH_VARARGS}, #endif - {"setdefaultencoding", sys_setdefaultencoding, METH_VARARGS, - setdefaultencoding_doc}, - {"setfilesystemencoding", sys_setfilesystemencoding, METH_VARARGS, - setfilesystemencoding_doc}, - {"setcheckinterval", sys_setcheckinterval, METH_VARARGS, - setcheckinterval_doc}, - {"getcheckinterval", sys_getcheckinterval, METH_NOARGS, - getcheckinterval_doc}, + {"setdefaultencoding", sys_setdefaultencoding, METH_VARARGS, + setdefaultencoding_doc}, + {"setfilesystemencoding", sys_setfilesystemencoding, METH_VARARGS, + setfilesystemencoding_doc}, + {"setcheckinterval", sys_setcheckinterval, METH_VARARGS, + setcheckinterval_doc}, + {"getcheckinterval", sys_getcheckinterval, METH_NOARGS, + getcheckinterval_doc}, #ifdef WITH_THREAD - {"setswitchinterval", sys_setswitchinterval, METH_VARARGS, - setswitchinterval_doc}, - {"getswitchinterval", sys_getswitchinterval, METH_NOARGS, - getswitchinterval_doc}, + {"setswitchinterval", sys_setswitchinterval, METH_VARARGS, + setswitchinterval_doc}, + {"getswitchinterval", sys_getswitchinterval, METH_NOARGS, + getswitchinterval_doc}, #endif #ifdef HAVE_DLOPEN - {"setdlopenflags", sys_setdlopenflags, METH_VARARGS, - setdlopenflags_doc}, + {"setdlopenflags", sys_setdlopenflags, METH_VARARGS, + setdlopenflags_doc}, #endif - {"setprofile", sys_setprofile, METH_O, setprofile_doc}, - {"getprofile", sys_getprofile, METH_NOARGS, getprofile_doc}, - {"setrecursionlimit", sys_setrecursionlimit, METH_VARARGS, - setrecursionlimit_doc}, + {"setprofile", sys_setprofile, METH_O, setprofile_doc}, + {"getprofile", sys_getprofile, METH_NOARGS, getprofile_doc}, + {"setrecursionlimit", sys_setrecursionlimit, METH_VARARGS, + setrecursionlimit_doc}, #ifdef WITH_TSC - {"settscdump", sys_settscdump, METH_VARARGS, settscdump_doc}, + {"settscdump", sys_settscdump, METH_VARARGS, settscdump_doc}, #endif - {"settrace", sys_settrace, METH_O, settrace_doc}, - {"gettrace", sys_gettrace, METH_NOARGS, gettrace_doc}, - {"call_tracing", sys_call_tracing, METH_VARARGS, call_tracing_doc}, - {NULL, NULL} /* sentinel */ + {"settrace", sys_settrace, METH_O, settrace_doc}, + {"gettrace", sys_gettrace, METH_NOARGS, gettrace_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 = PyUnicode_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; + PyObject *list = PyList_New(0); + int i; + if (list == NULL) + return NULL; + for (i = 0; PyImport_Inittab[i].name != NULL; i++) { + PyObject *name = PyUnicode_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; @@ -1042,27 +1042,27 @@ static PyObject *warnoptions = NULL; void PySys_ResetWarnOptions(void) { - if (warnoptions == NULL || !PyList_Check(warnoptions)) - return; - PyList_SetSlice(warnoptions, 0, PyList_GET_SIZE(warnoptions), NULL); + if (warnoptions == NULL || !PyList_Check(warnoptions)) + return; + PyList_SetSlice(warnoptions, 0, PyList_GET_SIZE(warnoptions), NULL); } void PySys_AddWarnOption(const wchar_t *s) { - PyObject *str; - - if (warnoptions == NULL || !PyList_Check(warnoptions)) { - Py_XDECREF(warnoptions); - warnoptions = PyList_New(0); - if (warnoptions == NULL) - return; - } - str = PyUnicode_FromWideChar(s, -1); - if (str != NULL) { - PyList_Append(warnoptions, str); - Py_DECREF(str); - } + PyObject *str; + + if (warnoptions == NULL || !PyList_Check(warnoptions)) { + Py_XDECREF(warnoptions); + warnoptions = PyList_New(0); + if (warnoptions == NULL) + return; + } + str = PyUnicode_FromWideChar(s, -1); + if (str != NULL) { + PyList_Append(warnoptions, str); + Py_DECREF(str); + } } int @@ -1174,64 +1174,64 @@ 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 = 0; - - if (svn_initialized) - return; - - python = strstr(headurl, "/python/"); - if (!python) { - strcpy(branch, "unknown branch"); - strcpy(shortbranch, "unknown"); - } - else { - 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, "Unversioned directory") != 0 && strcmp(svnversion, "exported") != 0) - svn_revision = svnversion; - else if (istag) { - len = strlen(_patchlevel_revision); - assert(len >= 13); - assert(len < (sizeof(patchlevel_revision) + 13)); - strncpy(patchlevel_revision, _patchlevel_revision + 11, - len - 13); - patchlevel_revision[len - 13] = '\0'; - svn_revision = patchlevel_revision; - } - else - svn_revision = ""; - - svn_initialized = 1; + const char *python, *br_start, *br_end, *br_end2, *svnversion; + Py_ssize_t len; + int istag = 0; + + if (svn_initialized) + return; + + python = strstr(headurl, "/python/"); + if (!python) { + strcpy(branch, "unknown branch"); + strcpy(shortbranch, "unknown"); + } + else { + 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, "Unversioned directory") != 0 && strcmp(svnversion, "exported") != 0) + svn_revision = svnversion; + else if (istag) { + len = strlen(_patchlevel_revision); + assert(len >= 13); + assert(len < (sizeof(patchlevel_revision) + 13)); + 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. @@ -1240,15 +1240,15 @@ svnversion_init(void) const char* Py_SubversionRevision() { - svnversion_init(); - return svn_revision; + svnversion_init(); + return svn_revision; } const char* Py_SubversionShortBranch() { - svnversion_init(); - return shortbranch; + svnversion_init(); + return shortbranch; } @@ -1260,71 +1260,71 @@ Flags provided through command line arguments or environment vars."); static PyTypeObject FlagsType; static PyStructSequence_Field flags_fields[] = { - {"debug", "-d"}, - {"division_warning", "-Q"}, - {"inspect", "-i"}, - {"interactive", "-i"}, - {"optimize", "-O or -OO"}, - {"dont_write_bytecode", "-B"}, - {"no_user_site", "-s"}, - {"no_site", "-S"}, - {"ignore_environment", "-E"}, - {"verbose", "-v"}, + {"debug", "-d"}, + {"division_warning", "-Q"}, + {"inspect", "-i"}, + {"interactive", "-i"}, + {"optimize", "-O or -OO"}, + {"dont_write_bytecode", "-B"}, + {"no_user_site", "-s"}, + {"no_site", "-S"}, + {"ignore_environment", "-E"}, + {"verbose", "-v"}, #ifdef RISCOS - {"riscos_wimp", "???"}, + {"riscos_wimp", "???"}, #endif - /* {"unbuffered", "-u"}, */ - /* {"skip_first", "-x"}, */ - {"bytes_warning", "-b"}, - {0} + /* {"unbuffered", "-u"}, */ + /* {"skip_first", "-x"}, */ + {"bytes_warning", "-b"}, + {0} }; static PyStructSequence_Desc flags_desc = { - "sys.flags", /* name */ - flags__doc__, /* doc */ - flags_fields, /* fields */ + "sys.flags", /* name */ + flags__doc__, /* doc */ + flags_fields, /* fields */ #ifdef RISCOS - 12 + 12 #else - 11 + 11 #endif }; static PyObject* make_flags(void) { - int pos = 0; - PyObject *seq; + int pos = 0; + PyObject *seq; - seq = PyStructSequence_New(&FlagsType); - if (seq == NULL) - return NULL; + seq = PyStructSequence_New(&FlagsType); + if (seq == NULL) + return NULL; #define SetFlag(flag) \ - PyStructSequence_SET_ITEM(seq, pos++, PyLong_FromLong(flag)) - - SetFlag(Py_DebugFlag); - SetFlag(Py_DivisionWarningFlag); - SetFlag(Py_InspectFlag); - SetFlag(Py_InteractiveFlag); - SetFlag(Py_OptimizeFlag); - SetFlag(Py_DontWriteBytecodeFlag); - SetFlag(Py_NoUserSiteDirectory); - SetFlag(Py_NoSiteFlag); - SetFlag(Py_IgnoreEnvironmentFlag); - SetFlag(Py_VerboseFlag); + PyStructSequence_SET_ITEM(seq, pos++, PyLong_FromLong(flag)) + + SetFlag(Py_DebugFlag); + SetFlag(Py_DivisionWarningFlag); + SetFlag(Py_InspectFlag); + SetFlag(Py_InteractiveFlag); + SetFlag(Py_OptimizeFlag); + SetFlag(Py_DontWriteBytecodeFlag); + SetFlag(Py_NoUserSiteDirectory); + SetFlag(Py_NoSiteFlag); + SetFlag(Py_IgnoreEnvironmentFlag); + SetFlag(Py_VerboseFlag); #ifdef RISCOS - SetFlag(Py_RISCOSWimpFlag); + SetFlag(Py_RISCOSWimpFlag); #endif - /* SetFlag(saw_unbuffered_flag); */ - /* SetFlag(skipfirstline); */ + /* SetFlag(saw_unbuffered_flag); */ + /* SetFlag(skipfirstline); */ SetFlag(Py_BytesWarningFlag); #undef SetFlag - if (PyErr_Occurred()) { - return NULL; - } - return seq; + if (PyErr_Occurred()) { + return NULL; + } + return seq; } PyDoc_STRVAR(version_info__doc__, @@ -1335,330 +1335,330 @@ Version information as a named tuple."); static PyTypeObject VersionInfoType; static PyStructSequence_Field version_info_fields[] = { - {"major", "Major release number"}, - {"minor", "Minor release number"}, - {"micro", "Patch release number"}, - {"releaselevel", "'alpha', 'beta', 'candidate', or 'release'"}, - {"serial", "Serial release number"}, - {0} + {"major", "Major release number"}, + {"minor", "Minor release number"}, + {"micro", "Patch release number"}, + {"releaselevel", "'alpha', 'beta', 'candidate', or 'release'"}, + {"serial", "Serial release number"}, + {0} }; static PyStructSequence_Desc version_info_desc = { - "sys.version_info", /* name */ - version_info__doc__, /* doc */ - version_info_fields, /* fields */ - 5 + "sys.version_info", /* name */ + version_info__doc__, /* doc */ + version_info_fields, /* fields */ + 5 }; static PyObject * make_version_info(void) { - PyObject *version_info; - char *s; - int pos = 0; - - version_info = PyStructSequence_New(&VersionInfoType); - if (version_info == NULL) { - return NULL; - } - - /* - * These release level checks are mutually exclusive and cover - * the field, so don't get too fancy with the pre-processor! - */ + PyObject *version_info; + char *s; + int pos = 0; + + version_info = PyStructSequence_New(&VersionInfoType); + if (version_info == NULL) { + return NULL; + } + + /* + * 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"; + s = "alpha"; #elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_BETA - s = "beta"; + s = "beta"; #elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_GAMMA - s = "candidate"; + s = "candidate"; #elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_FINAL - s = "final"; + s = "final"; #endif #define SetIntItem(flag) \ - PyStructSequence_SET_ITEM(version_info, pos++, PyLong_FromLong(flag)) + PyStructSequence_SET_ITEM(version_info, pos++, PyLong_FromLong(flag)) #define SetStrItem(flag) \ - PyStructSequence_SET_ITEM(version_info, pos++, PyUnicode_FromString(flag)) + PyStructSequence_SET_ITEM(version_info, pos++, PyUnicode_FromString(flag)) - SetIntItem(PY_MAJOR_VERSION); - SetIntItem(PY_MINOR_VERSION); - SetIntItem(PY_MICRO_VERSION); - SetStrItem(s); - SetIntItem(PY_RELEASE_SERIAL); + SetIntItem(PY_MAJOR_VERSION); + SetIntItem(PY_MINOR_VERSION); + SetIntItem(PY_MICRO_VERSION); + SetStrItem(s); + SetIntItem(PY_RELEASE_SERIAL); #undef SetIntItem #undef SetStrItem - if (PyErr_Occurred()) { - Py_CLEAR(version_info); - return NULL; - } - return version_info; + if (PyErr_Occurred()) { + Py_CLEAR(version_info); + return NULL; + } + return version_info; } static struct PyModuleDef sysmodule = { - PyModuleDef_HEAD_INIT, - "sys", - sys_doc, - -1, /* multiple "initialization" just copies the module dict. */ - sys_methods, - NULL, - NULL, - NULL, - NULL + PyModuleDef_HEAD_INIT, + "sys", + sys_doc, + -1, /* multiple "initialization" just copies the module dict. */ + sys_methods, + NULL, + NULL, + NULL, + NULL }; PyObject * _PySys_Init(void) { - PyObject *m, *v, *sysdict; - char *s; - - m = PyModule_Create(&sysmodule); - if (m == NULL) - return NULL; - sysdict = PyModule_GetDict(m); -#define SET_SYS_FROM_STRING(key, value) \ - v = value; \ - if (v != NULL) \ - PyDict_SetItemString(sysdict, key, v); \ - Py_XDECREF(v) - - /* Check that stdin is not a directory - Using shell redirection, you can redirect stdin to a directory, - crashing the Python interpreter. Catch this common mistake here - and output a useful error message. Note that under MS Windows, - the shell already prevents that. */ + PyObject *m, *v, *sysdict; + char *s; + + m = PyModule_Create(&sysmodule); + if (m == NULL) + return NULL; + sysdict = PyModule_GetDict(m); +#define SET_SYS_FROM_STRING(key, value) \ + v = value; \ + if (v != NULL) \ + PyDict_SetItemString(sysdict, key, v); \ + Py_XDECREF(v) + + /* Check that stdin is not a directory + Using shell redirection, you can redirect stdin to a directory, + crashing the Python interpreter. Catch this common mistake here + and output a useful error message. Note that under MS Windows, + the shell already prevents that. */ #if !defined(MS_WINDOWS) - { - 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: is a directory, cannot continue\n"); - exit(EXIT_FAILURE); - } - } + { + 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: is a directory, cannot continue\n"); + exit(EXIT_FAILURE); + } + } #endif - /* stdin/stdout/stderr are now set by pythonrun.c */ - - PyDict_SetItemString(sysdict, "__displayhook__", - PyDict_GetItemString(sysdict, "displayhook")); - PyDict_SetItemString(sysdict, "__excepthook__", - PyDict_GetItemString(sysdict, "excepthook")); - SET_SYS_FROM_STRING("version", - PyUnicode_FromString(Py_GetVersion())); - SET_SYS_FROM_STRING("hexversion", - PyLong_FromLong(PY_VERSION_HEX)); - svnversion_init(); - SET_SYS_FROM_STRING("subversion", - Py_BuildValue("(UUU)", "CPython", branch, - svn_revision)); - SET_SYS_FROM_STRING("dont_write_bytecode", - PyBool_FromLong(Py_DontWriteBytecodeFlag)); - SET_SYS_FROM_STRING("api_version", - PyLong_FromLong(PYTHON_API_VERSION)); - SET_SYS_FROM_STRING("copyright", - PyUnicode_FromString(Py_GetCopyright())); - SET_SYS_FROM_STRING("platform", - PyUnicode_FromString(Py_GetPlatform())); - SET_SYS_FROM_STRING("executable", - PyUnicode_FromWideChar( - Py_GetProgramFullPath(), -1)); - SET_SYS_FROM_STRING("prefix", - PyUnicode_FromWideChar(Py_GetPrefix(), -1)); - SET_SYS_FROM_STRING("exec_prefix", - PyUnicode_FromWideChar(Py_GetExecPrefix(), -1)); - SET_SYS_FROM_STRING("maxsize", - PyLong_FromSsize_t(PY_SSIZE_T_MAX)); - SET_SYS_FROM_STRING("float_info", - PyFloat_GetInfo()); - SET_SYS_FROM_STRING("int_info", - PyLong_GetInfo()); - SET_SYS_FROM_STRING("maxunicode", - PyLong_FromLong(PyUnicode_GetMax())); - 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", - PyUnicode_FromString(value)); - } + /* stdin/stdout/stderr are now set by pythonrun.c */ + + PyDict_SetItemString(sysdict, "__displayhook__", + PyDict_GetItemString(sysdict, "displayhook")); + PyDict_SetItemString(sysdict, "__excepthook__", + PyDict_GetItemString(sysdict, "excepthook")); + SET_SYS_FROM_STRING("version", + PyUnicode_FromString(Py_GetVersion())); + SET_SYS_FROM_STRING("hexversion", + PyLong_FromLong(PY_VERSION_HEX)); + svnversion_init(); + SET_SYS_FROM_STRING("subversion", + Py_BuildValue("(UUU)", "CPython", branch, + svn_revision)); + SET_SYS_FROM_STRING("dont_write_bytecode", + PyBool_FromLong(Py_DontWriteBytecodeFlag)); + SET_SYS_FROM_STRING("api_version", + PyLong_FromLong(PYTHON_API_VERSION)); + SET_SYS_FROM_STRING("copyright", + PyUnicode_FromString(Py_GetCopyright())); + SET_SYS_FROM_STRING("platform", + PyUnicode_FromString(Py_GetPlatform())); + SET_SYS_FROM_STRING("executable", + PyUnicode_FromWideChar( + Py_GetProgramFullPath(), -1)); + SET_SYS_FROM_STRING("prefix", + PyUnicode_FromWideChar(Py_GetPrefix(), -1)); + SET_SYS_FROM_STRING("exec_prefix", + PyUnicode_FromWideChar(Py_GetExecPrefix(), -1)); + SET_SYS_FROM_STRING("maxsize", + PyLong_FromSsize_t(PY_SSIZE_T_MAX)); + SET_SYS_FROM_STRING("float_info", + PyFloat_GetInfo()); + SET_SYS_FROM_STRING("int_info", + PyLong_GetInfo()); + SET_SYS_FROM_STRING("maxunicode", + PyLong_FromLong(PyUnicode_GetMax())); + 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", + PyUnicode_FromString(value)); + } #ifdef MS_COREDLL - SET_SYS_FROM_STRING("dllhandle", - PyLong_FromVoidPtr(PyWin_DLLhModule)); - SET_SYS_FROM_STRING("winver", - PyUnicode_FromString(PyWin_DLLVersionString)); + SET_SYS_FROM_STRING("dllhandle", + PyLong_FromVoidPtr(PyWin_DLLhModule)); + SET_SYS_FROM_STRING("winver", + PyUnicode_FromString(PyWin_DLLVersionString)); #endif - if (warnoptions == NULL) { - warnoptions = PyList_New(0); - } - else { - Py_INCREF(warnoptions); - } - if (warnoptions != NULL) { - PyDict_SetItemString(sysdict, "warnoptions", warnoptions); - } - - /* version_info */ - if (VersionInfoType.tp_name == 0) - PyStructSequence_InitType(&VersionInfoType, &version_info_desc); - SET_SYS_FROM_STRING("version_info", make_version_info()); - /* prevent user from creating new instances */ - VersionInfoType.tp_init = NULL; - VersionInfoType.tp_new = NULL; - - /* flags */ - if (FlagsType.tp_name == 0) - PyStructSequence_InitType(&FlagsType, &flags_desc); - SET_SYS_FROM_STRING("flags", make_flags()); - /* prevent user from creating new instances */ - FlagsType.tp_init = NULL; - FlagsType.tp_new = NULL; + if (warnoptions == NULL) { + warnoptions = PyList_New(0); + } + else { + Py_INCREF(warnoptions); + } + if (warnoptions != NULL) { + PyDict_SetItemString(sysdict, "warnoptions", warnoptions); + } + + /* version_info */ + if (VersionInfoType.tp_name == 0) + PyStructSequence_InitType(&VersionInfoType, &version_info_desc); + SET_SYS_FROM_STRING("version_info", make_version_info()); + /* prevent user from creating new instances */ + VersionInfoType.tp_init = NULL; + VersionInfoType.tp_new = NULL; + + /* flags */ + if (FlagsType.tp_name == 0) + PyStructSequence_InitType(&FlagsType, &flags_desc); + SET_SYS_FROM_STRING("flags", make_flags()); + /* prevent user from creating new instances */ + FlagsType.tp_init = NULL; + FlagsType.tp_new = NULL; #if defined(MS_WINDOWS) - /* getwindowsversion */ - if (WindowsVersionType.tp_name == 0) - PyStructSequence_InitType(&WindowsVersionType, &windows_version_desc); - /* prevent user from creating new instances */ - WindowsVersionType.tp_init = NULL; - WindowsVersionType.tp_new = NULL; + /* getwindowsversion */ + if (WindowsVersionType.tp_name == 0) + PyStructSequence_InitType(&WindowsVersionType, &windows_version_desc); + /* prevent user from creating new instances */ + WindowsVersionType.tp_init = NULL; + WindowsVersionType.tp_new = NULL; #endif - /* float repr style: 0.03 (short) vs 0.029999999999999999 (legacy) */ + /* float repr style: 0.03 (short) vs 0.029999999999999999 (legacy) */ #ifndef PY_NO_SHORT_FLOAT_REPR - SET_SYS_FROM_STRING("float_repr_style", - PyUnicode_FromString("short")); + SET_SYS_FROM_STRING("float_repr_style", + PyUnicode_FromString("short")); #else - SET_SYS_FROM_STRING("float_repr_style", - PyUnicode_FromString("legacy")); + SET_SYS_FROM_STRING("float_repr_style", + PyUnicode_FromString("legacy")); #endif #undef SET_SYS_FROM_STRING - if (PyErr_Occurred()) - return NULL; - return m; + if (PyErr_Occurred()) + return NULL; + return m; } static PyObject * makepathobject(const wchar_t *path, wchar_t delim) { - int i, n; - const wchar_t *p; - PyObject *v, *w; - - n = 1; - p = path; - while ((p = wcschr(p, delim)) != NULL) { - n++; - p++; - } - v = PyList_New(n); - if (v == NULL) - return NULL; - for (i = 0; ; i++) { - p = wcschr(path, delim); - if (p == NULL) - p = path + wcslen(path); /* End of string */ - w = PyUnicode_FromWideChar(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; + int i, n; + const wchar_t *p; + PyObject *v, *w; + + n = 1; + p = path; + while ((p = wcschr(p, delim)) != NULL) { + n++; + p++; + } + v = PyList_New(n); + if (v == NULL) + return NULL; + for (i = 0; ; i++) { + p = wcschr(path, delim); + if (p == NULL) + p = path + wcslen(path); /* End of string */ + w = PyUnicode_FromWideChar(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(const wchar_t *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); + 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, wchar_t **argv) { - PyObject *av; - if (argc <= 0 || argv == NULL) { - /* Ensure at least one (empty) argument is seen */ - static wchar_t *empty_argv[1] = {L""}; - argv = empty_argv; - argc = 1; - } - av = PyList_New(argc); - if (av != NULL) { - int i; - for (i = 0; i < argc; i++) { + PyObject *av; + if (argc <= 0 || argv == NULL) { + /* Ensure at least one (empty) argument is seen */ + static wchar_t *empty_argv[1] = {L""}; + 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 = PyUnicode_FromString(argv[0]); - else - v = PyUnicode_FromString( - decc$translate_vms(argv[0])); - } else - v = PyUnicode_FromString(argv[i]); + 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 = PyUnicode_FromString(argv[0]); + else + v = PyUnicode_FromString( + decc$translate_vms(argv[0])); + } else + v = PyUnicode_FromString(argv[i]); #else - PyObject *v = PyUnicode_FromWideChar(argv[i], -1); + PyObject *v = PyUnicode_FromWideChar(argv[i], -1); #endif - if (v == NULL) { - Py_DECREF(av); - av = NULL; - break; - } - PyList_SetItem(av, i, v); - } - } - return av; + if (v == NULL) { + Py_DECREF(av); + av = NULL; + break; + } + PyList_SetItem(av, i, v); + } + } + return av; } #ifdef HAVE_REALPATH static wchar_t* _wrealpath(const wchar_t *path, wchar_t *resolved_path) { - char cpath[PATH_MAX]; - char cresolved_path[PATH_MAX]; - char *res; - size_t r; - r = wcstombs(cpath, path, PATH_MAX); - if (r == (size_t)-1 || r >= PATH_MAX) { - errno = EINVAL; - return NULL; - } - res = realpath(cpath, cresolved_path); - if (res == NULL) - return NULL; - r = mbstowcs(resolved_path, cresolved_path, PATH_MAX); - if (r == (size_t)-1 || r >= PATH_MAX) { - errno = EINVAL; - return NULL; - } - return resolved_path; + char cpath[PATH_MAX]; + char cresolved_path[PATH_MAX]; + char *res; + size_t r; + r = wcstombs(cpath, path, PATH_MAX); + if (r == (size_t)-1 || r >= PATH_MAX) { + errno = EINVAL; + return NULL; + } + res = realpath(cpath, cresolved_path); + if (res == NULL) + return NULL; + r = mbstowcs(resolved_path, cresolved_path, PATH_MAX); + if (r == (size_t)-1 || r >= PATH_MAX) { + errno = EINVAL; + return NULL; + } + return resolved_path; } #endif @@ -1666,101 +1666,101 @@ void PySys_SetArgv(int argc, wchar_t **argv) { #if defined(HAVE_REALPATH) - wchar_t fullpath[MAXPATHLEN]; + wchar_t fullpath[MAXPATHLEN]; #elif defined(MS_WINDOWS) && !defined(MS_WINCE) - wchar_t fullpath[MAX_PATH]; + wchar_t 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) { - wchar_t *argv0 = argv[0]; - wchar_t *p = NULL; - Py_ssize_t n = 0; - PyObject *a; - extern int _Py_wreadlink(const wchar_t *, wchar_t *, size_t); + 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) { + wchar_t *argv0 = argv[0]; + wchar_t *p = NULL; + Py_ssize_t n = 0; + PyObject *a; + extern int _Py_wreadlink(const wchar_t *, wchar_t *, size_t); #ifdef HAVE_READLINK - wchar_t link[MAXPATHLEN+1]; - wchar_t argv0copy[2*MAXPATHLEN+1]; - int nr = 0; - if (argc > 0 && argv0 != NULL && wcscmp(argv0, L"-c") != 0) - nr = _Py_wreadlink(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 (wcschr(link, SEP) == NULL) - ; /* Link without path */ - else { - /* Must join(dirname(argv0), link) */ - wchar_t *q = wcsrchr(argv0, SEP); - if (q == NULL) - argv0 = link; /* argv0 without path */ - else { - /* Must make a copy */ - wcscpy(argv0copy, argv0); - q = wcsrchr(argv0copy, SEP); - wcscpy(q+1, link); - argv0 = argv0copy; - } - } - } + wchar_t link[MAXPATHLEN+1]; + wchar_t argv0copy[2*MAXPATHLEN+1]; + int nr = 0; + if (argc > 0 && argv0 != NULL && wcscmp(argv0, L"-c") != 0) + nr = _Py_wreadlink(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 (wcschr(link, SEP) == NULL) + ; /* Link without path */ + else { + /* Must join(dirname(argv0), link) */ + wchar_t *q = wcsrchr(argv0, SEP); + if (q == NULL) + argv0 = link; /* argv0 without path */ + else { + /* Must make a copy */ + wcscpy(argv0copy, argv0); + q = wcsrchr(argv0copy, SEP); + wcscpy(q+1, link); + argv0 = argv0copy; + } + } + } #endif /* HAVE_READLINK */ #if SEP == '\\' /* Special case for MS filename syntax */ - if (argc > 0 && argv0 != NULL && wcscmp(argv0, L"-c") != 0) { - wchar_t *q; + if (argc > 0 && argv0 != NULL && wcscmp(argv0, L"-c") != 0) { + wchar_t *q; #if defined(MS_WINDOWS) && !defined(MS_WINCE) - /* This code here replaces the first element in argv with the full - path that it represents. Under CE, there are no relative paths so - the argument must be the full path anyway. */ - wchar_t *ptemp; - if (GetFullPathNameW(argv0, - sizeof(fullpath)/sizeof(fullpath[0]), - fullpath, - &ptemp)) { - argv0 = fullpath; - } + /* This code here replaces the first element in argv with the full + path that it represents. Under CE, there are no relative paths so + the argument must be the full path anyway. */ + wchar_t *ptemp; + if (GetFullPathNameW(argv0, + sizeof(fullpath)/sizeof(fullpath[0]), + fullpath, + &ptemp)) { + argv0 = fullpath; + } #endif - p = wcsrchr(argv0, SEP); - /* Test for alternate separator */ - q = wcsrchr(p ? p : argv0, '/'); - if (q != NULL) - p = q; - if (p != NULL) { - n = p + 1 - argv0; - if (n > 1 && p[-1] != ':') - n--; /* Drop trailing separator */ - } - } + p = wcsrchr(argv0, SEP); + /* Test for alternate separator */ + q = wcsrchr(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 && wcscmp(argv0, L"-c") != 0) { + if (argc > 0 && argv0 != NULL && wcscmp(argv0, L"-c") != 0) { #if defined(HAVE_REALPATH) - if (_wrealpath(argv0, fullpath)) { - argv0 = fullpath; - } + if (_wrealpath(argv0, fullpath)) { + argv0 = fullpath; + } #endif - p = wcsrchr(argv0, SEP); - } - if (p != NULL) { - n = p + 1 - argv0; + p = wcsrchr(argv0, SEP); + } + if (p != NULL) { + n = p + 1 - argv0; #if SEP == '/' /* Special case for Unix filename syntax */ - if (n > 1) - n--; /* Drop trailing separator */ + if (n > 1) + n--; /* Drop trailing separator */ #endif /* Unix */ - } + } #endif /* All others */ - a = PyUnicode_FromWideChar(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); + a = PyUnicode_FromWideChar(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); } /* Reimplementation of PyFile_WriteString() no calling indirectly @@ -1769,37 +1769,37 @@ PySys_SetArgv(int argc, wchar_t **argv) static int sys_pyfile_write(const char *text, PyObject *file) { - PyObject *unicode = NULL, *writer = NULL, *args = NULL, *result = NULL; - int err; + PyObject *unicode = NULL, *writer = NULL, *args = NULL, *result = NULL; + int err; - unicode = PyUnicode_FromString(text); - if (unicode == NULL) - goto error; + unicode = PyUnicode_FromString(text); + if (unicode == NULL) + goto error; - writer = PyObject_GetAttrString(file, "write"); - if (writer == NULL) - goto error; + writer = PyObject_GetAttrString(file, "write"); + if (writer == NULL) + goto error; - args = PyTuple_Pack(1, unicode); - if (args == NULL) - goto error; + args = PyTuple_Pack(1, unicode); + if (args == NULL) + goto error; - result = PyEval_CallObject(writer, args); - if (result == NULL) { - goto error; - } else { - err = 0; - goto finally; - } + result = PyEval_CallObject(writer, args); + if (result == NULL) { + goto error; + } else { + err = 0; + goto finally; + } error: - err = -1; + err = -1; finally: - Py_XDECREF(unicode); - Py_XDECREF(writer); - Py_XDECREF(args); - Py_XDECREF(result); - return err; + Py_XDECREF(unicode); + Py_XDECREF(writer); + Py_XDECREF(args); + Py_XDECREF(result); + return err; } @@ -1834,44 +1834,44 @@ finally: static void mywrite(char *name, FILE *fp, const char *format, va_list va) { - PyObject *file; - PyObject *error_type, *error_value, *error_traceback; - char buffer[1001]; - int written; - - PyErr_Fetch(&error_type, &error_value, &error_traceback); - file = PySys_GetObject(name); - written = PyOS_vsnprintf(buffer, sizeof(buffer), format, va); - if (sys_pyfile_write(buffer, file) != 0) { - PyErr_Clear(); - fputs(buffer, fp); - } - if (written < 0 || (size_t)written >= sizeof(buffer)) { - const char *truncated = "... truncated"; - if (sys_pyfile_write(truncated, file) != 0) { - PyErr_Clear(); - fputs(truncated, fp); - } - } - PyErr_Restore(error_type, error_value, error_traceback); + PyObject *file; + PyObject *error_type, *error_value, *error_traceback; + char buffer[1001]; + int written; + + PyErr_Fetch(&error_type, &error_value, &error_traceback); + file = PySys_GetObject(name); + written = PyOS_vsnprintf(buffer, sizeof(buffer), format, va); + if (sys_pyfile_write(buffer, file) != 0) { + PyErr_Clear(); + fputs(buffer, fp); + } + if (written < 0 || (size_t)written >= sizeof(buffer)) { + const char *truncated = "... truncated"; + if (sys_pyfile_write(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_list va; - va_start(va, format); - mywrite("stdout", stdout, format, va); - va_end(va); + va_start(va, format); + mywrite("stdout", stdout, format, va); + va_end(va); } void PySys_WriteStderr(const char *format, ...) { - va_list va; + va_list va; - va_start(va, format); - mywrite("stderr", stderr, format, va); - va_end(va); + va_start(va, format); + mywrite("stderr", stderr, format, va); + va_end(va); } diff --git a/Python/thread.c b/Python/thread.c index a839481b4f..09beaef795 100644 --- a/Python/thread.c +++ b/Python/thread.c @@ -40,7 +40,7 @@ #endif /* Check if we're running on HP-UX and _SC_THREADS is defined. If so, then - enough of the Posix threads package is implimented to support python + enough of the Posix threads package is implimented to support python threads. This is valid for HP-UX 11.23 running on an ia64 system. If needed, add @@ -58,8 +58,8 @@ #ifdef Py_DEBUG static int thread_debug = 0; -#define dprintf(args) (void)((thread_debug & 1) && printf args) -#define d2printf(args) ((thread_debug & 8) && printf args) +#define dprintf(args) (void)((thread_debug & 1) && printf args) +#define d2printf(args) ((thread_debug & 8) && printf args) #else #define dprintf(args) #define d2printf(args) @@ -73,20 +73,20 @@ void PyThread_init_thread(void) { #ifdef Py_DEBUG - char *p = Py_GETENV("PYTHONTHREADDEBUG"); - - if (p) { - if (*p) - thread_debug = atoi(p); - else - thread_debug = 1; - } + char *p = Py_GETENV("PYTHONTHREADDEBUG"); + + if (p) { + if (*p) + thread_debug = atoi(p); + else + thread_debug = 1; + } #endif /* Py_DEBUG */ - if (initialized) - return; - initialized = 1; - dprintf(("PyThread_init_thread called\n")); - PyThread__init_thread(); + if (initialized) + return; + initialized = 1; + dprintf(("PyThread_init_thread called\n")); + PyThread__init_thread(); } /* Support for runtime thread stack size tuning. @@ -145,21 +145,21 @@ static size_t _pythread_stacksize = 0; size_t PyThread_get_stacksize(void) { - return _pythread_stacksize; + return _pythread_stacksize; } /* Only platforms defining a THREAD_SET_STACKSIZE() macro in thread_.h support changing the stack size. Return 0 if stack size is valid, - -1 if stack size value is invalid, - -2 if setting stack size is not supported. */ + -1 if stack size value is invalid, + -2 if setting stack size is not supported. */ int PyThread_set_stacksize(size_t size) { #if defined(THREAD_SET_STACKSIZE) - return THREAD_SET_STACKSIZE(size); + return THREAD_SET_STACKSIZE(size); #else - return -2; + return -2; #endif } @@ -211,15 +211,15 @@ that calls to PyThread_create_key() are serialized externally. * to enforce exclusion internally. */ struct key { - /* Next record in the list, or NULL if this is the last record. */ - struct key *next; + /* Next record in the list, or NULL if this is the last record. */ + struct key *next; - /* The thread id, according to PyThread_get_thread_ident(). */ - long id; + /* The thread id, according to PyThread_get_thread_ident(). */ + long id; - /* The key and its associated value. */ - int key; - void *value; + /* The key and its associated value. */ + int key; + void *value; }; static struct key *keyhead = NULL; @@ -250,41 +250,41 @@ static int nkeys = 0; /* PyThread_create_key() hands out nkeys+1 next */ static struct key * find_key(int key, void *value) { - struct key *p, *prev_p; - long id = PyThread_get_thread_ident(); - - if (!keymutex) - return NULL; - PyThread_acquire_lock(keymutex, 1); - prev_p = NULL; - for (p = keyhead; p != NULL; p = p->next) { - if (p->id == id && p->key == key) - goto Done; - /* Sanity check. These states should never happen but if - * they do we must abort. Otherwise we'll end up spinning in - * in a tight loop with the lock held. A similar check is done - * in pystate.c tstate_delete_common(). */ - if (p == prev_p) - Py_FatalError("tls find_key: small circular list(!)"); - prev_p = p; - if (p->next == keyhead) - Py_FatalError("tls find_key: circular list(!)"); - } - if (value == NULL) { - assert(p == NULL); - goto Done; - } - p = (struct key *)malloc(sizeof(struct key)); - if (p != NULL) { - p->id = id; - p->key = key; - p->value = value; - p->next = keyhead; - keyhead = p; - } + struct key *p, *prev_p; + long id = PyThread_get_thread_ident(); + + if (!keymutex) + return NULL; + PyThread_acquire_lock(keymutex, 1); + prev_p = NULL; + for (p = keyhead; p != NULL; p = p->next) { + if (p->id == id && p->key == key) + goto Done; + /* Sanity check. These states should never happen but if + * they do we must abort. Otherwise we'll end up spinning in + * in a tight loop with the lock held. A similar check is done + * in pystate.c tstate_delete_common(). */ + if (p == prev_p) + Py_FatalError("tls find_key: small circular list(!)"); + prev_p = p; + if (p->next == keyhead) + Py_FatalError("tls find_key: circular list(!)"); + } + if (value == NULL) { + assert(p == NULL); + goto Done; + } + p = (struct key *)malloc(sizeof(struct key)); + if (p != NULL) { + p->id = id; + p->key = key; + p->value = value; + p->next = keyhead; + keyhead = p; + } Done: - PyThread_release_lock(keymutex); - return p; + PyThread_release_lock(keymutex); + return p; } /* Return a new key. This must be called before any other functions in @@ -294,32 +294,32 @@ find_key(int key, void *value) int PyThread_create_key(void) { - /* All parts of this function are wrong if it's called by multiple - * threads simultaneously. - */ - if (keymutex == NULL) - keymutex = PyThread_allocate_lock(); - return ++nkeys; + /* All parts of this function are wrong if it's called by multiple + * threads simultaneously. + */ + if (keymutex == NULL) + keymutex = PyThread_allocate_lock(); + return ++nkeys; } /* Forget the associations for key across *all* threads. */ void PyThread_delete_key(int key) { - struct key *p, **q; - - 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); + 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, @@ -331,14 +331,14 @@ PyThread_delete_key(int key) 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; + 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 @@ -347,34 +347,34 @@ PyThread_set_key_value(int key, void *value) void * PyThread_get_key_value(int key) { - struct key *p = find_key(key, NULL); + struct key *p = find_key(key, NULL); - if (p == NULL) - return NULL; - else - return p->value; + if (p == NULL) + return NULL; + else + return p->value; } /* Forget the current thread's association for key, if any. */ void PyThread_delete_key_value(int key) { - long id = PyThread_get_thread_ident(); - struct key *p, **q; - - 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); + 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); } /* Forget everything not associated with the current thread id. @@ -385,27 +385,27 @@ PyThread_delete_key_value(int key) void PyThread_ReInitTLS(void) { - long id = PyThread_get_thread_ident(); - struct key *p, **q; - - if (!keymutex) - return; - - /* As with interpreter_lock in PyEval_ReInitThreads() - we just create a new lock without freeing the old one */ - keymutex = PyThread_allocate_lock(); - - /* Delete all keys which do not match the current thread id */ - q = &keyhead; - while ((p = *q) != NULL) { - if (p->id != id) { - *q = p->next; - free((void *)p); - /* NB This does *not* free p->value! */ - } - else - q = &p->next; - } + long id = PyThread_get_thread_ident(); + struct key *p, **q; + + if (!keymutex) + return; + + /* As with interpreter_lock in PyEval_ReInitThreads() + we just create a new lock without freeing the old one */ + keymutex = PyThread_allocate_lock(); + + /* Delete all keys which do not match the current thread id */ + q = &keyhead; + while ((p = *q) != NULL) { + if (p->id != id) { + *q = p->next; + free((void *)p); + /* NB This does *not* free p->value! */ + } + else + q = &p->next; + } } #endif /* Py_HAVE_NATIVE_TLS */ diff --git a/Python/thread_cthread.h b/Python/thread_cthread.h index 71634122c0..1b3e3904cd 100644 --- a/Python/thread_cthread.h +++ b/Python/thread_cthread.h @@ -14,12 +14,12 @@ static void PyThread__init_thread(void) { #ifndef HURD_C_THREADS - /* Roland McGrath said this should not be used since this is - done while linking to threads */ - cthread_init(); + /* Roland McGrath said this should not be used since this is + done while linking to threads */ + cthread_init(); #else /* do nothing */ - ; + ; #endif } @@ -29,34 +29,34 @@ PyThread__init_thread(void) long PyThread_start_new_thread(void (*func)(void *), void *arg) { - int success = 0; /* init not needed when SOLARIS_THREADS and */ - /* C_THREADS implemented properly */ + int success = 0; /* init not needed when SOLARIS_THREADS and */ + /* C_THREADS implemented properly */ - dprintf(("PyThread_start_new_thread called\n")); - if (!initialized) - PyThread_init_thread(); - /* looks like solaris detaches the thread to never rejoin - * so well do it here - */ - cthread_detach(cthread_fork((cthread_fn_t) func, arg)); - return success < 0 ? -1 : 0; + dprintf(("PyThread_start_new_thread called\n")); + if (!initialized) + PyThread_init_thread(); + /* looks like solaris detaches the thread to never rejoin + * so well do it here + */ + cthread_detach(cthread_fork((cthread_fn_t) func, arg)); + return success < 0 ? -1 : 0; } long PyThread_get_thread_ident(void) { - if (!initialized) - PyThread_init_thread(); - return (long) cthread_self(); + if (!initialized) + PyThread_init_thread(); + return (long) cthread_self(); } void PyThread_exit_thread(void) { - dprintf(("PyThread_exit_thread called\n")); - if (!initialized) - exit(0); - cthread_exit(0); + dprintf(("PyThread_exit_thread called\n")); + if (!initialized) + exit(0); + cthread_exit(0); } /* @@ -65,48 +65,48 @@ PyThread_exit_thread(void) PyThread_type_lock PyThread_allocate_lock(void) { - mutex_t lock; + mutex_t lock; - dprintf(("PyThread_allocate_lock called\n")); - if (!initialized) - PyThread_init_thread(); + dprintf(("PyThread_allocate_lock called\n")); + if (!initialized) + PyThread_init_thread(); - lock = mutex_alloc(); - if (mutex_init(lock)) { - perror("mutex_init"); - free((void *) lock); - lock = 0; - } - dprintf(("PyThread_allocate_lock() -> %p\n", lock)); - return (PyThread_type_lock) lock; + lock = mutex_alloc(); + if (mutex_init(lock)) { + perror("mutex_init"); + free((void *) lock); + lock = 0; + } + dprintf(("PyThread_allocate_lock() -> %p\n", lock)); + return (PyThread_type_lock) lock; } void PyThread_free_lock(PyThread_type_lock lock) { - dprintf(("PyThread_free_lock(%p) called\n", lock)); - mutex_free(lock); + dprintf(("PyThread_free_lock(%p) called\n", lock)); + mutex_free(lock); } int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) { - int success = FALSE; + int success = FALSE; - dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); - if (waitflag) { /* blocking */ - mutex_lock((mutex_t)lock); - success = TRUE; - } else { /* non blocking */ - success = mutex_try_lock((mutex_t)lock); - } - dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); - return success; + dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); + if (waitflag) { /* blocking */ + mutex_lock((mutex_t)lock); + success = TRUE; + } else { /* non blocking */ + success = mutex_try_lock((mutex_t)lock); + } + dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); + return success; } void PyThread_release_lock(PyThread_type_lock lock) { - dprintf(("PyThread_release_lock(%p) called\n", lock)); - mutex_unlock((mutex_t )lock); + dprintf(("PyThread_release_lock(%p) called\n", lock)); + mutex_unlock((mutex_t )lock); } diff --git a/Python/thread_foobar.h b/Python/thread_foobar.h index 1b993d1e79..d2b78c5cae 100644 --- a/Python/thread_foobar.h +++ b/Python/thread_foobar.h @@ -13,28 +13,28 @@ PyThread__init_thread(void) long PyThread_start_new_thread(void (*func)(void *), void *arg) { - int success = 0; /* init not needed when SOLARIS_THREADS and */ - /* C_THREADS implemented properly */ + int success = 0; /* init not needed when SOLARIS_THREADS and */ + /* C_THREADS implemented properly */ - dprintf(("PyThread_start_new_thread called\n")); - if (!initialized) - PyThread_init_thread(); - return success < 0 ? -1 : 0; + dprintf(("PyThread_start_new_thread called\n")); + if (!initialized) + PyThread_init_thread(); + return success < 0 ? -1 : 0; } long PyThread_get_thread_ident(void) { - if (!initialized) - PyThread_init_thread(); + if (!initialized) + PyThread_init_thread(); } void PyThread_exit_thread(void) { - dprintf(("PyThread_exit_thread called\n")); - if (!initialized) - exit(0); + dprintf(("PyThread_exit_thread called\n")); + if (!initialized) + exit(0); } /* @@ -44,32 +44,32 @@ PyThread_type_lock PyThread_allocate_lock(void) { - dprintf(("PyThread_allocate_lock called\n")); - if (!initialized) - PyThread_init_thread(); + dprintf(("PyThread_allocate_lock called\n")); + if (!initialized) + PyThread_init_thread(); - dprintf(("PyThread_allocate_lock() -> %p\n", lock)); - return (PyThread_type_lock) lock; + dprintf(("PyThread_allocate_lock() -> %p\n", lock)); + return (PyThread_type_lock) lock; } void PyThread_free_lock(PyThread_type_lock lock) { - dprintf(("PyThread_free_lock(%p) called\n", lock)); + dprintf(("PyThread_free_lock(%p) called\n", lock)); } int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) { - int success; + int success; - dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); - dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); - return success; + dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); + dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); + return success; } void PyThread_release_lock(PyThread_type_lock lock) { - dprintf(("PyThread_release_lock(%p) called\n", lock)); + dprintf(("PyThread_release_lock(%p) called\n", lock)); } diff --git a/Python/thread_lwp.h b/Python/thread_lwp.h index 93d8295556..ba7b37ad7e 100644 --- a/Python/thread_lwp.h +++ b/Python/thread_lwp.h @@ -3,13 +3,13 @@ #include #include -#define STACKSIZE 1000 /* stacksize for a thread */ -#define NSTACKS 2 /* # stacks to be put in cache initially */ +#define STACKSIZE 1000 /* stacksize for a thread */ +#define NSTACKS 2 /* # stacks to be put in cache initially */ struct lock { - int lock_locked; - cv_t lock_condvar; - mon_t lock_monitor; + int lock_locked; + cv_t lock_condvar; + mon_t lock_monitor; }; @@ -18,7 +18,7 @@ struct lock { */ static void PyThread__init_thread(void) { - lwp_setstkcache(STACKSIZE, NSTACKS); + lwp_setstkcache(STACKSIZE, NSTACKS); } /* @@ -28,31 +28,31 @@ static void PyThread__init_thread(void) long PyThread_start_new_thread(void (*func)(void *), void *arg) { - thread_t tid; - int success; - dprintf(("PyThread_start_new_thread called\n")); - if (!initialized) - PyThread_init_thread(); - success = lwp_create(&tid, func, MINPRIO, 0, lwp_newstk(), 1, arg); - return success < 0 ? -1 : 0; + thread_t tid; + int success; + dprintf(("PyThread_start_new_thread called\n")); + if (!initialized) + PyThread_init_thread(); + success = lwp_create(&tid, func, MINPRIO, 0, lwp_newstk(), 1, arg); + return success < 0 ? -1 : 0; } long PyThread_get_thread_ident(void) { - thread_t tid; - if (!initialized) - PyThread_init_thread(); - if (lwp_self(&tid) < 0) - return -1; - return tid.thread_id; + thread_t tid; + if (!initialized) + PyThread_init_thread(); + if (lwp_self(&tid) < 0) + return -1; + return tid.thread_id; } void PyThread_exit_thread(void) { - dprintf(("PyThread_exit_thread called\n")); - if (!initialized) - exit(0); - lwp_destroy(SELF); + dprintf(("PyThread_exit_thread called\n")); + if (!initialized) + exit(0); + lwp_destroy(SELF); } /* @@ -60,54 +60,54 @@ void PyThread_exit_thread(void) */ PyThread_type_lock PyThread_allocate_lock(void) { - struct lock *lock; - extern char *malloc(size_t); - - 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; + 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); + 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; + 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); + 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/Python/thread_nt.h b/Python/thread_nt.h index e2e4443d86..2fd709817c 100644 --- a/Python/thread_nt.h +++ b/Python/thread_nt.h @@ -10,81 +10,81 @@ #endif typedef struct NRMUTEX { - LONG owned ; - DWORD thread_id ; - HANDLE hevent ; + LONG owned ; + DWORD thread_id ; + HANDLE hevent ; } NRMUTEX, *PNRMUTEX ; BOOL InitializeNonRecursiveMutex(PNRMUTEX mutex) { - mutex->owned = -1 ; /* No threads have entered NonRecursiveMutex */ - mutex->thread_id = 0 ; - mutex->hevent = CreateEvent(NULL, FALSE, FALSE, NULL) ; - return mutex->hevent != NULL ; /* TRUE if the mutex is created */ + mutex->owned = -1 ; /* No threads have entered NonRecursiveMutex */ + mutex->thread_id = 0 ; + mutex->hevent = CreateEvent(NULL, FALSE, FALSE, NULL) ; + return mutex->hevent != NULL ; /* TRUE if the mutex is created */ } VOID DeleteNonRecursiveMutex(PNRMUTEX mutex) { - /* No in-use check */ - CloseHandle(mutex->hevent) ; - mutex->hevent = NULL ; /* Just in case */ + /* No in-use check */ + CloseHandle(mutex->hevent) ; + mutex->hevent = NULL ; /* Just in case */ } DWORD EnterNonRecursiveMutex(PNRMUTEX mutex, DWORD milliseconds) { - /* Assume that the thread waits successfully */ - DWORD ret ; - - /* InterlockedIncrement(&mutex->owned) == 0 means that no thread currently owns the mutex */ - if (milliseconds == 0) - { - if (InterlockedCompareExchange(&mutex->owned, 0, -1) != -1) - return WAIT_TIMEOUT ; - ret = WAIT_OBJECT_0 ; - } - else - ret = InterlockedIncrement(&mutex->owned) ? - /* Some thread owns the mutex, let's wait... */ - WaitForSingleObject(mutex->hevent, milliseconds) : WAIT_OBJECT_0 ; - - mutex->thread_id = GetCurrentThreadId() ; /* We own it */ - return ret ; + /* Assume that the thread waits successfully */ + DWORD ret ; + + /* InterlockedIncrement(&mutex->owned) == 0 means that no thread currently owns the mutex */ + if (milliseconds == 0) + { + if (InterlockedCompareExchange(&mutex->owned, 0, -1) != -1) + return WAIT_TIMEOUT ; + ret = WAIT_OBJECT_0 ; + } + else + ret = InterlockedIncrement(&mutex->owned) ? + /* Some thread owns the mutex, let's wait... */ + WaitForSingleObject(mutex->hevent, milliseconds) : WAIT_OBJECT_0 ; + + mutex->thread_id = GetCurrentThreadId() ; /* We own it */ + return ret ; } BOOL LeaveNonRecursiveMutex(PNRMUTEX mutex) { - /* We don't own the mutex */ - mutex->thread_id = 0 ; - return - InterlockedDecrement(&mutex->owned) < 0 || - SetEvent(mutex->hevent) ; /* Other threads are waiting, wake one on them up */ + /* We don't own the mutex */ + mutex->thread_id = 0 ; + return + InterlockedDecrement(&mutex->owned) < 0 || + SetEvent(mutex->hevent) ; /* Other threads are waiting, wake one on them up */ } PNRMUTEX AllocNonRecursiveMutex(void) { - PNRMUTEX mutex = (PNRMUTEX)malloc(sizeof(NRMUTEX)) ; - if (mutex && !InitializeNonRecursiveMutex(mutex)) - { - free(mutex) ; - mutex = NULL ; - } - return mutex ; + PNRMUTEX mutex = (PNRMUTEX)malloc(sizeof(NRMUTEX)) ; + if (mutex && !InitializeNonRecursiveMutex(mutex)) + { + free(mutex) ; + mutex = NULL ; + } + return mutex ; } void FreeNonRecursiveMutex(PNRMUTEX mutex) { - if (mutex) - { - DeleteNonRecursiveMutex(mutex) ; - free(mutex) ; - } + if (mutex) + { + DeleteNonRecursiveMutex(mutex) ; + free(mutex) ; + } } long PyThread_get_thread_ident(void); @@ -102,8 +102,8 @@ PyThread__init_thread(void) */ typedef struct { - void (*func)(void*); - void *arg; + void (*func)(void*); + void *arg; } callobj; /* thunker to call adapt between the function type used by the system's @@ -115,66 +115,66 @@ static unsigned __stdcall #endif bootstrap(void *call) { - callobj *obj = (callobj*)call; - void (*func)(void*) = obj->func; - void *arg = obj->arg; - HeapFree(GetProcessHeap(), 0, obj); - func(arg); - return 0; + callobj *obj = (callobj*)call; + void (*func)(void*) = obj->func; + void *arg = obj->arg; + HeapFree(GetProcessHeap(), 0, obj); + func(arg); + return 0; } long PyThread_start_new_thread(void (*func)(void *), void *arg) { - HANDLE hThread; - unsigned threadID; - callobj *obj; - - dprintf(("%ld: PyThread_start_new_thread called\n", - PyThread_get_thread_ident())); - if (!initialized) - PyThread_init_thread(); - - obj = (callobj*)HeapAlloc(GetProcessHeap(), 0, sizeof(*obj)); - if (!obj) - return -1; - obj->func = func; - obj->arg = arg; + HANDLE hThread; + unsigned threadID; + callobj *obj; + + dprintf(("%ld: PyThread_start_new_thread called\n", + PyThread_get_thread_ident())); + if (!initialized) + PyThread_init_thread(); + + obj = (callobj*)HeapAlloc(GetProcessHeap(), 0, sizeof(*obj)); + if (!obj) + return -1; + obj->func = func; + obj->arg = arg; #if defined(MS_WINCE) - hThread = CreateThread(NULL, - Py_SAFE_DOWNCAST(_pythread_stacksize, Py_ssize_t, SIZE_T), - bootstrap, obj, 0, &threadID); + hThread = CreateThread(NULL, + Py_SAFE_DOWNCAST(_pythread_stacksize, Py_ssize_t, SIZE_T), + bootstrap, obj, 0, &threadID); #else - hThread = (HANDLE)_beginthreadex(0, - Py_SAFE_DOWNCAST(_pythread_stacksize, - Py_ssize_t, unsigned int), - bootstrap, obj, - 0, &threadID); + hThread = (HANDLE)_beginthreadex(0, + Py_SAFE_DOWNCAST(_pythread_stacksize, + Py_ssize_t, unsigned int), + bootstrap, obj, + 0, &threadID); #endif - if (hThread == 0) { + if (hThread == 0) { #if defined(MS_WINCE) - /* Save error in variable, to prevent PyThread_get_thread_ident - from clobbering it. */ - unsigned e = GetLastError(); - dprintf(("%ld: PyThread_start_new_thread failed, win32 error code %u\n", - PyThread_get_thread_ident(), e)); + /* Save error in variable, to prevent PyThread_get_thread_ident + from clobbering it. */ + unsigned e = GetLastError(); + dprintf(("%ld: PyThread_start_new_thread failed, win32 error code %u\n", + PyThread_get_thread_ident(), e)); #else - /* I've seen errno == EAGAIN here, which means "there are - * too many threads". - */ - int e = errno; - dprintf(("%ld: PyThread_start_new_thread failed, errno %d\n", - PyThread_get_thread_ident(), e)); + /* I've seen errno == EAGAIN here, which means "there are + * too many threads". + */ + int e = errno; + dprintf(("%ld: PyThread_start_new_thread failed, errno %d\n", + PyThread_get_thread_ident(), e)); #endif - threadID = (unsigned)-1; - HeapFree(GetProcessHeap(), 0, obj); - } - else { - dprintf(("%ld: PyThread_start_new_thread succeeded: %p\n", - PyThread_get_thread_ident(), (void*)hThread)); - CloseHandle(hThread); - } - return (long) threadID; + threadID = (unsigned)-1; + HeapFree(GetProcessHeap(), 0, obj); + } + else { + dprintf(("%ld: PyThread_start_new_thread succeeded: %p\n", + PyThread_get_thread_ident(), (void*)hThread)); + CloseHandle(hThread); + } + return (long) threadID; } /* @@ -184,22 +184,22 @@ PyThread_start_new_thread(void (*func)(void *), void *arg) long PyThread_get_thread_ident(void) { - if (!initialized) - PyThread_init_thread(); + if (!initialized) + PyThread_init_thread(); - return GetCurrentThreadId(); + return GetCurrentThreadId(); } void PyThread_exit_thread(void) { - dprintf(("%ld: PyThread_exit_thread called\n", PyThread_get_thread_ident())); - if (!initialized) - exit(0); + dprintf(("%ld: PyThread_exit_thread called\n", PyThread_get_thread_ident())); + if (!initialized) + exit(0); #if defined(MS_WINCE) - ExitThread(0); + ExitThread(0); #else - _endthreadex(0); + _endthreadex(0); #endif } @@ -211,25 +211,25 @@ PyThread_exit_thread(void) PyThread_type_lock PyThread_allocate_lock(void) { - PNRMUTEX aLock; + PNRMUTEX aLock; - dprintf(("PyThread_allocate_lock called\n")); - if (!initialized) - PyThread_init_thread(); + dprintf(("PyThread_allocate_lock called\n")); + if (!initialized) + PyThread_init_thread(); - aLock = AllocNonRecursiveMutex() ; + aLock = AllocNonRecursiveMutex() ; - dprintf(("%ld: PyThread_allocate_lock() -> %p\n", PyThread_get_thread_ident(), aLock)); + dprintf(("%ld: PyThread_allocate_lock() -> %p\n", PyThread_get_thread_ident(), aLock)); - return (PyThread_type_lock) aLock; + return (PyThread_type_lock) aLock; } void PyThread_free_lock(PyThread_type_lock aLock) { - dprintf(("%ld: PyThread_free_lock(%p) called\n", PyThread_get_thread_ident(),aLock)); + dprintf(("%ld: PyThread_free_lock(%p) called\n", PyThread_get_thread_ident(),aLock)); - FreeNonRecursiveMutex(aLock) ; + FreeNonRecursiveMutex(aLock) ; } /* @@ -241,48 +241,48 @@ PyThread_free_lock(PyThread_type_lock aLock) int PyThread_acquire_lock_timed(PyThread_type_lock aLock, PY_TIMEOUT_T microseconds) { - int success ; - PY_TIMEOUT_T milliseconds; + int success ; + PY_TIMEOUT_T milliseconds; - if (microseconds >= 0) { - milliseconds = microseconds / 1000; - if (microseconds % 1000 > 0) - ++milliseconds; - if ((DWORD) milliseconds != milliseconds) - Py_FatalError("Timeout too large for a DWORD, " - "please check PY_TIMEOUT_MAX"); - } - else - milliseconds = INFINITE; + if (microseconds >= 0) { + milliseconds = microseconds / 1000; + if (microseconds % 1000 > 0) + ++milliseconds; + if ((DWORD) milliseconds != milliseconds) + Py_FatalError("Timeout too large for a DWORD, " + "please check PY_TIMEOUT_MAX"); + } + else + milliseconds = INFINITE; - dprintf(("%ld: PyThread_acquire_lock_timed(%p, %lld) called\n", - PyThread_get_thread_ident(), aLock, microseconds)); + dprintf(("%ld: PyThread_acquire_lock_timed(%p, %lld) called\n", + PyThread_get_thread_ident(), aLock, microseconds)); - success = aLock && EnterNonRecursiveMutex((PNRMUTEX) aLock, (DWORD) milliseconds) == WAIT_OBJECT_0 ; + success = aLock && EnterNonRecursiveMutex((PNRMUTEX) aLock, (DWORD) milliseconds) == WAIT_OBJECT_0 ; - dprintf(("%ld: PyThread_acquire_lock(%p, %lld) -> %d\n", - PyThread_get_thread_ident(), aLock, microseconds, success)); + dprintf(("%ld: PyThread_acquire_lock(%p, %lld) -> %d\n", + PyThread_get_thread_ident(), aLock, microseconds, success)); - return success; + return success; } int PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag) { - return PyThread_acquire_lock_timed(aLock, waitflag ? -1 : 0); + return PyThread_acquire_lock_timed(aLock, waitflag ? -1 : 0); } void PyThread_release_lock(PyThread_type_lock aLock) { - dprintf(("%ld: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock)); + dprintf(("%ld: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock)); - if (!(aLock && LeaveNonRecursiveMutex((PNRMUTEX) aLock))) - dprintf(("%ld: Could not PyThread_release_lock(%p) error: %ld\n", PyThread_get_thread_ident(), aLock, GetLastError())); + if (!(aLock && LeaveNonRecursiveMutex((PNRMUTEX) aLock))) + dprintf(("%ld: Could not PyThread_release_lock(%p) error: %ld\n", PyThread_get_thread_ident(), aLock, GetLastError())); } /* minimum/maximum thread stack sizes supported */ -#define THREAD_MIN_STACKSIZE 0x8000 /* 32kB */ -#define THREAD_MAX_STACKSIZE 0x10000000 /* 256MB */ +#define THREAD_MIN_STACKSIZE 0x8000 /* 32kB */ +#define THREAD_MAX_STACKSIZE 0x10000000 /* 256MB */ /* set the thread stack size. * Return 0 if size is valid, -1 otherwise. @@ -290,22 +290,22 @@ PyThread_release_lock(PyThread_type_lock aLock) static int _pythread_nt_set_stacksize(size_t size) { - /* set to default */ - if (size == 0) { - _pythread_stacksize = 0; - return 0; - } - - /* valid range? */ - if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) { - _pythread_stacksize = size; - return 0; - } - - return -1; + /* 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) +#define THREAD_SET_STACKSIZE(x) _pythread_nt_set_stacksize(x) /* use native Windows TLS functions */ @@ -315,13 +315,13 @@ _pythread_nt_set_stacksize(size_t size) int PyThread_create_key(void) { - return (int) TlsAlloc(); + return (int) TlsAlloc(); } void PyThread_delete_key(int key) { - TlsFree(key); + TlsFree(key); } /* We must be careful to emulate the strange semantics implemented in thread.c, @@ -330,42 +330,42 @@ PyThread_delete_key(int key) int PyThread_set_key_value(int key, void *value) { - BOOL ok; - void *oldvalue; - - assert(value != NULL); - oldvalue = TlsGetValue(key); - if (oldvalue != NULL) - /* ignore value if already set */ - return 0; - ok = TlsSetValue(key, value); - if (!ok) - return -1; - return 0; + BOOL ok; + void *oldvalue; + + assert(value != NULL); + oldvalue = TlsGetValue(key); + if (oldvalue != NULL) + /* ignore value if already set */ + return 0; + ok = TlsSetValue(key, value); + if (!ok) + return -1; + return 0; } void * PyThread_get_key_value(int key) { - /* because TLS is used in the Py_END_ALLOW_THREAD macro, - * it is necessary to preserve the windows error state, because - * it is assumed to be preserved across the call to the macro. - * Ideally, the macro should be fixed, but it is simpler to - * do it here. - */ - DWORD error = GetLastError(); - void *result = TlsGetValue(key); - SetLastError(error); - return result; + /* because TLS is used in the Py_END_ALLOW_THREAD macro, + * it is necessary to preserve the windows error state, because + * it is assumed to be preserved across the call to the macro. + * Ideally, the macro should be fixed, but it is simpler to + * do it here. + */ + DWORD error = GetLastError(); + void *result = TlsGetValue(key); + SetLastError(error); + return result; } void PyThread_delete_key_value(int key) { - /* NULL is used as "key missing", and it is also the default - * given by TlsGetValue() if nothing has been set yet. - */ - TlsSetValue(key, NULL); + /* NULL is used as "key missing", and it is also the default + * given by TlsGetValue() if nothing has been set yet. + */ + TlsSetValue(key, NULL); } /* reinitialization of TLS is not necessary after fork when using diff --git a/Python/thread_os2.h b/Python/thread_os2.h index eee8de6337..1b264b5ad5 100644 --- a/Python/thread_os2.h +++ b/Python/thread_os2.h @@ -16,10 +16,10 @@ long PyThread_get_thread_ident(void); /* default thread stack size of 64kB */ #if !defined(THREAD_STACK_SIZE) -#define THREAD_STACK_SIZE 0x10000 +#define THREAD_STACK_SIZE 0x10000 #endif -#define OS2_STACKSIZE(x) (x ? x : THREAD_STACK_SIZE) +#define OS2_STACKSIZE(x) (x ? x : THREAD_STACK_SIZE) /* * Initialization of the C package, should not be needed. @@ -35,113 +35,113 @@ PyThread__init_thread(void) long PyThread_start_new_thread(void (*func)(void *), void *arg) { - int thread_id; + int thread_id; - thread_id = _beginthread(func, - NULL, - OS2_STACKSIZE(_pythread_stacksize), - arg); + thread_id = _beginthread(func, + NULL, + OS2_STACKSIZE(_pythread_stacksize), + arg); - if (thread_id == -1) { - dprintf(("_beginthread failed. return %ld\n", errno)); - } + if (thread_id == -1) { + dprintf(("_beginthread failed. return %ld\n", errno)); + } - return thread_id; + return thread_id; } long PyThread_get_thread_ident(void) { #if !defined(PYCC_GCC) - PPIB pib; - PTIB tib; + PPIB pib; + PTIB tib; #endif - if (!initialized) - PyThread_init_thread(); + if (!initialized) + PyThread_init_thread(); #if defined(PYCC_GCC) - return _gettid(); + return _gettid(); #else - DosGetInfoBlocks(&tib, &pib); - return tib->tib_ptib2->tib2_ultid; + DosGetInfoBlocks(&tib, &pib); + return tib->tib_ptib2->tib2_ultid; #endif } void PyThread_exit_thread(void) { - dprintf(("%ld: PyThread_exit_thread called\n", - PyThread_get_thread_ident())); - if (!initialized) - exit(0); - _endthread(); + dprintf(("%ld: PyThread_exit_thread called\n", + PyThread_get_thread_ident())); + if (!initialized) + exit(0); + _endthread(); } /* * Lock support. This is implemented with an event semaphore and critical - * sections to make it behave more like a posix mutex than its OS/2 + * sections to make it behave more like a posix mutex than its OS/2 * counterparts. */ typedef struct os2_lock_t { - int is_set; - HEV changed; + int is_set; + HEV changed; } *type_os2_lock; -PyThread_type_lock +PyThread_type_lock PyThread_allocate_lock(void) { #if defined(PYCC_GCC) - _fmutex *sem = malloc(sizeof(_fmutex)); - if (!initialized) - PyThread_init_thread(); - dprintf(("%ld: PyThread_allocate_lock() -> %lx\n", - PyThread_get_thread_ident(), - (long)sem)); - if (_fmutex_create(sem, 0)) { - free(sem); - sem = NULL; - } - return (PyThread_type_lock)sem; + _fmutex *sem = malloc(sizeof(_fmutex)); + if (!initialized) + PyThread_init_thread(); + dprintf(("%ld: PyThread_allocate_lock() -> %lx\n", + PyThread_get_thread_ident(), + (long)sem)); + if (_fmutex_create(sem, 0)) { + free(sem); + sem = NULL; + } + return (PyThread_type_lock)sem; #else - APIRET rc; - type_os2_lock lock = (type_os2_lock)malloc(sizeof(struct os2_lock_t)); + APIRET rc; + type_os2_lock lock = (type_os2_lock)malloc(sizeof(struct os2_lock_t)); - dprintf(("PyThread_allocate_lock called\n")); - if (!initialized) - PyThread_init_thread(); + dprintf(("PyThread_allocate_lock called\n")); + if (!initialized) + PyThread_init_thread(); - lock->is_set = 0; + lock->is_set = 0; - DosCreateEventSem(NULL, &lock->changed, 0, 0); + DosCreateEventSem(NULL, &lock->changed, 0, 0); - dprintf(("%ld: PyThread_allocate_lock() -> %p\n", - PyThread_get_thread_ident(), - lock->changed)); + dprintf(("%ld: PyThread_allocate_lock() -> %p\n", + PyThread_get_thread_ident(), + lock->changed)); - return (PyThread_type_lock)lock; + return (PyThread_type_lock)lock; #endif } -void +void PyThread_free_lock(PyThread_type_lock aLock) { #if !defined(PYCC_GCC) - type_os2_lock lock = (type_os2_lock)aLock; + type_os2_lock lock = (type_os2_lock)aLock; #endif - dprintf(("%ld: PyThread_free_lock(%p) called\n", - PyThread_get_thread_ident(),aLock)); + dprintf(("%ld: PyThread_free_lock(%p) called\n", + PyThread_get_thread_ident(),aLock)); #if defined(PYCC_GCC) - if (aLock) { - _fmutex_close((_fmutex *)aLock); - free((_fmutex *)aLock); - } + if (aLock) { + _fmutex_close((_fmutex *)aLock); + free((_fmutex *)aLock); + } #else - DosCloseEventSem(lock->changed); - free(aLock); + DosCloseEventSem(lock->changed); + free(aLock); #endif } @@ -150,98 +150,98 @@ PyThread_free_lock(PyThread_type_lock aLock) * * and 0 if the lock was not acquired. */ -int +int PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag) { #if !defined(PYCC_GCC) - int done = 0; - ULONG count; - PID pid = 0; - TID tid = 0; - type_os2_lock lock = (type_os2_lock)aLock; + int done = 0; + ULONG count; + PID pid = 0; + TID tid = 0; + type_os2_lock lock = (type_os2_lock)aLock; #endif - dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n", - PyThread_get_thread_ident(), - aLock, - waitflag)); + dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n", + PyThread_get_thread_ident(), + aLock, + waitflag)); #if defined(PYCC_GCC) - /* always successful if the lock doesn't exist */ - if (aLock && - _fmutex_request((_fmutex *)aLock, waitflag ? 0 : _FMR_NOWAIT)) - return 0; + /* always successful if the lock doesn't exist */ + if (aLock && + _fmutex_request((_fmutex *)aLock, waitflag ? 0 : _FMR_NOWAIT)) + return 0; #else - while (!done) { - /* if the lock is currently set, we have to wait for - * the state to change - */ - if (lock->is_set) { - if (!waitflag) - return 0; - DosWaitEventSem(lock->changed, SEM_INDEFINITE_WAIT); - } - - /* 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(); - } + 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; + return 1; } void PyThread_release_lock(PyThread_type_lock aLock) { #if !defined(PYCC_GCC) - type_os2_lock lock = (type_os2_lock)aLock; + type_os2_lock lock = (type_os2_lock)aLock; #endif - dprintf(("%ld: PyThread_release_lock(%p) called\n", - PyThread_get_thread_ident(), - aLock)); + dprintf(("%ld: PyThread_release_lock(%p) called\n", + PyThread_get_thread_ident(), + aLock)); #if defined(PYCC_GCC) - if (aLock) - _fmutex_release((_fmutex *)aLock); + if (aLock) + _fmutex_release((_fmutex *)aLock); #else - if (!lock->is_set) { - dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n", - PyThread_get_thread_ident(), - aLock, - GetLastError())); - return; - } - - if (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(); + 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 */ +#define THREAD_MIN_STACKSIZE 0x8000 /* 32kB */ +#define THREAD_MAX_STACKSIZE 0x2000000 /* 32MB */ /* set the thread stack size. * Return 0 if size is valid, -1 otherwise. @@ -249,19 +249,19 @@ PyThread_release_lock(PyThread_type_lock aLock) static int _pythread_os2_set_stacksize(size_t size) { - /* set to default */ - if (size == 0) { - _pythread_stacksize = 0; - return 0; - } - - /* valid range? */ - if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) { - _pythread_stacksize = size; - return 0; - } - - return -1; + /* 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) +#define THREAD_SET_STACKSIZE(x) _pythread_os2_set_stacksize(x) diff --git a/Python/thread_pth.h b/Python/thread_pth.h index f11e4848d9..82a00e72ba 100644 --- a/Python/thread_pth.h +++ b/Python/thread_pth.h @@ -3,7 +3,7 @@ http://www.gnu.org/software/pth 2000-05-03 Andy Dustman - Adapted from Posix threads interface + Adapted from Posix threads interface 12 May 1997 -- david arnold */ @@ -22,10 +22,10 @@ */ typedef struct { - char locked; /* 0=unlocked, 1=locked */ - /* a pair to handle an acquire of a locked lock */ - pth_cond_t lock_released; - pth_mutex_t mut; + char locked; /* 0=unlocked, 1=locked */ + /* a pair to handle an acquire of a locked lock */ + pth_cond_t lock_released; + pth_mutex_t mut; } pth_lock; #define CHECK_STATUS(name) if (status == -1) { printf("%d ", status); perror(name); error = 1; } @@ -38,10 +38,10 @@ pth_attr_t PyThread_attr; static void PyThread__init_thread(void) { - pth_init(); - PyThread_attr = pth_attr_new(); - pth_attr_set(PyThread_attr, PTH_ATTR_STACK_SIZE, 1<<18); - pth_attr_set(PyThread_attr, PTH_ATTR_JOINABLE, FALSE); + pth_init(); + PyThread_attr = pth_attr_new(); + pth_attr_set(PyThread_attr, PTH_ATTR_STACK_SIZE, 1<<18); + pth_attr_set(PyThread_attr, PTH_ATTR_JOINABLE, FALSE); } /* @@ -51,35 +51,35 @@ static void PyThread__init_thread(void) long PyThread_start_new_thread(void (*func)(void *), void *arg) { - pth_t th; - dprintf(("PyThread_start_new_thread called\n")); - if (!initialized) - PyThread_init_thread(); + pth_t th; + dprintf(("PyThread_start_new_thread called\n")); + if (!initialized) + PyThread_init_thread(); - th = pth_spawn(PyThread_attr, - (void* (*)(void *))func, - (void *)arg - ); + th = pth_spawn(PyThread_attr, + (void* (*)(void *))func, + (void *)arg + ); - return th; + return th; } long PyThread_get_thread_ident(void) { - volatile pth_t threadid; - if (!initialized) - PyThread_init_thread(); - /* Jump through some hoops for Alpha OSF/1 */ - threadid = pth_self(); - return (long) *(long *) &threadid; + volatile pth_t threadid; + if (!initialized) + PyThread_init_thread(); + /* Jump through some hoops for Alpha OSF/1 */ + threadid = pth_self(); + return (long) *(long *) &threadid; } void PyThread_exit_thread(void) { - dprintf(("PyThread_exit_thread called\n")); - if (!initialized) { - exit(0); - } + dprintf(("PyThread_exit_thread called\n")); + if (!initialized) { + exit(0); + } } /* @@ -87,92 +87,92 @@ void PyThread_exit_thread(void) */ PyThread_type_lock PyThread_allocate_lock(void) { - pth_lock *lock; - int status, error = 0; - - 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; + 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; + pth_lock *thelock = (pth_lock *)lock; - dprintf(("PyThread_free_lock(%p) called\n", lock)); + dprintf(("PyThread_free_lock(%p) called\n", lock)); - free((void *)thelock); + free((void *)thelock); } int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) { - int success; - pth_lock *thelock = (pth_lock *)lock; - int status, error = 0; - - 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; + 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"); } - if (error) success = 0; - dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); - return success; + thelock->locked = 1; + status = pth_mutex_release( &thelock->mut ); + CHECK_STATUS("pth_mutex_release[2]"); + success = 1; + } + if (error) success = 0; + dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); + return success; } void PyThread_release_lock(PyThread_type_lock lock) { - pth_lock *thelock = (pth_lock *)lock; - int status, error = 0; + pth_lock *thelock = (pth_lock *)lock; + int status, error = 0; - dprintf(("PyThread_release_lock(%p) called\n", lock)); + dprintf(("PyThread_release_lock(%p) called\n", lock)); - status = pth_mutex_acquire( &thelock->mut, 0, NULL ); - CHECK_STATUS("pth_mutex_acquire[3]"); + status = pth_mutex_acquire( &thelock->mut, 0, NULL ); + CHECK_STATUS("pth_mutex_acquire[3]"); - thelock->locked = 0; + thelock->locked = 0; - status = pth_mutex_release( &thelock->mut ); - CHECK_STATUS("pth_mutex_release[3]"); + status = pth_mutex_release( &thelock->mut ); + CHECK_STATUS("pth_mutex_release[3]"); - /* wake up someone (anyone, if any) waiting on the lock */ - status = pth_cond_notify( &thelock->lock_released, 0 ); - CHECK_STATUS("pth_cond_notify"); + /* wake up someone (anyone, if any) waiting on the lock */ + status = pth_cond_notify( &thelock->lock_released, 0 ); + CHECK_STATUS("pth_cond_notify"); } diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index f60f36dc2e..5e52b3977e 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -16,10 +16,10 @@ be conditional on _POSIX_THREAD_ATTR_STACKSIZE being defined. */ #ifdef _POSIX_THREAD_ATTR_STACKSIZE #ifndef THREAD_STACK_SIZE -#define THREAD_STACK_SIZE 0 /* use default stack size */ +#define THREAD_STACK_SIZE 0 /* use default stack size */ #endif /* for safety, ensure a viable minimum stacksize */ -#define THREAD_STACK_MIN 0x8000 /* 32kB */ +#define THREAD_STACK_MIN 0x8000 /* 32kB */ #else /* !_POSIX_THREAD_ATTR_STACKSIZE */ #ifdef THREAD_STACK_SIZE #error "THREAD_STACK_SIZE defined but _POSIX_THREAD_ATTR_STACKSIZE undefined" @@ -28,9 +28,9 @@ /* The POSIX spec says that implementations supporting the sem_* family of functions must indicate this by defining - _POSIX_SEMAPHORES. */ + _POSIX_SEMAPHORES. */ #ifdef _POSIX_SEMAPHORES -/* On FreeBSD 4.x, _POSIX_SEMAPHORES is defined empty, so +/* On FreeBSD 4.x, _POSIX_SEMAPHORES is defined empty, so we need to add 0 to make it work there as well. */ #if (_POSIX_SEMAPHORES+0) == -1 #define HAVE_BROKEN_POSIX_SEMAPHORES @@ -92,14 +92,14 @@ #define MICROSECONDS_TO_TIMESPEC(microseconds, ts) \ do { \ - struct timeval tv; \ - GETTIMEOFDAY(&tv); \ - tv.tv_usec += microseconds % 1000000; \ - tv.tv_sec += microseconds / 1000000; \ - tv.tv_sec += tv.tv_usec / 1000000; \ - tv.tv_usec %= 1000000; \ - ts.tv_sec = tv.tv_sec; \ - ts.tv_nsec = tv.tv_usec * 1000; \ + struct timeval tv; \ + GETTIMEOFDAY(&tv); \ + tv.tv_usec += microseconds % 1000000; \ + tv.tv_sec += microseconds / 1000000; \ + tv.tv_sec += tv.tv_usec / 1000000; \ + tv.tv_usec %= 1000000; \ + ts.tv_sec = tv.tv_sec; \ + ts.tv_nsec = tv.tv_usec * 1000; \ } while(0) @@ -119,10 +119,10 @@ do { \ */ typedef struct { - char locked; /* 0=unlocked, 1=locked */ - /* a pair to handle an acquire of a locked lock */ - pthread_cond_t lock_released; - pthread_mutex_t mut; + char locked; /* 0=unlocked, 1=locked */ + /* a pair to handle an acquire of a locked lock */ + pthread_cond_t lock_released; + pthread_mutex_t mut; } pthread_lock; #define CHECK_STATUS(name) if (status != 0) { perror(name); error = 1; } @@ -140,11 +140,11 @@ void _noop(void) static void PyThread__init_thread(void) { - /* DO AN INIT BY STARTING THE THREAD */ - static int dummy = 0; - pthread_t thread1; - pthread_create(&thread1, NULL, (void *) _noop, &dummy); - pthread_join(thread1, NULL); + /* DO AN INIT BY STARTING THE THREAD */ + static int dummy = 0; + pthread_t thread1; + pthread_create(&thread1, NULL, (void *) _noop, &dummy); + pthread_join(thread1, NULL); } #else /* !_HAVE_BSDI */ @@ -153,7 +153,7 @@ static void PyThread__init_thread(void) { #if defined(_AIX) && defined(__GNUC__) - pthread_init(); + pthread_init(); #endif } @@ -167,59 +167,59 @@ PyThread__init_thread(void) long PyThread_start_new_thread(void (*func)(void *), void *arg) { - pthread_t th; - int status; + pthread_t th; + int status; #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) - pthread_attr_t attrs; + pthread_attr_t attrs; #endif #if defined(THREAD_STACK_SIZE) - size_t tss; + size_t tss; #endif - dprintf(("PyThread_start_new_thread called\n")); - if (!initialized) - PyThread_init_thread(); + dprintf(("PyThread_start_new_thread called\n")); + if (!initialized) + PyThread_init_thread(); #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) - if (pthread_attr_init(&attrs) != 0) - return -1; + if (pthread_attr_init(&attrs) != 0) + return -1; #endif #if defined(THREAD_STACK_SIZE) - tss = (_pythread_stacksize != 0) ? _pythread_stacksize - : THREAD_STACK_SIZE; - if (tss != 0) { - if (pthread_attr_setstacksize(&attrs, tss) != 0) { - pthread_attr_destroy(&attrs); - return -1; - } - } + tss = (_pythread_stacksize != 0) ? _pythread_stacksize + : THREAD_STACK_SIZE; + if (tss != 0) { + if (pthread_attr_setstacksize(&attrs, tss) != 0) { + pthread_attr_destroy(&attrs); + return -1; + } + } #endif #if defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) - pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM); + pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM); #endif - status = pthread_create(&th, + status = pthread_create(&th, #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) - &attrs, + &attrs, #else - (pthread_attr_t*)NULL, + (pthread_attr_t*)NULL, #endif - (void* (*)(void *))func, - (void *)arg - ); + (void* (*)(void *))func, + (void *)arg + ); #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) - pthread_attr_destroy(&attrs); + pthread_attr_destroy(&attrs); #endif - if (status != 0) - return -1; + if (status != 0) + return -1; - pthread_detach(th); + pthread_detach(th); #if SIZEOF_PTHREAD_T <= SIZEOF_LONG - return (long) th; + return (long) th; #else - return (long) *(long *) &th; + return (long) *(long *) &th; #endif } @@ -230,28 +230,28 @@ PyThread_start_new_thread(void (*func)(void *), void *arg) - It is not clear that the 'volatile' (for AIX?) and ugly casting in the latter return statement (for Alpha OSF/1) are any longer necessary. */ -long +long PyThread_get_thread_ident(void) { - volatile pthread_t threadid; - if (!initialized) - PyThread_init_thread(); - /* Jump through some hoops for Alpha OSF/1 */ - threadid = pthread_self(); + volatile pthread_t threadid; + if (!initialized) + PyThread_init_thread(); + /* Jump through some hoops for Alpha OSF/1 */ + threadid = pthread_self(); #if SIZEOF_PTHREAD_T <= SIZEOF_LONG - return (long) threadid; + return (long) threadid; #else - return (long) *(long *) &threadid; + return (long) *(long *) &threadid; #endif } -void +void PyThread_exit_thread(void) { - dprintf(("PyThread_exit_thread called\n")); - if (!initialized) { - exit(0); - } + dprintf(("PyThread_exit_thread called\n")); + if (!initialized) { + exit(0); + } } #ifdef USE_SEMAPHORES @@ -260,47 +260,47 @@ PyThread_exit_thread(void) * Lock support. */ -PyThread_type_lock +PyThread_type_lock PyThread_allocate_lock(void) { - sem_t *lock; - int status, error = 0; + sem_t *lock; + int status, error = 0; - dprintf(("PyThread_allocate_lock called\n")); - if (!initialized) - PyThread_init_thread(); + dprintf(("PyThread_allocate_lock called\n")); + if (!initialized) + PyThread_init_thread(); - lock = (sem_t *)malloc(sizeof(sem_t)); + lock = (sem_t *)malloc(sizeof(sem_t)); - if (lock) { - status = sem_init(lock,0,1); - CHECK_STATUS("sem_init"); + if (lock) { + status = sem_init(lock,0,1); + CHECK_STATUS("sem_init"); - if (error) { - free((void *)lock); - lock = NULL; - } - } + if (error) { + free((void *)lock); + lock = NULL; + } + } - dprintf(("PyThread_allocate_lock() -> %p\n", lock)); - return (PyThread_type_lock)lock; + dprintf(("PyThread_allocate_lock() -> %p\n", lock)); + return (PyThread_type_lock)lock; } -void +void PyThread_free_lock(PyThread_type_lock lock) { - sem_t *thelock = (sem_t *)lock; - int status, error = 0; + sem_t *thelock = (sem_t *)lock; + int status, error = 0; - dprintf(("PyThread_free_lock(%p) called\n", lock)); + dprintf(("PyThread_free_lock(%p) called\n", lock)); - if (!thelock) - return; + if (!thelock) + return; - status = sem_destroy(thelock); - CHECK_STATUS("sem_destroy"); + status = sem_destroy(thelock); + CHECK_STATUS("sem_destroy"); - free((void *)thelock); + free((void *)thelock); } /* @@ -312,66 +312,66 @@ PyThread_free_lock(PyThread_type_lock lock) static int fix_status(int status) { - return (status == -1) ? errno : status; + return (status == -1) ? errno : status; } int PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds) { - int success; - sem_t *thelock = (sem_t *)lock; - int status, error = 0; - struct timespec ts; - - dprintf(("PyThread_acquire_lock_timed(%p, %lld) called\n", - lock, microseconds)); - - if (microseconds > 0) - MICROSECONDS_TO_TIMESPEC(microseconds, ts); - do { - if (microseconds > 0) - status = fix_status(sem_timedwait(thelock, &ts)); - else if (microseconds == 0) - status = fix_status(sem_trywait(thelock)); - else - status = fix_status(sem_wait(thelock)); - } while (status == EINTR); /* Retry if interrupted by a signal */ - - if (microseconds > 0) { - if (status != ETIMEDOUT) - CHECK_STATUS("sem_timedwait"); - } - else if (microseconds == 0) { - if (status != EAGAIN) - CHECK_STATUS("sem_trywait"); - } - else { - CHECK_STATUS("sem_wait"); - } - - success = (status == 0) ? 1 : 0; - - dprintf(("PyThread_acquire_lock_timed(%p, %lld) -> %d\n", - lock, microseconds, success)); - return success; + int success; + sem_t *thelock = (sem_t *)lock; + int status, error = 0; + struct timespec ts; + + dprintf(("PyThread_acquire_lock_timed(%p, %lld) called\n", + lock, microseconds)); + + if (microseconds > 0) + MICROSECONDS_TO_TIMESPEC(microseconds, ts); + do { + if (microseconds > 0) + status = fix_status(sem_timedwait(thelock, &ts)); + else if (microseconds == 0) + status = fix_status(sem_trywait(thelock)); + else + status = fix_status(sem_wait(thelock)); + } while (status == EINTR); /* Retry if interrupted by a signal */ + + if (microseconds > 0) { + if (status != ETIMEDOUT) + CHECK_STATUS("sem_timedwait"); + } + else if (microseconds == 0) { + if (status != EAGAIN) + CHECK_STATUS("sem_trywait"); + } + else { + CHECK_STATUS("sem_wait"); + } + + success = (status == 0) ? 1 : 0; + + dprintf(("PyThread_acquire_lock_timed(%p, %lld) -> %d\n", + lock, microseconds, success)); + return success; } -int +int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) { - return PyThread_acquire_lock_timed(lock, waitflag ? -1 : 0); + return PyThread_acquire_lock_timed(lock, waitflag ? -1 : 0); } -void +void PyThread_release_lock(PyThread_type_lock lock) { - sem_t *thelock = (sem_t *)lock; - int status, error = 0; + sem_t *thelock = (sem_t *)lock; + int status, error = 0; - dprintf(("PyThread_release_lock(%p) called\n", lock)); + dprintf(("PyThread_release_lock(%p) called\n", lock)); - status = sem_post(thelock); - CHECK_STATUS("sem_post"); + status = sem_post(thelock); + CHECK_STATUS("sem_post"); } #else /* USE_SEMAPHORES */ @@ -379,137 +379,137 @@ PyThread_release_lock(PyThread_type_lock lock) /* * Lock support. */ -PyThread_type_lock +PyThread_type_lock PyThread_allocate_lock(void) { - pthread_lock *lock; - int status, error = 0; - - 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"); - /* Mark the pthread mutex underlying a Python mutex as - pure happens-before. We can't simply mark the - Python-level mutex as a mutex because it can be - acquired and released in different threads, which - will cause errors. */ - _Py_ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&lock->mut); - - status = pthread_cond_init(&lock->lock_released, - pthread_condattr_default); - CHECK_STATUS("pthread_cond_init"); - - if (error) { - free((void *)lock); - lock = 0; - } - } - - dprintf(("PyThread_allocate_lock() -> %p\n", lock)); - return (PyThread_type_lock) lock; + 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"); + /* Mark the pthread mutex underlying a Python mutex as + pure happens-before. We can't simply mark the + Python-level mutex as a mutex because it can be + acquired and released in different threads, which + will cause errors. */ + _Py_ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&lock->mut); + + status = pthread_cond_init(&lock->lock_released, + pthread_condattr_default); + CHECK_STATUS("pthread_cond_init"); + + if (error) { + free((void *)lock); + lock = 0; + } + } + + dprintf(("PyThread_allocate_lock() -> %p\n", lock)); + return (PyThread_type_lock) lock; } -void +void PyThread_free_lock(PyThread_type_lock lock) { - pthread_lock *thelock = (pthread_lock *)lock; - int status, error = 0; + pthread_lock *thelock = (pthread_lock *)lock; + int status, error = 0; - dprintf(("PyThread_free_lock(%p) called\n", lock)); + dprintf(("PyThread_free_lock(%p) called\n", lock)); - status = pthread_mutex_destroy( &thelock->mut ); - CHECK_STATUS("pthread_mutex_destroy"); + status = pthread_mutex_destroy( &thelock->mut ); + CHECK_STATUS("pthread_mutex_destroy"); - status = pthread_cond_destroy( &thelock->lock_released ); - CHECK_STATUS("pthread_cond_destroy"); + status = pthread_cond_destroy( &thelock->lock_released ); + CHECK_STATUS("pthread_cond_destroy"); - free((void *)thelock); + free((void *)thelock); } int PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds) { - int success; - pthread_lock *thelock = (pthread_lock *)lock; - int status, error = 0; - - dprintf(("PyThread_acquire_lock_timed(%p, %lld) called\n", - lock, microseconds)); - - status = pthread_mutex_lock( &thelock->mut ); - CHECK_STATUS("pthread_mutex_lock[1]"); - success = thelock->locked == 0; - - if (!success && microseconds != 0) { - struct timespec ts; - if (microseconds > 0) - MICROSECONDS_TO_TIMESPEC(microseconds, ts); - /* continue trying until we get the lock */ - - /* mut must be locked by me -- part of the condition - * protocol */ - while (thelock->locked) { - if (microseconds > 0) { - status = pthread_cond_timedwait( - &thelock->lock_released, - &thelock->mut, &ts); - if (status == ETIMEDOUT) - break; - CHECK_STATUS("pthread_cond_timed_wait"); - } - else { - status = pthread_cond_wait( - &thelock->lock_released, - &thelock->mut); - CHECK_STATUS("pthread_cond_wait"); - } - } - success = (status == 0); - } - if (success) thelock->locked = 1; - status = pthread_mutex_unlock( &thelock->mut ); - CHECK_STATUS("pthread_mutex_unlock[1]"); - - if (error) success = 0; - dprintf(("PyThread_acquire_lock_timed(%p, %lld) -> %d\n", - lock, microseconds, success)); - return success; + int success; + pthread_lock *thelock = (pthread_lock *)lock; + int status, error = 0; + + dprintf(("PyThread_acquire_lock_timed(%p, %lld) called\n", + lock, microseconds)); + + status = pthread_mutex_lock( &thelock->mut ); + CHECK_STATUS("pthread_mutex_lock[1]"); + success = thelock->locked == 0; + + if (!success && microseconds != 0) { + struct timespec ts; + if (microseconds > 0) + MICROSECONDS_TO_TIMESPEC(microseconds, ts); + /* continue trying until we get the lock */ + + /* mut must be locked by me -- part of the condition + * protocol */ + while (thelock->locked) { + if (microseconds > 0) { + status = pthread_cond_timedwait( + &thelock->lock_released, + &thelock->mut, &ts); + if (status == ETIMEDOUT) + break; + CHECK_STATUS("pthread_cond_timed_wait"); + } + else { + status = pthread_cond_wait( + &thelock->lock_released, + &thelock->mut); + CHECK_STATUS("pthread_cond_wait"); + } + } + success = (status == 0); + } + if (success) thelock->locked = 1; + status = pthread_mutex_unlock( &thelock->mut ); + CHECK_STATUS("pthread_mutex_unlock[1]"); + + if (error) success = 0; + dprintf(("PyThread_acquire_lock_timed(%p, %lld) -> %d\n", + lock, microseconds, success)); + return success; } -int +int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) { - return PyThread_acquire_lock_timed(lock, waitflag ? -1 : 0); + return PyThread_acquire_lock_timed(lock, waitflag ? -1 : 0); } -void +void PyThread_release_lock(PyThread_type_lock lock) { - pthread_lock *thelock = (pthread_lock *)lock; - int status, error = 0; + pthread_lock *thelock = (pthread_lock *)lock; + int status, error = 0; - dprintf(("PyThread_release_lock(%p) called\n", lock)); + dprintf(("PyThread_release_lock(%p) called\n", lock)); - status = pthread_mutex_lock( &thelock->mut ); - CHECK_STATUS("pthread_mutex_lock[3]"); + status = pthread_mutex_lock( &thelock->mut ); + CHECK_STATUS("pthread_mutex_lock[3]"); - thelock->locked = 0; + thelock->locked = 0; - status = pthread_mutex_unlock( &thelock->mut ); - CHECK_STATUS("pthread_mutex_unlock[3]"); + status = pthread_mutex_unlock( &thelock->mut ); + CHECK_STATUS("pthread_mutex_unlock[3]"); - /* wake up someone (anyone, if any) waiting on the lock */ - status = pthread_cond_signal( &thelock->lock_released ); - CHECK_STATUS("pthread_cond_signal"); + /* wake up someone (anyone, if any) waiting on the lock */ + status = pthread_cond_signal( &thelock->lock_released ); + CHECK_STATUS("pthread_cond_signal"); } #endif /* USE_SEMAPHORES */ @@ -522,39 +522,39 @@ static int _pythread_pthread_set_stacksize(size_t size) { #if defined(THREAD_STACK_SIZE) - pthread_attr_t attrs; - size_t tss_min; - int rc = 0; + pthread_attr_t attrs; + size_t tss_min; + int rc = 0; #endif - /* set to default */ - if (size == 0) { - _pythread_stacksize = 0; - return 0; - } + /* set to default */ + if (size == 0) { + _pythread_stacksize = 0; + return 0; + } #if defined(THREAD_STACK_SIZE) #if defined(PTHREAD_STACK_MIN) - tss_min = PTHREAD_STACK_MIN > THREAD_STACK_MIN ? PTHREAD_STACK_MIN - : THREAD_STACK_MIN; + tss_min = PTHREAD_STACK_MIN > THREAD_STACK_MIN ? PTHREAD_STACK_MIN + : THREAD_STACK_MIN; #else - tss_min = THREAD_STACK_MIN; + tss_min = THREAD_STACK_MIN; #endif - if (size >= tss_min) { - /* validate stack size by setting thread attribute */ - if (pthread_attr_init(&attrs) == 0) { - rc = pthread_attr_setstacksize(&attrs, size); - pthread_attr_destroy(&attrs); - if (rc == 0) { - _pythread_stacksize = size; - return 0; - } - } - } - return -1; + if (size >= tss_min) { + /* validate stack size by setting thread attribute */ + if (pthread_attr_init(&attrs) == 0) { + rc = pthread_attr_setstacksize(&attrs, size); + pthread_attr_destroy(&attrs); + if (rc == 0) { + _pythread_stacksize = size; + return 0; + } + } + } + return -1; #else - return -2; + return -2; #endif } -#define THREAD_SET_STACKSIZE(x) _pythread_pthread_set_stacksize(x) +#define THREAD_SET_STACKSIZE(x) _pythread_pthread_set_stacksize(x) diff --git a/Python/thread_sgi.h b/Python/thread_sgi.h index 4f4b210a28..771ab2cc60 100644 --- a/Python/thread_sgi.h +++ b/Python/thread_sgi.h @@ -8,67 +8,67 @@ #include #include -#define HDR_SIZE 2680 /* sizeof(ushdr_t) */ -#define MAXPROC 100 /* max # of threads that can be started */ +#define HDR_SIZE 2680 /* sizeof(ushdr_t) */ +#define MAXPROC 100 /* max # of threads that can be started */ static usptr_t *shared_arena; -static ulock_t count_lock; /* protection for some variables */ -static ulock_t wait_lock; /* lock used to wait for other threads */ -static int waiting_for_threads; /* protected by count_lock */ -static int nthreads; /* protected by count_lock */ +static ulock_t count_lock; /* protection for some variables */ +static ulock_t wait_lock; /* lock used to wait for other threads */ +static int waiting_for_threads; /* protected by count_lock */ +static int nthreads; /* protected by count_lock */ static int exit_status; -static int exiting; /* we're already exiting (for maybe_exit) */ -static pid_t my_pid; /* PID of main thread */ +static int exiting; /* we're already exiting (for maybe_exit) */ +static pid_t my_pid; /* PID of main thread */ static struct pidlist { - pid_t parent; - pid_t child; -} pidlist[MAXPROC]; /* PIDs of other threads; protected by count_lock */ -static int maxpidindex; /* # of PIDs in pidlist */ + pid_t parent; + pid_t child; +} pidlist[MAXPROC]; /* PIDs of other threads; protected by count_lock */ +static int maxpidindex; /* # of PIDs in pidlist */ /* * Initialization. */ static void PyThread__init_thread(void) { #ifdef USE_DL - long addr, size; + long addr, size; #endif /* USE_DL */ #ifdef USE_DL - if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0) - perror("usconfig - CONF_INITSIZE (check)"); - if (usconfig(CONF_INITSIZE, size) < 0) - perror("usconfig - CONF_INITSIZE (reset)"); - addr = (long) dl_getrange(size + HDR_SIZE); - dprintf(("trying to use addr %p-%p for shared arena\n", addr, addr+size)); - errno = 0; - if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 && errno != 0) - perror("usconfig - CONF_ATTACHADDR (set)"); + if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0) + perror("usconfig - CONF_INITSIZE (check)"); + if (usconfig(CONF_INITSIZE, size) < 0) + perror("usconfig - CONF_INITSIZE (reset)"); + addr = (long) dl_getrange(size + HDR_SIZE); + dprintf(("trying to use addr %p-%p for shared arena\n", addr, addr+size)); + errno = 0; + if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 && errno != 0) + perror("usconfig - CONF_ATTACHADDR (set)"); #endif /* USE_DL */ - if (usconfig(CONF_INITUSERS, 16) < 0) - perror("usconfig - CONF_INITUSERS"); - my_pid = getpid(); /* so that we know which is the main thread */ - if (usconfig(CONF_ARENATYPE, US_SHAREDONLY) < 0) - perror("usconfig - CONF_ARENATYPE"); - usconfig(CONF_LOCKTYPE, US_DEBUG); /* XXX */ + if (usconfig(CONF_INITUSERS, 16) < 0) + perror("usconfig - CONF_INITUSERS"); + my_pid = getpid(); /* so that we know which is the main thread */ + if (usconfig(CONF_ARENATYPE, US_SHAREDONLY) < 0) + perror("usconfig - CONF_ARENATYPE"); + usconfig(CONF_LOCKTYPE, US_DEBUG); /* XXX */ #ifdef Py_DEBUG - if (thread_debug & 4) - usconfig(CONF_LOCKTYPE, US_DEBUGPLUS); - else if (thread_debug & 2) - usconfig(CONF_LOCKTYPE, US_DEBUG); + if (thread_debug & 4) + usconfig(CONF_LOCKTYPE, US_DEBUGPLUS); + else if (thread_debug & 2) + usconfig(CONF_LOCKTYPE, US_DEBUG); #endif /* Py_DEBUG */ - if ((shared_arena = usinit(tmpnam(0))) == 0) - perror("usinit"); + if ((shared_arena = usinit(tmpnam(0))) == 0) + perror("usinit"); #ifdef USE_DL - if (usconfig(CONF_ATTACHADDR, addr) < 0) /* reset address */ - perror("usconfig - CONF_ATTACHADDR (reset)"); + if (usconfig(CONF_ATTACHADDR, addr) < 0) /* reset address */ + perror("usconfig - CONF_ATTACHADDR (reset)"); #endif /* USE_DL */ - if ((count_lock = usnewlock(shared_arena)) == NULL) - perror("usnewlock (count_lock)"); - (void) usinitlock(count_lock); - if ((wait_lock = usnewlock(shared_arena)) == NULL) - perror("usnewlock (wait_lock)"); - dprintf(("arena start: %p, arena size: %ld\n", shared_arena, (long) usconfig(CONF_GETSIZE, shared_arena))); + if ((count_lock = usnewlock(shared_arena)) == NULL) + perror("usnewlock (count_lock)"); + (void) usinitlock(count_lock); + if ((wait_lock = usnewlock(shared_arena)) == NULL) + perror("usnewlock (wait_lock)"); + dprintf(("arena start: %p, arena size: %ld\n", shared_arena, (long) usconfig(CONF_GETSIZE, shared_arena))); } /* @@ -77,138 +77,138 @@ static void PyThread__init_thread(void) static void clean_threads(void) { - int i, j; - pid_t mypid, pid; + int i, j; + pid_t mypid, pid; - /* clean up any exited threads */ - mypid = getpid(); - i = 0; - while (i < maxpidindex) { - if (pidlist[i].parent == mypid && (pid = pidlist[i].child) > 0) { - pid = waitpid(pid, 0, WNOHANG); - if (pid > 0) { - /* a thread has exited */ - pidlist[i] = pidlist[--maxpidindex]; - /* remove references to children of dead proc */ - for (j = 0; j < maxpidindex; j++) - if (pidlist[j].parent == pid) - pidlist[j].child = -1; - continue; /* don't increment i */ - } - } - i++; - } - /* clean up the list */ - i = 0; - while (i < maxpidindex) { - if (pidlist[i].child == -1) { - pidlist[i] = pidlist[--maxpidindex]; - continue; /* don't increment i */ - } - i++; - } + /* clean up any exited threads */ + mypid = getpid(); + i = 0; + while (i < maxpidindex) { + if (pidlist[i].parent == mypid && (pid = pidlist[i].child) > 0) { + pid = waitpid(pid, 0, WNOHANG); + if (pid > 0) { + /* a thread has exited */ + pidlist[i] = pidlist[--maxpidindex]; + /* remove references to children of dead proc */ + for (j = 0; j < maxpidindex; j++) + if (pidlist[j].parent == pid) + pidlist[j].child = -1; + continue; /* don't increment i */ + } + } + i++; + } + /* clean up the list */ + i = 0; + while (i < maxpidindex) { + if (pidlist[i].child == -1) { + pidlist[i] = pidlist[--maxpidindex]; + continue; /* don't increment i */ + } + i++; + } } long PyThread_start_new_thread(void (*func)(void *), void *arg) { #ifdef USE_DL - long addr, size; - static int local_initialized = 0; + long addr, size; + static int local_initialized = 0; #endif /* USE_DL */ - int success = 0; /* init not needed when SOLARIS_THREADS and */ - /* C_THREADS implemented properly */ + int success = 0; /* init not needed when SOLARIS_THREADS and */ + /* C_THREADS implemented properly */ - dprintf(("PyThread_start_new_thread called\n")); - if (!initialized) - PyThread_init_thread(); - switch (ussetlock(count_lock)) { - case 0: return 0; - case -1: perror("ussetlock (count_lock)"); - } - if (maxpidindex >= MAXPROC) - success = -1; - else { + dprintf(("PyThread_start_new_thread called\n")); + if (!initialized) + PyThread_init_thread(); + switch (ussetlock(count_lock)) { + case 0: return 0; + case -1: perror("ussetlock (count_lock)"); + } + if (maxpidindex >= MAXPROC) + success = -1; + else { #ifdef USE_DL - if (!local_initialized) { - if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0) - perror("usconfig - CONF_INITSIZE (check)"); - if (usconfig(CONF_INITSIZE, size) < 0) - perror("usconfig - CONF_INITSIZE (reset)"); - addr = (long) dl_getrange(size + HDR_SIZE); - dprintf(("trying to use addr %p-%p for sproc\n", - addr, addr+size)); - errno = 0; - if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 && - errno != 0) - perror("usconfig - CONF_ATTACHADDR (set)"); - } + if (!local_initialized) { + if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0) + perror("usconfig - CONF_INITSIZE (check)"); + if (usconfig(CONF_INITSIZE, size) < 0) + perror("usconfig - CONF_INITSIZE (reset)"); + addr = (long) dl_getrange(size + HDR_SIZE); + dprintf(("trying to use addr %p-%p for sproc\n", + addr, addr+size)); + errno = 0; + if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 && + errno != 0) + perror("usconfig - CONF_ATTACHADDR (set)"); + } #endif /* USE_DL */ - clean_threads(); - if ((success = sproc(func, PR_SALL, arg)) < 0) - perror("sproc"); + clean_threads(); + if ((success = sproc(func, PR_SALL, arg)) < 0) + perror("sproc"); #ifdef USE_DL - if (!local_initialized) { - if (usconfig(CONF_ATTACHADDR, addr) < 0) - /* reset address */ - perror("usconfig - CONF_ATTACHADDR (reset)"); - local_initialized = 1; - } + if (!local_initialized) { + if (usconfig(CONF_ATTACHADDR, addr) < 0) + /* reset address */ + perror("usconfig - CONF_ATTACHADDR (reset)"); + local_initialized = 1; + } #endif /* USE_DL */ - if (success >= 0) { - nthreads++; - pidlist[maxpidindex].parent = getpid(); - pidlist[maxpidindex++].child = success; - dprintf(("pidlist[%d] = %d\n", - maxpidindex-1, success)); - } - } - if (usunsetlock(count_lock) < 0) - perror("usunsetlock (count_lock)"); - return success; + if (success >= 0) { + nthreads++; + pidlist[maxpidindex].parent = getpid(); + pidlist[maxpidindex++].child = success; + dprintf(("pidlist[%d] = %d\n", + maxpidindex-1, success)); + } + } + if (usunsetlock(count_lock) < 0) + perror("usunsetlock (count_lock)"); + return success; } long PyThread_get_thread_ident(void) { - return getpid(); + return getpid(); } void PyThread_exit_thread(void) { - dprintf(("PyThread_exit_thread called\n")); - if (!initialized) - exit(0); - if (ussetlock(count_lock) < 0) - perror("ussetlock (count_lock)"); - nthreads--; - if (getpid() == my_pid) { - /* main thread; wait for other threads to exit */ - exiting = 1; - waiting_for_threads = 1; - if (ussetlock(wait_lock) < 0) - perror("ussetlock (wait_lock)"); - for (;;) { - if (nthreads < 0) { - dprintf(("really exit (%d)\n", exit_status)); - exit(exit_status); - } - if (usunsetlock(count_lock) < 0) - perror("usunsetlock (count_lock)"); - dprintf(("waiting for other threads (%d)\n", nthreads)); - if (ussetlock(wait_lock) < 0) - perror("ussetlock (wait_lock)"); - if (ussetlock(count_lock) < 0) - perror("ussetlock (count_lock)"); - } - } - /* not the main thread */ - if (waiting_for_threads) { - dprintf(("main thread is waiting\n")); - if (usunsetlock(wait_lock) < 0) - perror("usunsetlock (wait_lock)"); - } - if (usunsetlock(count_lock) < 0) - perror("usunsetlock (count_lock)"); - _exit(0); + dprintf(("PyThread_exit_thread called\n")); + if (!initialized) + exit(0); + if (ussetlock(count_lock) < 0) + perror("ussetlock (count_lock)"); + nthreads--; + if (getpid() == my_pid) { + /* main thread; wait for other threads to exit */ + exiting = 1; + waiting_for_threads = 1; + if (ussetlock(wait_lock) < 0) + perror("ussetlock (wait_lock)"); + for (;;) { + if (nthreads < 0) { + dprintf(("really exit (%d)\n", exit_status)); + exit(exit_status); + } + if (usunsetlock(count_lock) < 0) + perror("usunsetlock (count_lock)"); + dprintf(("waiting for other threads (%d)\n", nthreads)); + if (ussetlock(wait_lock) < 0) + perror("ussetlock (wait_lock)"); + if (ussetlock(count_lock) < 0) + perror("ussetlock (count_lock)"); + } + } + /* not the main thread */ + if (waiting_for_threads) { + dprintf(("main thread is waiting\n")); + if (usunsetlock(wait_lock) < 0) + perror("usunsetlock (wait_lock)"); + } + if (usunsetlock(count_lock) < 0) + perror("usunsetlock (count_lock)"); + _exit(0); } /* @@ -216,44 +216,44 @@ void PyThread_exit_thread(void) */ PyThread_type_lock PyThread_allocate_lock(void) { - ulock_t lock; + ulock_t lock; - dprintf(("PyThread_allocate_lock called\n")); - if (!initialized) - PyThread_init_thread(); + dprintf(("PyThread_allocate_lock called\n")); + if (!initialized) + PyThread_init_thread(); - if ((lock = usnewlock(shared_arena)) == NULL) - perror("usnewlock"); - (void) usinitlock(lock); - dprintf(("PyThread_allocate_lock() -> %p\n", lock)); - return (PyThread_type_lock) lock; + if ((lock = usnewlock(shared_arena)) == NULL) + perror("usnewlock"); + (void) usinitlock(lock); + dprintf(("PyThread_allocate_lock() -> %p\n", lock)); + return (PyThread_type_lock) lock; } void PyThread_free_lock(PyThread_type_lock lock) { - dprintf(("PyThread_free_lock(%p) called\n", lock)); - usfreelock((ulock_t) lock, shared_arena); + dprintf(("PyThread_free_lock(%p) called\n", lock)); + usfreelock((ulock_t) lock, shared_arena); } int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) { - int success; + int success; - dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); - errno = 0; /* clear it just in case */ - if (waitflag) - success = ussetlock((ulock_t) lock); - else - success = uscsetlock((ulock_t) lock, 1); /* Try it once */ - if (success < 0) - perror(waitflag ? "ussetlock" : "uscsetlock"); - dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); - return success; + dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); + errno = 0; /* clear it just in case */ + if (waitflag) + success = ussetlock((ulock_t) lock); + else + success = uscsetlock((ulock_t) lock, 1); /* Try it once */ + if (success < 0) + perror(waitflag ? "ussetlock" : "uscsetlock"); + dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); + return success; } void PyThread_release_lock(PyThread_type_lock lock) { - dprintf(("PyThread_release_lock(%p) called\n", lock)); - if (usunsetlock((ulock_t) lock) < 0) - perror("usunsetlock"); + dprintf(("PyThread_release_lock(%p) called\n", lock)); + if (usunsetlock((ulock_t) lock) < 0) + perror("usunsetlock"); } diff --git a/Python/thread_solaris.h b/Python/thread_solaris.h index 59ca0025a7..1ce1cfcba9 100644 --- a/Python/thread_solaris.h +++ b/Python/thread_solaris.h @@ -17,114 +17,114 @@ static void PyThread__init_thread(void) * Thread support. */ struct func_arg { - void (*func)(void *); - void *arg; + void (*func)(void *); + void *arg; }; static void * new_func(void *funcarg) { - void (*func)(void *); - void *arg; - - func = ((struct func_arg *) funcarg)->func; - arg = ((struct func_arg *) funcarg)->arg; - free(funcarg); - (*func)(arg); - return 0; + 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; + 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(); + if (!initialized) + PyThread_init_thread(); + return thr_self(); } -void +void PyThread_exit_thread(void) { - dprintf(("PyThread_exit_thread called\n")); - if (!initialized) - exit(0); - thr_exit(0); + dprintf(("PyThread_exit_thread called\n")); + if (!initialized) + exit(0); + thr_exit(0); } /* * Lock support. */ -PyThread_type_lock +PyThread_type_lock PyThread_allocate_lock(void) { - mutex_t *lock; - - 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; + 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 +void PyThread_free_lock(PyThread_type_lock lock) { - dprintf(("PyThread_free_lock(%p) called\n", lock)); - mutex_destroy((mutex_t *) lock); - free((void *) lock); + dprintf(("PyThread_free_lock(%p) called\n", lock)); + mutex_destroy((mutex_t *) lock); + free((void *) lock); } -int +int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) { - int success; - - 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; + 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 +void PyThread_release_lock(PyThread_type_lock lock) { - dprintf(("PyThread_release_lock(%p) called\n", lock)); - if (mutex_unlock((mutex_t *) lock)) - perror("mutex_unlock"); + dprintf(("PyThread_release_lock(%p) called\n", lock)); + if (mutex_unlock((mutex_t *) lock)) + perror("mutex_unlock"); } diff --git a/Python/thread_wince.h b/Python/thread_wince.h index f8cf2cf937..51ddc02f9a 100644 --- a/Python/thread_wince.h +++ b/Python/thread_wince.h @@ -24,21 +24,21 @@ static void PyThread__init_thread(void) */ long PyThread_start_new_thread(void (*func)(void *), void *arg) { - long rv; - int success = -1; + long rv; + int success = -1; - dprintf(("%ld: PyThread_start_new_thread called\n", PyThread_get_thread_ident())); - if (!initialized) - PyThread_init_thread(); + dprintf(("%ld: PyThread_start_new_thread called\n", PyThread_get_thread_ident())); + if (!initialized) + PyThread_init_thread(); - rv = _beginthread(func, 0, arg); /* use default stack size */ - - if (rv != -1) { - success = 0; - dprintf(("%ld: PyThread_start_new_thread succeeded:\n", PyThread_get_thread_ident())); - } + rv = _beginthread(func, 0, arg); /* use default stack size */ - return success; + if (rv != -1) { + success = 0; + dprintf(("%ld: PyThread_start_new_thread succeeded:\n", PyThread_get_thread_ident())); + } + + return success; } /* @@ -47,18 +47,18 @@ long PyThread_start_new_thread(void (*func)(void *), void *arg) */ long PyThread_get_thread_ident(void) { - if (!initialized) - PyThread_init_thread(); - - return GetCurrentThreadId(); + if (!initialized) + PyThread_init_thread(); + + return GetCurrentThreadId(); } void PyThread_exit_thread(void) { - dprintf(("%ld: PyThread_exit_thread called\n", PyThread_get_thread_ident())); - if (!initialized) - exit(0); - _endthread(); + dprintf(("%ld: PyThread_exit_thread called\n", PyThread_get_thread_ident())); + if (!initialized) + exit(0); + _endthread(); } /* @@ -72,12 +72,12 @@ PyThread_type_lock PyThread_allocate_lock(void) dprintf(("PyThread_allocate_lock called\n")); if (!initialized) - PyThread_init_thread(); + PyThread_init_thread(); aLock = CreateEvent(NULL, /* Security attributes */ - 0, /* Manual-Reset */ - 1, /* Is initially signalled */ - NULL); /* Name of event */ + 0, /* Manual-Reset */ + 1, /* Is initially signalled */ + NULL); /* Name of event */ dprintf(("%ld: PyThread_allocate_lock() -> %p\n", PyThread_get_thread_ident(), aLock)); @@ -107,22 +107,22 @@ int PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag) #ifndef DEBUG waitResult = WaitForSingleObject(aLock, (waitflag ? INFINITE : 0)); #else - /* To aid in debugging, we regularly wake up. This allows us to - break into the debugger */ - while (TRUE) { - waitResult = WaitForSingleObject(aLock, waitflag ? 3000 : 0); - if (waitflag==0 || (waitflag && waitResult == WAIT_OBJECT_0)) - break; - } + /* To aid in debugging, we regularly wake up. This allows us to + break into the debugger */ + while (TRUE) { + waitResult = WaitForSingleObject(aLock, waitflag ? 3000 : 0); + if (waitflag==0 || (waitflag && waitResult == WAIT_OBJECT_0)) + break; + } #endif if (waitResult != WAIT_OBJECT_0) { - success = 0; /* We failed */ + success = 0; /* We failed */ } - dprintf(("%ld: PyThread_acquire_lock(%p, %d) -> %d\n", PyThread_get_thread_ident(),aLock, waitflag, success)); + dprintf(("%ld: PyThread_acquire_lock(%p, %d) -> %d\n", PyThread_get_thread_ident(),aLock, waitflag, success)); - return success; + return success; } void PyThread_release_lock(PyThread_type_lock aLock) @@ -130,7 +130,7 @@ void PyThread_release_lock(PyThread_type_lock aLock) dprintf(("%ld: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock)); if (!SetEvent(aLock)) - dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n", PyThread_get_thread_ident(), aLock, GetLastError())); + dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n", PyThread_get_thread_ident(), aLock, GetLastError())); } diff --git a/Python/traceback.c b/Python/traceback.c index 1de2df6f5d..51a92269aa 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -30,303 +30,303 @@ static PyMethodDef tb_methods[] = { }; static PyMemberDef tb_memberlist[] = { - {"tb_next", T_OBJECT, OFF(tb_next), READONLY}, - {"tb_frame", T_OBJECT, OFF(tb_frame), READONLY}, - {"tb_lasti", T_INT, OFF(tb_lasti), READONLY}, - {"tb_lineno", T_INT, OFF(tb_lineno), READONLY}, - {NULL} /* Sentinel */ + {"tb_next", T_OBJECT, OFF(tb_next), READONLY}, + {"tb_frame", T_OBJECT, OFF(tb_frame), READONLY}, + {"tb_lasti", T_INT, OFF(tb_lasti), READONLY}, + {"tb_lineno", T_INT, OFF(tb_lineno), READONLY}, + {NULL} /* Sentinel */ }; static void tb_dealloc(PyTracebackObject *tb) { - PyObject_GC_UnTrack(tb); - Py_TRASHCAN_SAFE_BEGIN(tb) - Py_XDECREF(tb->tb_next); - Py_XDECREF(tb->tb_frame); - PyObject_GC_Del(tb); - Py_TRASHCAN_SAFE_END(tb) + PyObject_GC_UnTrack(tb); + Py_TRASHCAN_SAFE_BEGIN(tb) + Py_XDECREF(tb->tb_next); + Py_XDECREF(tb->tb_frame); + PyObject_GC_Del(tb); + Py_TRASHCAN_SAFE_END(tb) } static int tb_traverse(PyTracebackObject *tb, visitproc visit, void *arg) { - Py_VISIT(tb->tb_next); - Py_VISIT(tb->tb_frame); - return 0; + Py_VISIT(tb->tb_next); + Py_VISIT(tb->tb_frame); + return 0; } static void tb_clear(PyTracebackObject *tb) { - Py_CLEAR(tb->tb_next); - Py_CLEAR(tb->tb_frame); + Py_CLEAR(tb->tb_next); + Py_CLEAR(tb->tb_frame); } PyTypeObject PyTraceBack_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "traceback", - sizeof(PyTracebackObject), - 0, - (destructor)tb_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ - 0, /* tp_doc */ - (traverseproc)tb_traverse, /* tp_traverse */ - (inquiry)tb_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - tb_methods, /* tp_methods */ - tb_memberlist, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "traceback", + sizeof(PyTracebackObject), + 0, + (destructor)tb_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_reserved*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ + 0, /* tp_doc */ + (traverseproc)tb_traverse, /* tp_traverse */ + (inquiry)tb_clear, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + tb_methods, /* tp_methods */ + tb_memberlist, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ }; static PyTracebackObject * newtracebackobject(PyTracebackObject *next, PyFrameObject *frame) { - PyTracebackObject *tb; - if ((next != NULL && !PyTraceBack_Check(next)) || - frame == NULL || !PyFrame_Check(frame)) { - PyErr_BadInternalCall(); - return NULL; - } - tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type); - if (tb != NULL) { - Py_XINCREF(next); - tb->tb_next = next; - Py_XINCREF(frame); - tb->tb_frame = frame; - tb->tb_lasti = frame->f_lasti; - tb->tb_lineno = PyFrame_GetLineNumber(frame); - PyObject_GC_Track(tb); - } - return tb; + PyTracebackObject *tb; + if ((next != NULL && !PyTraceBack_Check(next)) || + frame == NULL || !PyFrame_Check(frame)) { + PyErr_BadInternalCall(); + return NULL; + } + tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type); + if (tb != NULL) { + Py_XINCREF(next); + tb->tb_next = next; + Py_XINCREF(frame); + tb->tb_frame = frame; + tb->tb_lasti = frame->f_lasti; + tb->tb_lineno = PyFrame_GetLineNumber(frame); + PyObject_GC_Track(tb); + } + return tb; } int PyTraceBack_Here(PyFrameObject *frame) { - PyThreadState *tstate = PyThreadState_GET(); - PyTracebackObject *oldtb = (PyTracebackObject *) tstate->curexc_traceback; - PyTracebackObject *tb = newtracebackobject(oldtb, frame); - if (tb == NULL) - return -1; - tstate->curexc_traceback = (PyObject *)tb; - Py_XDECREF(oldtb); - return 0; + PyThreadState *tstate = PyThreadState_GET(); + PyTracebackObject *oldtb = (PyTracebackObject *) tstate->curexc_traceback; + PyTracebackObject *tb = newtracebackobject(oldtb, frame); + if (tb == NULL) + return -1; + tstate->curexc_traceback = (PyObject *)tb; + Py_XDECREF(oldtb); + return 0; } static int _Py_FindSourceFile(const char* filename, char* namebuf, size_t namelen, int open_flags) { - int i; - int fd = -1; - PyObject *v; - Py_ssize_t _npath; - int npath; - size_t taillen; - PyObject *syspath; - const char* path; - const char* tail; - Py_ssize_t len; - - /* Search tail of filename in sys.path before giving up */ - tail = strrchr(filename, SEP); - if (tail == NULL) - tail = filename; - else - tail++; - taillen = strlen(tail); - - syspath = PySys_GetObject("path"); - if (syspath == NULL || !PyList_Check(syspath)) - return -1; - _npath = PyList_Size(syspath); - npath = Py_SAFE_DOWNCAST(_npath, Py_ssize_t, int); - - for (i = 0; i < npath; i++) { - v = PyList_GetItem(syspath, i); - if (v == NULL) { - PyErr_Clear(); - break; - } - if (!PyUnicode_Check(v)) - continue; - path = _PyUnicode_AsStringAndSize(v, &len); - if (len + 1 + (Py_ssize_t)taillen >= (Py_ssize_t)namelen - 1) - continue; /* Too long */ - strcpy(namebuf, path); - if (strlen(namebuf) != len) - continue; /* v contains '\0' */ - if (len > 0 && namebuf[len-1] != SEP) - namebuf[len++] = SEP; - strcpy(namebuf+len, tail); - Py_BEGIN_ALLOW_THREADS - fd = open(namebuf, open_flags); - Py_END_ALLOW_THREADS - if (0 <= fd) { - return fd; - } - } - return -1; + int i; + int fd = -1; + PyObject *v; + Py_ssize_t _npath; + int npath; + size_t taillen; + PyObject *syspath; + const char* path; + const char* tail; + Py_ssize_t len; + + /* Search tail of filename in sys.path before giving up */ + tail = strrchr(filename, SEP); + if (tail == NULL) + tail = filename; + else + tail++; + taillen = strlen(tail); + + syspath = PySys_GetObject("path"); + if (syspath == NULL || !PyList_Check(syspath)) + return -1; + _npath = PyList_Size(syspath); + npath = Py_SAFE_DOWNCAST(_npath, Py_ssize_t, int); + + for (i = 0; i < npath; i++) { + v = PyList_GetItem(syspath, i); + if (v == NULL) { + PyErr_Clear(); + break; + } + if (!PyUnicode_Check(v)) + continue; + path = _PyUnicode_AsStringAndSize(v, &len); + if (len + 1 + (Py_ssize_t)taillen >= (Py_ssize_t)namelen - 1) + continue; /* Too long */ + strcpy(namebuf, path); + if (strlen(namebuf) != len) + continue; /* v contains '\0' */ + if (len > 0 && namebuf[len-1] != SEP) + namebuf[len++] = SEP; + strcpy(namebuf+len, tail); + Py_BEGIN_ALLOW_THREADS + fd = open(namebuf, open_flags); + Py_END_ALLOW_THREADS + if (0 <= fd) { + return fd; + } + } + return -1; } int _Py_DisplaySourceLine(PyObject *f, const char *filename, int lineno, int indent) { - int err = 0; - int fd; - int i; - char *found_encoding; - char *encoding; - PyObject *fob = NULL; - PyObject *lineobj = NULL; + int err = 0; + int fd; + int i; + char *found_encoding; + char *encoding; + PyObject *fob = NULL; + PyObject *lineobj = NULL; #ifdef O_BINARY - const int open_flags = O_RDONLY | O_BINARY; /* necessary for Windows */ + const int open_flags = O_RDONLY | O_BINARY; /* necessary for Windows */ #else - const int open_flags = O_RDONLY; + const int open_flags = O_RDONLY; #endif - char buf[MAXPATHLEN+1]; - Py_UNICODE *u, *p; - Py_ssize_t len; - - /* open the file */ - if (filename == NULL) - return 0; - Py_BEGIN_ALLOW_THREADS - fd = open(filename, open_flags); - Py_END_ALLOW_THREADS - if (fd < 0) { - fd = _Py_FindSourceFile(filename, buf, sizeof(buf), open_flags); - if (fd < 0) - return 0; - filename = buf; - } - - /* use the right encoding to decode the file as unicode */ - found_encoding = PyTokenizer_FindEncoding(fd); - encoding = (found_encoding != NULL) ? found_encoding : - (char*)PyUnicode_GetDefaultEncoding(); - lseek(fd, 0, 0); /* Reset position */ - fob = PyFile_FromFd(fd, (char*)filename, "r", -1, (char*)encoding, - NULL, NULL, 1); - PyMem_FREE(found_encoding); - if (fob == NULL) { - PyErr_Clear(); - close(fd); - return 0; - } - - /* get the line number lineno */ - for (i = 0; i < lineno; i++) { - Py_XDECREF(lineobj); - lineobj = PyFile_GetLine(fob, -1); - if (!lineobj) { - err = -1; - break; - } - } - Py_DECREF(fob); - if (!lineobj || !PyUnicode_Check(lineobj)) { - Py_XDECREF(lineobj); - return err; - } - - /* remove the indentation of the line */ - u = PyUnicode_AS_UNICODE(lineobj); - len = PyUnicode_GET_SIZE(lineobj); - for (p=u; *p == ' ' || *p == '\t' || *p == '\014'; p++) - len--; - if (u != p) { - PyObject *truncated; - truncated = PyUnicode_FromUnicode(p, len); - if (truncated) { - Py_DECREF(lineobj); - lineobj = truncated; - } else { - PyErr_Clear(); - } - } - - /* Write some spaces before the line */ - strcpy(buf, " "); - assert (strlen(buf) == 10); - while (indent > 0) { - if(indent < 10) - buf[indent] = '\0'; - err = PyFile_WriteString(buf, f); - if (err != 0) - break; - indent -= 10; - } - - /* finally display the line */ - if (err == 0) - err = PyFile_WriteObject(lineobj, f, Py_PRINT_RAW); - Py_DECREF(lineobj); - if (err == 0) - err = PyFile_WriteString("\n", f); - return err; + char buf[MAXPATHLEN+1]; + Py_UNICODE *u, *p; + Py_ssize_t len; + + /* open the file */ + if (filename == NULL) + return 0; + Py_BEGIN_ALLOW_THREADS + fd = open(filename, open_flags); + Py_END_ALLOW_THREADS + if (fd < 0) { + fd = _Py_FindSourceFile(filename, buf, sizeof(buf), open_flags); + if (fd < 0) + return 0; + filename = buf; + } + + /* use the right encoding to decode the file as unicode */ + found_encoding = PyTokenizer_FindEncoding(fd); + encoding = (found_encoding != NULL) ? found_encoding : + (char*)PyUnicode_GetDefaultEncoding(); + lseek(fd, 0, 0); /* Reset position */ + fob = PyFile_FromFd(fd, (char*)filename, "r", -1, (char*)encoding, + NULL, NULL, 1); + PyMem_FREE(found_encoding); + if (fob == NULL) { + PyErr_Clear(); + close(fd); + return 0; + } + + /* get the line number lineno */ + for (i = 0; i < lineno; i++) { + Py_XDECREF(lineobj); + lineobj = PyFile_GetLine(fob, -1); + if (!lineobj) { + err = -1; + break; + } + } + Py_DECREF(fob); + if (!lineobj || !PyUnicode_Check(lineobj)) { + Py_XDECREF(lineobj); + return err; + } + + /* remove the indentation of the line */ + u = PyUnicode_AS_UNICODE(lineobj); + len = PyUnicode_GET_SIZE(lineobj); + for (p=u; *p == ' ' || *p == '\t' || *p == '\014'; p++) + len--; + if (u != p) { + PyObject *truncated; + truncated = PyUnicode_FromUnicode(p, len); + if (truncated) { + Py_DECREF(lineobj); + lineobj = truncated; + } else { + PyErr_Clear(); + } + } + + /* Write some spaces before the line */ + strcpy(buf, " "); + assert (strlen(buf) == 10); + while (indent > 0) { + if(indent < 10) + buf[indent] = '\0'; + err = PyFile_WriteString(buf, f); + if (err != 0) + break; + indent -= 10; + } + + /* finally display the line */ + if (err == 0) + err = PyFile_WriteObject(lineobj, f, Py_PRINT_RAW); + Py_DECREF(lineobj); + if (err == 0) + err = PyFile_WriteString("\n", f); + return err; } static int tb_displayline(PyObject *f, const char *filename, int lineno, const char *name) { - int err = 0; - char linebuf[2000]; + int err = 0; + char linebuf[2000]; - if (filename == NULL || name == NULL) - return -1; - /* This is needed by Emacs' compile command */ + if (filename == NULL || name == NULL) + return -1; + /* This is needed by Emacs' compile command */ #define FMT " File \"%.500s\", line %d, in %.500s\n" - PyOS_snprintf(linebuf, sizeof(linebuf), FMT, filename, lineno, name); - err = PyFile_WriteString(linebuf, f); - if (err != 0) - return err; - return _Py_DisplaySourceLine(f, filename, lineno, 4); + PyOS_snprintf(linebuf, sizeof(linebuf), FMT, filename, lineno, name); + err = PyFile_WriteString(linebuf, f); + if (err != 0) + return err; + return _Py_DisplaySourceLine(f, filename, lineno, 4); } static int tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit) { - int err = 0; - long depth = 0; - PyTracebackObject *tb1 = tb; - while (tb1 != NULL) { - depth++; - tb1 = tb1->tb_next; - } - while (tb != NULL && err == 0) { - if (depth <= limit) { - err = tb_displayline(f, - _PyUnicode_AsString( - tb->tb_frame->f_code->co_filename), - tb->tb_lineno, - _PyUnicode_AsString(tb->tb_frame->f_code->co_name)); - } - depth--; - tb = tb->tb_next; - if (err == 0) - err = PyErr_CheckSignals(); - } - return err; + int err = 0; + long depth = 0; + PyTracebackObject *tb1 = tb; + while (tb1 != NULL) { + depth++; + tb1 = tb1->tb_next; + } + while (tb != NULL && err == 0) { + if (depth <= limit) { + err = tb_displayline(f, + _PyUnicode_AsString( + tb->tb_frame->f_code->co_filename), + tb->tb_lineno, + _PyUnicode_AsString(tb->tb_frame->f_code->co_name)); + } + depth--; + tb = tb->tb_next; + if (err == 0) + err = PyErr_CheckSignals(); + } + return err; } #define PyTraceBack_LIMIT 1000 @@ -334,40 +334,40 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit) int PyTraceBack_Print(PyObject *v, PyObject *f) { - int err; - PyObject *limitv; - long limit = PyTraceBack_LIMIT; - - if (v == NULL) - return 0; - if (!PyTraceBack_Check(v)) { - PyErr_BadInternalCall(); - return -1; - } - limitv = PySys_GetObject("tracebacklimit"); - if (limitv) { - PyObject *exc_type, *exc_value, *exc_tb; - - PyErr_Fetch(&exc_type, &exc_value, &exc_tb); - limit = PyLong_AsLong(limitv); - if (limit == -1 && PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) { - limit = PyTraceBack_LIMIT; - } - else { - Py_XDECREF(exc_type); - Py_XDECREF(exc_value); - Py_XDECREF(exc_tb); - return 0; - } - } - else if (limit <= 0) { - limit = PyTraceBack_LIMIT; - } - PyErr_Restore(exc_type, exc_value, exc_tb); - } - err = PyFile_WriteString("Traceback (most recent call last):\n", f); - if (!err) - err = tb_printinternal((PyTracebackObject *)v, f, limit); - return err; + int err; + PyObject *limitv; + long limit = PyTraceBack_LIMIT; + + if (v == NULL) + return 0; + if (!PyTraceBack_Check(v)) { + PyErr_BadInternalCall(); + return -1; + } + limitv = PySys_GetObject("tracebacklimit"); + if (limitv) { + PyObject *exc_type, *exc_value, *exc_tb; + + PyErr_Fetch(&exc_type, &exc_value, &exc_tb); + limit = PyLong_AsLong(limitv); + if (limit == -1 && PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_OverflowError)) { + limit = PyTraceBack_LIMIT; + } + else { + Py_XDECREF(exc_type); + Py_XDECREF(exc_value); + Py_XDECREF(exc_tb); + return 0; + } + } + else if (limit <= 0) { + limit = PyTraceBack_LIMIT; + } + PyErr_Restore(exc_type, exc_value, exc_tb); + } + err = PyFile_WriteString("Traceback (most recent call last):\n", f); + if (!err) + err = tb_printinternal((PyTracebackObject *)v, f, limit); + return err; } -- cgit v1.2.1 From 167b903781d0e9f44d16924955eec443b024e445 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Thu, 13 May 2010 11:52:22 +0000 Subject: Remove unnecessary assignments. --- Python/dtoa.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/dtoa.c b/Python/dtoa.c index 4b2c6c36e3..44dc01f1d5 100644 --- a/Python/dtoa.c +++ b/Python/dtoa.c @@ -1382,7 +1382,6 @@ bigcomp(U *rv, const char *s0, BCinfo *bc) Bigint *b, *d; int b2, d2, dd, i, nd, nd0, odd, p2, p5; - dd = 0; /* silence compiler warning about possibly unused variable */ nd = bc->nd; nd0 = bc->nd0; p5 = nd + bc->e0; @@ -2362,7 +2361,7 @@ _Py_dg_dtoa(double dd, int mode, int ndigits, /* set pointers to NULL, to silence gcc compiler warnings and make cleanup easier on error */ - mlo = mhi = b = S = 0; + mlo = mhi = S = 0; s0 = 0; u.d = dd; @@ -2713,8 +2712,6 @@ _Py_dg_dtoa(double dd, int mode, int ndigits, * and for all and pass them and a shift to quorem, so it * can do shifts and ors to compute the numerator for q. */ - if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f)) - i = 32 - i; #define iInc 28 i = dshift(S, s2); b2 += i; -- cgit v1.2.1 From a2109217d1e96e46c777ff4db7660c4aea072b4a Mon Sep 17 00:00:00 2001 From: Jeffrey Yasskin Date: Thu, 13 May 2010 18:31:05 +0000 Subject: Make PyErr_Occurred return NULL if there is no current thread. Previously it would Py_FatalError, which called PyErr_Occurred, resulting in a semi-infinite recursion. Fixes issue 3605. --- Python/errors.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/errors.c b/Python/errors.c index e98d7a946c..37669739c1 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -130,9 +130,14 @@ PyErr_SetString(PyObject *exception, const char *string) PyObject * PyErr_Occurred(void) { - PyThreadState *tstate = PyThreadState_GET(); - - return tstate->curexc_type; + /* If there is no thread state, PyThreadState_GET calls + Py_FatalError, which calls PyErr_Occurred. To avoid the + resulting infinite loop, we inline PyThreadState_GET here and + treat no thread as no error. */ + PyThreadState *tstate = + ((PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current)); + + return tstate == NULL ? NULL : tstate->curexc_type; } -- cgit v1.2.1 From 5266e4236ff854c931fb0f6b958539e243da015f Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 14 May 2010 00:59:09 +0000 Subject: Issue #4653: fix typo in flush_std_files() Don't call sys.stderr.flush() if sys has no stderr attribute or if sys.stderr==None. --- Python/pythonrun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index e58b1c8ab9..3031aef5f2 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -334,7 +334,7 @@ flush_std_files(void) Py_DECREF(tmp); } - if (ferr != NULL || ferr != Py_None) { + if (ferr != NULL && ferr != Py_None) { tmp = PyObject_CallMethod(ferr, "flush", ""); if (tmp == NULL) PyErr_Clear(); -- cgit v1.2.1 From f9dbe155860b82bbc704f46258ad998e2b018e59 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 15 May 2010 12:27:16 +0000 Subject: Issue #8610: Load file system codec at startup, and display a fatal error on failure. Set the file system encoding to utf-8 (instead of None) if getting the locale encoding failed, or if nl_langinfo(CODESET) function is missing. --- Python/bltinmodule.c | 11 ++++++++-- Python/pythonrun.c | 62 +++++++++++++++++++++++++++++++++++----------------- 2 files changed, 51 insertions(+), 22 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 97f7b96126..a658f9b968 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -9,6 +9,10 @@ #include +#ifdef HAVE_LANGINFO_H +#include /* CODESET */ +#endif + /* The default encoding used by the platform file system APIs Can remain NULL for all platforms that don't have such a concept @@ -21,9 +25,12 @@ int Py_HasFileSystemDefaultEncoding = 1; #elif defined(__APPLE__) const char *Py_FileSystemDefaultEncoding = "utf-8"; int Py_HasFileSystemDefaultEncoding = 1; -#else -const char *Py_FileSystemDefaultEncoding = NULL; /* use default */ +#elif defined(HAVE_LANGINFO_H) && defined(CODESET) +const char *Py_FileSystemDefaultEncoding = NULL; /* set by initfsencoding() */ int Py_HasFileSystemDefaultEncoding = 0; +#else +const char *Py_FileSystemDefaultEncoding = "utf-8"; +int Py_HasFileSystemDefaultEncoding = 1; #endif int diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 3031aef5f2..4932c4ad4c 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -57,6 +57,7 @@ extern grammar _PyParser_Grammar; /* From graminit.c */ /* Forward */ static void initmain(void); +static void initfsencoding(void); static void initsite(void); static int initstdio(void); static void flush_io(void); @@ -159,7 +160,6 @@ get_codeset(void) error: Py_XDECREF(codec); - PyErr_Clear(); return NULL; } #endif @@ -171,9 +171,6 @@ Py_InitializeEx(int install_sigs) PyThreadState *tstate; PyObject *bimod, *sysmod, *pstderr; char *p; -#if defined(HAVE_LANGINFO_H) && defined(CODESET) - char *codeset; -#endif extern void _Py_ReadyTypes(void); if (initialized) @@ -264,21 +261,7 @@ Py_InitializeEx(int install_sigs) _PyImportHooks_Init(); -#if 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. */ - - codeset = get_codeset(); - if (codeset) { - if (!Py_FileSystemDefaultEncoding) - Py_FileSystemDefaultEncoding = codeset; - else - free(codeset); - } -#endif + initfsencoding(); if (install_sigs) initsigs(); /* Signal handling stuff, including initintr() */ @@ -496,7 +479,7 @@ Py_Finalize(void) _PyUnicode_Fini(); /* reset file system default encoding */ - if (!Py_HasFileSystemDefaultEncoding) { + if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) { free((char*)Py_FileSystemDefaultEncoding); Py_FileSystemDefaultEncoding = NULL; } @@ -707,6 +690,45 @@ initmain(void) } } +static void +initfsencoding(void) +{ + PyObject *codec; +#if defined(HAVE_LANGINFO_H) && defined(CODESET) + char *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. */ + codeset = get_codeset(); + if (codeset != NULL) { + Py_FileSystemDefaultEncoding = codeset; + Py_HasFileSystemDefaultEncoding = 0; + return; + } + + PyErr_Clear(); + fprintf(stderr, + "Unable to get the locale encoding: " + "fallback to utf-8\n"); + Py_FileSystemDefaultEncoding = "utf-8"; + Py_HasFileSystemDefaultEncoding = 1; +#endif + + /* the encoding is mbcs, utf-8 or ascii */ + codec = _PyCodec_Lookup(Py_FileSystemDefaultEncoding); + if (!codec) { + /* Such error can only occurs in critical situations: no more + * memory, import a module of the standard library failed, + * etc. */ + Py_FatalError("Py_Initialize: unable to load the file system codec"); + } else { + Py_DECREF(codec); + } +} + /* Import the site module (not into __main__ though) */ static void -- cgit v1.2.1 From 54567ad24842b6c6c98423b6614d22b0de784915 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 15 May 2010 16:27:27 +0000 Subject: Issue #8715: Create PyUnicode_EncodeFSDefault() function: Encode a Unicode object to Py_FileSystemDefaultEncoding with the "surrogateescape" error handler, return a bytes object. If Py_FileSystemDefaultEncoding is not set, fall back to UTF-8. --- Python/import.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 923888d5df..d23eb6a941 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1633,8 +1633,7 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, if (!v) return NULL; if (PyUnicode_Check(v)) { - v = PyUnicode_AsEncodedString(v, - Py_FileSystemDefaultEncoding, NULL); + v = PyUnicode_EncodeFSDefault(v); if (v == NULL) return NULL; } @@ -2752,14 +2751,7 @@ ensure_fromlist(PyObject *mod, PyObject *fromlist, char *buf, Py_ssize_t buflen, char *subname; PyObject *submod; char *p; - if (!Py_FileSystemDefaultEncoding) { - item8 = PyUnicode_EncodeASCII(PyUnicode_AsUnicode(item), - PyUnicode_GetSize(item), - NULL); - } else { - item8 = PyUnicode_AsEncodedString(item, - Py_FileSystemDefaultEncoding, NULL); - } + item8 = PyUnicode_EncodeFSDefault(item); if (!item8) { PyErr_SetString(PyExc_ValueError, "Cannot encode path item"); return 0; -- cgit v1.2.1 From f75ef67ababe10cb03f477838a505e189bbf14c2 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 15 May 2010 23:00:51 +0000 Subject: Merged revisions 81220 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r81220 | victor.stinner | 2010-05-16 00:55:28 +0200 (dim., 16 mai 2010) | 4 lines Use 4-spaces for indentation (instead of tabs) in pgen outputs Regenerate (reindent) Python/graminit.c ........ --- Python/graminit.c | 2454 ++++++++++++++++++++++++++--------------------------- 1 file changed, 1227 insertions(+), 1227 deletions(-) (limited to 'Python') diff --git a/Python/graminit.c b/Python/graminit.c index e3530857a5..691e1687c6 100644 --- a/Python/graminit.c +++ b/Python/graminit.c @@ -4,2077 +4,2077 @@ #include "grammar.h" PyAPI_DATA(grammar) _PyParser_Grammar; static arc arcs_0_0[3] = { - {2, 1}, - {3, 1}, - {4, 2}, + {2, 1}, + {3, 1}, + {4, 2}, }; static arc arcs_0_1[1] = { - {0, 1}, + {0, 1}, }; static arc arcs_0_2[1] = { - {2, 1}, + {2, 1}, }; static state states_0[3] = { - {3, arcs_0_0}, - {1, arcs_0_1}, - {1, arcs_0_2}, + {3, arcs_0_0}, + {1, arcs_0_1}, + {1, arcs_0_2}, }; static arc arcs_1_0[3] = { - {2, 0}, - {6, 0}, - {7, 1}, + {2, 0}, + {6, 0}, + {7, 1}, }; static arc arcs_1_1[1] = { - {0, 1}, + {0, 1}, }; static state states_1[2] = { - {3, arcs_1_0}, - {1, arcs_1_1}, + {3, arcs_1_0}, + {1, arcs_1_1}, }; static arc arcs_2_0[1] = { - {9, 1}, + {9, 1}, }; static arc arcs_2_1[2] = { - {2, 1}, - {7, 2}, + {2, 1}, + {7, 2}, }; static arc arcs_2_2[1] = { - {0, 2}, + {0, 2}, }; static state states_2[3] = { - {1, arcs_2_0}, - {2, arcs_2_1}, - {1, arcs_2_2}, + {1, arcs_2_0}, + {2, arcs_2_1}, + {1, arcs_2_2}, }; static arc arcs_3_0[1] = { - {11, 1}, + {11, 1}, }; static arc arcs_3_1[1] = { - {12, 2}, + {12, 2}, }; static arc arcs_3_2[2] = { - {13, 3}, - {2, 4}, + {13, 3}, + {2, 4}, }; static arc arcs_3_3[2] = { - {14, 5}, - {15, 6}, + {14, 5}, + {15, 6}, }; static arc arcs_3_4[1] = { - {0, 4}, + {0, 4}, }; static arc arcs_3_5[1] = { - {15, 6}, + {15, 6}, }; static arc arcs_3_6[1] = { - {2, 4}, + {2, 4}, }; static state states_3[7] = { - {1, arcs_3_0}, - {1, arcs_3_1}, - {2, arcs_3_2}, - {2, arcs_3_3}, - {1, arcs_3_4}, - {1, arcs_3_5}, - {1, arcs_3_6}, + {1, arcs_3_0}, + {1, arcs_3_1}, + {2, arcs_3_2}, + {2, arcs_3_3}, + {1, arcs_3_4}, + {1, arcs_3_5}, + {1, arcs_3_6}, }; static arc arcs_4_0[1] = { - {10, 1}, + {10, 1}, }; static arc arcs_4_1[2] = { - {10, 1}, - {0, 1}, + {10, 1}, + {0, 1}, }; static state states_4[2] = { - {1, arcs_4_0}, - {2, arcs_4_1}, + {1, arcs_4_0}, + {2, arcs_4_1}, }; static arc arcs_5_0[1] = { - {16, 1}, + {16, 1}, }; static arc arcs_5_1[2] = { - {18, 2}, - {19, 2}, + {18, 2}, + {19, 2}, }; static arc arcs_5_2[1] = { - {0, 2}, + {0, 2}, }; static state states_5[3] = { - {1, arcs_5_0}, - {2, arcs_5_1}, - {1, arcs_5_2}, + {1, arcs_5_0}, + {2, arcs_5_1}, + {1, arcs_5_2}, }; static arc arcs_6_0[1] = { - {20, 1}, + {20, 1}, }; static arc arcs_6_1[1] = { - {21, 2}, + {21, 2}, }; static arc arcs_6_2[1] = { - {22, 3}, + {22, 3}, }; static arc arcs_6_3[2] = { - {23, 4}, - {25, 5}, + {23, 4}, + {25, 5}, }; static arc arcs_6_4[1] = { - {24, 6}, + {24, 6}, }; static arc arcs_6_5[1] = { - {26, 7}, + {26, 7}, }; static arc arcs_6_6[1] = { - {25, 5}, + {25, 5}, }; static arc arcs_6_7[1] = { - {0, 7}, + {0, 7}, }; static state states_6[8] = { - {1, arcs_6_0}, - {1, arcs_6_1}, - {1, arcs_6_2}, - {2, arcs_6_3}, - {1, arcs_6_4}, - {1, arcs_6_5}, - {1, arcs_6_6}, - {1, arcs_6_7}, + {1, arcs_6_0}, + {1, arcs_6_1}, + {1, arcs_6_2}, + {2, arcs_6_3}, + {1, arcs_6_4}, + {1, arcs_6_5}, + {1, arcs_6_6}, + {1, arcs_6_7}, }; static arc arcs_7_0[1] = { - {13, 1}, + {13, 1}, }; static arc arcs_7_1[2] = { - {27, 2}, - {15, 3}, + {27, 2}, + {15, 3}, }; static arc arcs_7_2[1] = { - {15, 3}, + {15, 3}, }; static arc arcs_7_3[1] = { - {0, 3}, + {0, 3}, }; static state states_7[4] = { - {1, arcs_7_0}, - {2, arcs_7_1}, - {1, arcs_7_2}, - {1, arcs_7_3}, + {1, arcs_7_0}, + {2, arcs_7_1}, + {1, arcs_7_2}, + {1, arcs_7_3}, }; static arc arcs_8_0[3] = { - {28, 1}, - {31, 2}, - {32, 3}, + {28, 1}, + {31, 2}, + {32, 3}, }; static arc arcs_8_1[3] = { - {29, 4}, - {30, 5}, - {0, 1}, + {29, 4}, + {30, 5}, + {0, 1}, }; static arc arcs_8_2[3] = { - {28, 6}, - {30, 7}, - {0, 2}, + {28, 6}, + {30, 7}, + {0, 2}, }; static arc arcs_8_3[1] = { - {28, 8}, + {28, 8}, }; static arc arcs_8_4[1] = { - {24, 9}, + {24, 9}, }; static arc arcs_8_5[4] = { - {28, 1}, - {31, 2}, - {32, 3}, - {0, 5}, + {28, 1}, + {31, 2}, + {32, 3}, + {0, 5}, }; static arc arcs_8_6[2] = { - {30, 7}, - {0, 6}, + {30, 7}, + {0, 6}, }; static arc arcs_8_7[2] = { - {28, 10}, - {32, 3}, + {28, 10}, + {32, 3}, }; static arc arcs_8_8[1] = { - {0, 8}, + {0, 8}, }; static arc arcs_8_9[2] = { - {30, 5}, - {0, 9}, + {30, 5}, + {0, 9}, }; static arc arcs_8_10[3] = { - {30, 7}, - {29, 11}, - {0, 10}, + {30, 7}, + {29, 11}, + {0, 10}, }; static arc arcs_8_11[1] = { - {24, 6}, + {24, 6}, }; static state states_8[12] = { - {3, arcs_8_0}, - {3, arcs_8_1}, - {3, arcs_8_2}, - {1, arcs_8_3}, - {1, arcs_8_4}, - {4, arcs_8_5}, - {2, arcs_8_6}, - {2, arcs_8_7}, - {1, arcs_8_8}, - {2, arcs_8_9}, - {3, arcs_8_10}, - {1, arcs_8_11}, + {3, arcs_8_0}, + {3, arcs_8_1}, + {3, arcs_8_2}, + {1, arcs_8_3}, + {1, arcs_8_4}, + {4, arcs_8_5}, + {2, arcs_8_6}, + {2, arcs_8_7}, + {1, arcs_8_8}, + {2, arcs_8_9}, + {3, arcs_8_10}, + {1, arcs_8_11}, }; static arc arcs_9_0[1] = { - {21, 1}, + {21, 1}, }; static arc arcs_9_1[2] = { - {25, 2}, - {0, 1}, + {25, 2}, + {0, 1}, }; static arc arcs_9_2[1] = { - {24, 3}, + {24, 3}, }; static arc arcs_9_3[1] = { - {0, 3}, + {0, 3}, }; static state states_9[4] = { - {1, arcs_9_0}, - {2, arcs_9_1}, - {1, arcs_9_2}, - {1, arcs_9_3}, + {1, arcs_9_0}, + {2, arcs_9_1}, + {1, arcs_9_2}, + {1, arcs_9_3}, }; static arc arcs_10_0[3] = { - {34, 1}, - {31, 2}, - {32, 3}, + {34, 1}, + {31, 2}, + {32, 3}, }; static arc arcs_10_1[3] = { - {29, 4}, - {30, 5}, - {0, 1}, + {29, 4}, + {30, 5}, + {0, 1}, }; static arc arcs_10_2[3] = { - {34, 6}, - {30, 7}, - {0, 2}, + {34, 6}, + {30, 7}, + {0, 2}, }; static arc arcs_10_3[1] = { - {34, 8}, + {34, 8}, }; static arc arcs_10_4[1] = { - {24, 9}, + {24, 9}, }; static arc arcs_10_5[4] = { - {34, 1}, - {31, 2}, - {32, 3}, - {0, 5}, + {34, 1}, + {31, 2}, + {32, 3}, + {0, 5}, }; static arc arcs_10_6[2] = { - {30, 7}, - {0, 6}, + {30, 7}, + {0, 6}, }; static arc arcs_10_7[2] = { - {34, 10}, - {32, 3}, + {34, 10}, + {32, 3}, }; static arc arcs_10_8[1] = { - {0, 8}, + {0, 8}, }; static arc arcs_10_9[2] = { - {30, 5}, - {0, 9}, + {30, 5}, + {0, 9}, }; static arc arcs_10_10[3] = { - {30, 7}, - {29, 11}, - {0, 10}, + {30, 7}, + {29, 11}, + {0, 10}, }; static arc arcs_10_11[1] = { - {24, 6}, + {24, 6}, }; static state states_10[12] = { - {3, arcs_10_0}, - {3, arcs_10_1}, - {3, arcs_10_2}, - {1, arcs_10_3}, - {1, arcs_10_4}, - {4, arcs_10_5}, - {2, arcs_10_6}, - {2, arcs_10_7}, - {1, arcs_10_8}, - {2, arcs_10_9}, - {3, arcs_10_10}, - {1, arcs_10_11}, + {3, arcs_10_0}, + {3, arcs_10_1}, + {3, arcs_10_2}, + {1, arcs_10_3}, + {1, arcs_10_4}, + {4, arcs_10_5}, + {2, arcs_10_6}, + {2, arcs_10_7}, + {1, arcs_10_8}, + {2, arcs_10_9}, + {3, arcs_10_10}, + {1, arcs_10_11}, }; static arc arcs_11_0[1] = { - {21, 1}, + {21, 1}, }; static arc arcs_11_1[1] = { - {0, 1}, + {0, 1}, }; static state states_11[2] = { - {1, arcs_11_0}, - {1, arcs_11_1}, + {1, arcs_11_0}, + {1, arcs_11_1}, }; static arc arcs_12_0[2] = { - {3, 1}, - {4, 1}, + {3, 1}, + {4, 1}, }; static arc arcs_12_1[1] = { - {0, 1}, + {0, 1}, }; static state states_12[2] = { - {2, arcs_12_0}, - {1, arcs_12_1}, + {2, arcs_12_0}, + {1, arcs_12_1}, }; static arc arcs_13_0[1] = { - {35, 1}, + {35, 1}, }; static arc arcs_13_1[2] = { - {36, 2}, - {2, 3}, + {36, 2}, + {2, 3}, }; static arc arcs_13_2[2] = { - {35, 1}, - {2, 3}, + {35, 1}, + {2, 3}, }; static arc arcs_13_3[1] = { - {0, 3}, + {0, 3}, }; static state states_13[4] = { - {1, arcs_13_0}, - {2, arcs_13_1}, - {2, arcs_13_2}, - {1, arcs_13_3}, + {1, arcs_13_0}, + {2, arcs_13_1}, + {2, arcs_13_2}, + {1, arcs_13_3}, }; static arc arcs_14_0[8] = { - {37, 1}, - {38, 1}, - {39, 1}, - {40, 1}, - {41, 1}, - {42, 1}, - {43, 1}, - {44, 1}, + {37, 1}, + {38, 1}, + {39, 1}, + {40, 1}, + {41, 1}, + {42, 1}, + {43, 1}, + {44, 1}, }; static arc arcs_14_1[1] = { - {0, 1}, + {0, 1}, }; static state states_14[2] = { - {8, arcs_14_0}, - {1, arcs_14_1}, + {8, arcs_14_0}, + {1, arcs_14_1}, }; static arc arcs_15_0[1] = { - {45, 1}, + {45, 1}, }; static arc arcs_15_1[3] = { - {46, 2}, - {29, 3}, - {0, 1}, + {46, 2}, + {29, 3}, + {0, 1}, }; static arc arcs_15_2[2] = { - {47, 4}, - {9, 4}, + {47, 4}, + {9, 4}, }; static arc arcs_15_3[2] = { - {47, 5}, - {45, 5}, + {47, 5}, + {45, 5}, }; static arc arcs_15_4[1] = { - {0, 4}, + {0, 4}, }; static arc arcs_15_5[2] = { - {29, 3}, - {0, 5}, + {29, 3}, + {0, 5}, }; static state states_15[6] = { - {1, arcs_15_0}, - {3, arcs_15_1}, - {2, arcs_15_2}, - {2, arcs_15_3}, - {1, arcs_15_4}, - {2, arcs_15_5}, + {1, arcs_15_0}, + {3, arcs_15_1}, + {2, arcs_15_2}, + {2, arcs_15_3}, + {1, arcs_15_4}, + {2, arcs_15_5}, }; static arc arcs_16_0[2] = { - {24, 1}, - {48, 1}, + {24, 1}, + {48, 1}, }; static arc arcs_16_1[2] = { - {30, 2}, - {0, 1}, + {30, 2}, + {0, 1}, }; static arc arcs_16_2[3] = { - {24, 1}, - {48, 1}, - {0, 2}, + {24, 1}, + {48, 1}, + {0, 2}, }; static state states_16[3] = { - {2, arcs_16_0}, - {2, arcs_16_1}, - {3, arcs_16_2}, + {2, arcs_16_0}, + {2, arcs_16_1}, + {3, arcs_16_2}, }; static arc arcs_17_0[12] = { - {49, 1}, - {50, 1}, - {51, 1}, - {52, 1}, - {53, 1}, - {54, 1}, - {55, 1}, - {56, 1}, - {57, 1}, - {58, 1}, - {59, 1}, - {60, 1}, + {49, 1}, + {50, 1}, + {51, 1}, + {52, 1}, + {53, 1}, + {54, 1}, + {55, 1}, + {56, 1}, + {57, 1}, + {58, 1}, + {59, 1}, + {60, 1}, }; static arc arcs_17_1[1] = { - {0, 1}, + {0, 1}, }; static state states_17[2] = { - {12, arcs_17_0}, - {1, arcs_17_1}, + {12, arcs_17_0}, + {1, arcs_17_1}, }; static arc arcs_18_0[1] = { - {61, 1}, + {61, 1}, }; static arc arcs_18_1[1] = { - {62, 2}, + {62, 2}, }; static arc arcs_18_2[1] = { - {0, 2}, + {0, 2}, }; static state states_18[3] = { - {1, arcs_18_0}, - {1, arcs_18_1}, - {1, arcs_18_2}, + {1, arcs_18_0}, + {1, arcs_18_1}, + {1, arcs_18_2}, }; static arc arcs_19_0[1] = { - {63, 1}, + {63, 1}, }; static arc arcs_19_1[1] = { - {0, 1}, + {0, 1}, }; static state states_19[2] = { - {1, arcs_19_0}, - {1, arcs_19_1}, + {1, arcs_19_0}, + {1, arcs_19_1}, }; static arc arcs_20_0[5] = { - {64, 1}, - {65, 1}, - {66, 1}, - {67, 1}, - {68, 1}, + {64, 1}, + {65, 1}, + {66, 1}, + {67, 1}, + {68, 1}, }; static arc arcs_20_1[1] = { - {0, 1}, + {0, 1}, }; static state states_20[2] = { - {5, arcs_20_0}, - {1, arcs_20_1}, + {5, arcs_20_0}, + {1, arcs_20_1}, }; static arc arcs_21_0[1] = { - {69, 1}, + {69, 1}, }; static arc arcs_21_1[1] = { - {0, 1}, + {0, 1}, }; static state states_21[2] = { - {1, arcs_21_0}, - {1, arcs_21_1}, + {1, arcs_21_0}, + {1, arcs_21_1}, }; static arc arcs_22_0[1] = { - {70, 1}, + {70, 1}, }; static arc arcs_22_1[1] = { - {0, 1}, + {0, 1}, }; static state states_22[2] = { - {1, arcs_22_0}, - {1, arcs_22_1}, + {1, arcs_22_0}, + {1, arcs_22_1}, }; static arc arcs_23_0[1] = { - {71, 1}, + {71, 1}, }; static arc arcs_23_1[2] = { - {9, 2}, - {0, 1}, + {9, 2}, + {0, 1}, }; static arc arcs_23_2[1] = { - {0, 2}, + {0, 2}, }; static state states_23[3] = { - {1, arcs_23_0}, - {2, arcs_23_1}, - {1, arcs_23_2}, + {1, arcs_23_0}, + {2, arcs_23_1}, + {1, arcs_23_2}, }; static arc arcs_24_0[1] = { - {47, 1}, + {47, 1}, }; static arc arcs_24_1[1] = { - {0, 1}, + {0, 1}, }; static state states_24[2] = { - {1, arcs_24_0}, - {1, arcs_24_1}, + {1, arcs_24_0}, + {1, arcs_24_1}, }; static arc arcs_25_0[1] = { - {72, 1}, + {72, 1}, }; static arc arcs_25_1[2] = { - {24, 2}, - {0, 1}, + {24, 2}, + {0, 1}, }; static arc arcs_25_2[2] = { - {73, 3}, - {0, 2}, + {73, 3}, + {0, 2}, }; static arc arcs_25_3[1] = { - {24, 4}, + {24, 4}, }; static arc arcs_25_4[1] = { - {0, 4}, + {0, 4}, }; static state states_25[5] = { - {1, arcs_25_0}, - {2, arcs_25_1}, - {2, arcs_25_2}, - {1, arcs_25_3}, - {1, arcs_25_4}, + {1, arcs_25_0}, + {2, arcs_25_1}, + {2, arcs_25_2}, + {1, arcs_25_3}, + {1, arcs_25_4}, }; static arc arcs_26_0[2] = { - {74, 1}, - {75, 1}, + {74, 1}, + {75, 1}, }; static arc arcs_26_1[1] = { - {0, 1}, + {0, 1}, }; static state states_26[2] = { - {2, arcs_26_0}, - {1, arcs_26_1}, + {2, arcs_26_0}, + {1, arcs_26_1}, }; static arc arcs_27_0[1] = { - {76, 1}, + {76, 1}, }; static arc arcs_27_1[1] = { - {77, 2}, + {77, 2}, }; static arc arcs_27_2[1] = { - {0, 2}, + {0, 2}, }; static state states_27[3] = { - {1, arcs_27_0}, - {1, arcs_27_1}, - {1, arcs_27_2}, + {1, arcs_27_0}, + {1, arcs_27_1}, + {1, arcs_27_2}, }; static arc arcs_28_0[1] = { - {73, 1}, + {73, 1}, }; static arc arcs_28_1[3] = { - {78, 2}, - {79, 2}, - {12, 3}, + {78, 2}, + {79, 2}, + {12, 3}, }; static arc arcs_28_2[4] = { - {78, 2}, - {79, 2}, - {12, 3}, - {76, 4}, + {78, 2}, + {79, 2}, + {12, 3}, + {76, 4}, }; static arc arcs_28_3[1] = { - {76, 4}, + {76, 4}, }; static arc arcs_28_4[3] = { - {31, 5}, - {13, 6}, - {80, 5}, + {31, 5}, + {13, 6}, + {80, 5}, }; static arc arcs_28_5[1] = { - {0, 5}, + {0, 5}, }; static arc arcs_28_6[1] = { - {80, 7}, + {80, 7}, }; static arc arcs_28_7[1] = { - {15, 5}, + {15, 5}, }; static state states_28[8] = { - {1, arcs_28_0}, - {3, arcs_28_1}, - {4, arcs_28_2}, - {1, arcs_28_3}, - {3, arcs_28_4}, - {1, arcs_28_5}, - {1, arcs_28_6}, - {1, arcs_28_7}, + {1, arcs_28_0}, + {3, arcs_28_1}, + {4, arcs_28_2}, + {1, arcs_28_3}, + {3, arcs_28_4}, + {1, arcs_28_5}, + {1, arcs_28_6}, + {1, arcs_28_7}, }; static arc arcs_29_0[1] = { - {21, 1}, + {21, 1}, }; static arc arcs_29_1[2] = { - {82, 2}, - {0, 1}, + {82, 2}, + {0, 1}, }; static arc arcs_29_2[1] = { - {21, 3}, + {21, 3}, }; static arc arcs_29_3[1] = { - {0, 3}, + {0, 3}, }; static state states_29[4] = { - {1, arcs_29_0}, - {2, arcs_29_1}, - {1, arcs_29_2}, - {1, arcs_29_3}, + {1, arcs_29_0}, + {2, arcs_29_1}, + {1, arcs_29_2}, + {1, arcs_29_3}, }; static arc arcs_30_0[1] = { - {12, 1}, + {12, 1}, }; static arc arcs_30_1[2] = { - {82, 2}, - {0, 1}, + {82, 2}, + {0, 1}, }; static arc arcs_30_2[1] = { - {21, 3}, + {21, 3}, }; static arc arcs_30_3[1] = { - {0, 3}, + {0, 3}, }; static state states_30[4] = { - {1, arcs_30_0}, - {2, arcs_30_1}, - {1, arcs_30_2}, - {1, arcs_30_3}, + {1, arcs_30_0}, + {2, arcs_30_1}, + {1, arcs_30_2}, + {1, arcs_30_3}, }; static arc arcs_31_0[1] = { - {81, 1}, + {81, 1}, }; static arc arcs_31_1[2] = { - {30, 2}, - {0, 1}, + {30, 2}, + {0, 1}, }; static arc arcs_31_2[2] = { - {81, 1}, - {0, 2}, + {81, 1}, + {0, 2}, }; static state states_31[3] = { - {1, arcs_31_0}, - {2, arcs_31_1}, - {2, arcs_31_2}, + {1, arcs_31_0}, + {2, arcs_31_1}, + {2, arcs_31_2}, }; static arc arcs_32_0[1] = { - {83, 1}, + {83, 1}, }; static arc arcs_32_1[2] = { - {30, 0}, - {0, 1}, + {30, 0}, + {0, 1}, }; static state states_32[2] = { - {1, arcs_32_0}, - {2, arcs_32_1}, + {1, arcs_32_0}, + {2, arcs_32_1}, }; static arc arcs_33_0[1] = { - {21, 1}, + {21, 1}, }; static arc arcs_33_1[2] = { - {78, 0}, - {0, 1}, + {78, 0}, + {0, 1}, }; static state states_33[2] = { - {1, arcs_33_0}, - {2, arcs_33_1}, + {1, arcs_33_0}, + {2, arcs_33_1}, }; static arc arcs_34_0[1] = { - {84, 1}, + {84, 1}, }; static arc arcs_34_1[1] = { - {21, 2}, + {21, 2}, }; static arc arcs_34_2[2] = { - {30, 1}, - {0, 2}, + {30, 1}, + {0, 2}, }; static state states_34[3] = { - {1, arcs_34_0}, - {1, arcs_34_1}, - {2, arcs_34_2}, + {1, arcs_34_0}, + {1, arcs_34_1}, + {2, arcs_34_2}, }; static arc arcs_35_0[1] = { - {85, 1}, + {85, 1}, }; static arc arcs_35_1[1] = { - {21, 2}, + {21, 2}, }; static arc arcs_35_2[2] = { - {30, 1}, - {0, 2}, + {30, 1}, + {0, 2}, }; static state states_35[3] = { - {1, arcs_35_0}, - {1, arcs_35_1}, - {2, arcs_35_2}, + {1, arcs_35_0}, + {1, arcs_35_1}, + {2, arcs_35_2}, }; static arc arcs_36_0[1] = { - {86, 1}, + {86, 1}, }; static arc arcs_36_1[1] = { - {24, 2}, + {24, 2}, }; static arc arcs_36_2[2] = { - {30, 3}, - {0, 2}, + {30, 3}, + {0, 2}, }; static arc arcs_36_3[1] = { - {24, 4}, + {24, 4}, }; static arc arcs_36_4[1] = { - {0, 4}, + {0, 4}, }; static state states_36[5] = { - {1, arcs_36_0}, - {1, arcs_36_1}, - {2, arcs_36_2}, - {1, arcs_36_3}, - {1, arcs_36_4}, + {1, arcs_36_0}, + {1, arcs_36_1}, + {2, arcs_36_2}, + {1, arcs_36_3}, + {1, arcs_36_4}, }; static arc arcs_37_0[8] = { - {87, 1}, - {88, 1}, - {89, 1}, - {90, 1}, - {91, 1}, - {19, 1}, - {18, 1}, - {17, 1}, + {87, 1}, + {88, 1}, + {89, 1}, + {90, 1}, + {91, 1}, + {19, 1}, + {18, 1}, + {17, 1}, }; static arc arcs_37_1[1] = { - {0, 1}, + {0, 1}, }; static state states_37[2] = { - {8, arcs_37_0}, - {1, arcs_37_1}, + {8, arcs_37_0}, + {1, arcs_37_1}, }; static arc arcs_38_0[1] = { - {92, 1}, + {92, 1}, }; static arc arcs_38_1[1] = { - {24, 2}, + {24, 2}, }; static arc arcs_38_2[1] = { - {25, 3}, + {25, 3}, }; static arc arcs_38_3[1] = { - {26, 4}, + {26, 4}, }; static arc arcs_38_4[3] = { - {93, 1}, - {94, 5}, - {0, 4}, + {93, 1}, + {94, 5}, + {0, 4}, }; static arc arcs_38_5[1] = { - {25, 6}, + {25, 6}, }; static arc arcs_38_6[1] = { - {26, 7}, + {26, 7}, }; static arc arcs_38_7[1] = { - {0, 7}, + {0, 7}, }; static state states_38[8] = { - {1, arcs_38_0}, - {1, arcs_38_1}, - {1, arcs_38_2}, - {1, arcs_38_3}, - {3, arcs_38_4}, - {1, arcs_38_5}, - {1, arcs_38_6}, - {1, arcs_38_7}, + {1, arcs_38_0}, + {1, arcs_38_1}, + {1, arcs_38_2}, + {1, arcs_38_3}, + {3, arcs_38_4}, + {1, arcs_38_5}, + {1, arcs_38_6}, + {1, arcs_38_7}, }; static arc arcs_39_0[1] = { - {95, 1}, + {95, 1}, }; static arc arcs_39_1[1] = { - {24, 2}, + {24, 2}, }; static arc arcs_39_2[1] = { - {25, 3}, + {25, 3}, }; static arc arcs_39_3[1] = { - {26, 4}, + {26, 4}, }; static arc arcs_39_4[2] = { - {94, 5}, - {0, 4}, + {94, 5}, + {0, 4}, }; static arc arcs_39_5[1] = { - {25, 6}, + {25, 6}, }; static arc arcs_39_6[1] = { - {26, 7}, + {26, 7}, }; static arc arcs_39_7[1] = { - {0, 7}, + {0, 7}, }; static state states_39[8] = { - {1, arcs_39_0}, - {1, arcs_39_1}, - {1, arcs_39_2}, - {1, arcs_39_3}, - {2, arcs_39_4}, - {1, arcs_39_5}, - {1, arcs_39_6}, - {1, arcs_39_7}, + {1, arcs_39_0}, + {1, arcs_39_1}, + {1, arcs_39_2}, + {1, arcs_39_3}, + {2, arcs_39_4}, + {1, arcs_39_5}, + {1, arcs_39_6}, + {1, arcs_39_7}, }; static arc arcs_40_0[1] = { - {96, 1}, + {96, 1}, }; static arc arcs_40_1[1] = { - {62, 2}, + {62, 2}, }; static arc arcs_40_2[1] = { - {97, 3}, + {97, 3}, }; static arc arcs_40_3[1] = { - {9, 4}, + {9, 4}, }; static arc arcs_40_4[1] = { - {25, 5}, + {25, 5}, }; static arc arcs_40_5[1] = { - {26, 6}, + {26, 6}, }; static arc arcs_40_6[2] = { - {94, 7}, - {0, 6}, + {94, 7}, + {0, 6}, }; static arc arcs_40_7[1] = { - {25, 8}, + {25, 8}, }; static arc arcs_40_8[1] = { - {26, 9}, + {26, 9}, }; static arc arcs_40_9[1] = { - {0, 9}, + {0, 9}, }; static state states_40[10] = { - {1, arcs_40_0}, - {1, arcs_40_1}, - {1, arcs_40_2}, - {1, arcs_40_3}, - {1, arcs_40_4}, - {1, arcs_40_5}, - {2, arcs_40_6}, - {1, arcs_40_7}, - {1, arcs_40_8}, - {1, arcs_40_9}, + {1, arcs_40_0}, + {1, arcs_40_1}, + {1, arcs_40_2}, + {1, arcs_40_3}, + {1, arcs_40_4}, + {1, arcs_40_5}, + {2, arcs_40_6}, + {1, arcs_40_7}, + {1, arcs_40_8}, + {1, arcs_40_9}, }; static arc arcs_41_0[1] = { - {98, 1}, + {98, 1}, }; static arc arcs_41_1[1] = { - {25, 2}, + {25, 2}, }; static arc arcs_41_2[1] = { - {26, 3}, + {26, 3}, }; static arc arcs_41_3[2] = { - {99, 4}, - {100, 5}, + {99, 4}, + {100, 5}, }; static arc arcs_41_4[1] = { - {25, 6}, + {25, 6}, }; static arc arcs_41_5[1] = { - {25, 7}, + {25, 7}, }; static arc arcs_41_6[1] = { - {26, 8}, + {26, 8}, }; static arc arcs_41_7[1] = { - {26, 9}, + {26, 9}, }; static arc arcs_41_8[4] = { - {99, 4}, - {94, 10}, - {100, 5}, - {0, 8}, + {99, 4}, + {94, 10}, + {100, 5}, + {0, 8}, }; static arc arcs_41_9[1] = { - {0, 9}, + {0, 9}, }; static arc arcs_41_10[1] = { - {25, 11}, + {25, 11}, }; static arc arcs_41_11[1] = { - {26, 12}, + {26, 12}, }; static arc arcs_41_12[2] = { - {100, 5}, - {0, 12}, + {100, 5}, + {0, 12}, }; static state states_41[13] = { - {1, arcs_41_0}, - {1, arcs_41_1}, - {1, arcs_41_2}, - {2, arcs_41_3}, - {1, arcs_41_4}, - {1, arcs_41_5}, - {1, arcs_41_6}, - {1, arcs_41_7}, - {4, arcs_41_8}, - {1, arcs_41_9}, - {1, arcs_41_10}, - {1, arcs_41_11}, - {2, arcs_41_12}, + {1, arcs_41_0}, + {1, arcs_41_1}, + {1, arcs_41_2}, + {2, arcs_41_3}, + {1, arcs_41_4}, + {1, arcs_41_5}, + {1, arcs_41_6}, + {1, arcs_41_7}, + {4, arcs_41_8}, + {1, arcs_41_9}, + {1, arcs_41_10}, + {1, arcs_41_11}, + {2, arcs_41_12}, }; static arc arcs_42_0[1] = { - {101, 1}, + {101, 1}, }; static arc arcs_42_1[1] = { - {102, 2}, + {102, 2}, }; static arc arcs_42_2[2] = { - {30, 1}, - {25, 3}, + {30, 1}, + {25, 3}, }; static arc arcs_42_3[1] = { - {26, 4}, + {26, 4}, }; static arc arcs_42_4[1] = { - {0, 4}, + {0, 4}, }; static state states_42[5] = { - {1, arcs_42_0}, - {1, arcs_42_1}, - {2, arcs_42_2}, - {1, arcs_42_3}, - {1, arcs_42_4}, + {1, arcs_42_0}, + {1, arcs_42_1}, + {2, arcs_42_2}, + {1, arcs_42_3}, + {1, arcs_42_4}, }; static arc arcs_43_0[1] = { - {24, 1}, + {24, 1}, }; static arc arcs_43_1[2] = { - {82, 2}, - {0, 1}, + {82, 2}, + {0, 1}, }; static arc arcs_43_2[1] = { - {103, 3}, + {103, 3}, }; static arc arcs_43_3[1] = { - {0, 3}, + {0, 3}, }; static state states_43[4] = { - {1, arcs_43_0}, - {2, arcs_43_1}, - {1, arcs_43_2}, - {1, arcs_43_3}, + {1, arcs_43_0}, + {2, arcs_43_1}, + {1, arcs_43_2}, + {1, arcs_43_3}, }; static arc arcs_44_0[1] = { - {104, 1}, + {104, 1}, }; static arc arcs_44_1[2] = { - {24, 2}, - {0, 1}, + {24, 2}, + {0, 1}, }; static arc arcs_44_2[2] = { - {82, 3}, - {0, 2}, + {82, 3}, + {0, 2}, }; static arc arcs_44_3[1] = { - {21, 4}, + {21, 4}, }; static arc arcs_44_4[1] = { - {0, 4}, + {0, 4}, }; static state states_44[5] = { - {1, arcs_44_0}, - {2, arcs_44_1}, - {2, arcs_44_2}, - {1, arcs_44_3}, - {1, arcs_44_4}, + {1, arcs_44_0}, + {2, arcs_44_1}, + {2, arcs_44_2}, + {1, arcs_44_3}, + {1, arcs_44_4}, }; static arc arcs_45_0[2] = { - {3, 1}, - {2, 2}, + {3, 1}, + {2, 2}, }; static arc arcs_45_1[1] = { - {0, 1}, + {0, 1}, }; static arc arcs_45_2[1] = { - {105, 3}, + {105, 3}, }; static arc arcs_45_3[1] = { - {6, 4}, + {6, 4}, }; static arc arcs_45_4[2] = { - {6, 4}, - {106, 1}, + {6, 4}, + {106, 1}, }; static state states_45[5] = { - {2, arcs_45_0}, - {1, arcs_45_1}, - {1, arcs_45_2}, - {1, arcs_45_3}, - {2, arcs_45_4}, + {2, arcs_45_0}, + {1, arcs_45_1}, + {1, arcs_45_2}, + {1, arcs_45_3}, + {2, arcs_45_4}, }; static arc arcs_46_0[2] = { - {107, 1}, - {108, 2}, + {107, 1}, + {108, 2}, }; static arc arcs_46_1[2] = { - {92, 3}, - {0, 1}, + {92, 3}, + {0, 1}, }; static arc arcs_46_2[1] = { - {0, 2}, + {0, 2}, }; static arc arcs_46_3[1] = { - {107, 4}, + {107, 4}, }; static arc arcs_46_4[1] = { - {94, 5}, + {94, 5}, }; static arc arcs_46_5[1] = { - {24, 2}, + {24, 2}, }; static state states_46[6] = { - {2, arcs_46_0}, - {2, arcs_46_1}, - {1, arcs_46_2}, - {1, arcs_46_3}, - {1, arcs_46_4}, - {1, arcs_46_5}, + {2, arcs_46_0}, + {2, arcs_46_1}, + {1, arcs_46_2}, + {1, arcs_46_3}, + {1, arcs_46_4}, + {1, arcs_46_5}, }; static arc arcs_47_0[2] = { - {107, 1}, - {110, 1}, + {107, 1}, + {110, 1}, }; static arc arcs_47_1[1] = { - {0, 1}, + {0, 1}, }; static state states_47[2] = { - {2, arcs_47_0}, - {1, arcs_47_1}, + {2, arcs_47_0}, + {1, arcs_47_1}, }; static arc arcs_48_0[1] = { - {111, 1}, + {111, 1}, }; static arc arcs_48_1[2] = { - {33, 2}, - {25, 3}, + {33, 2}, + {25, 3}, }; static arc arcs_48_2[1] = { - {25, 3}, + {25, 3}, }; static arc arcs_48_3[1] = { - {24, 4}, + {24, 4}, }; static arc arcs_48_4[1] = { - {0, 4}, + {0, 4}, }; static state states_48[5] = { - {1, arcs_48_0}, - {2, arcs_48_1}, - {1, arcs_48_2}, - {1, arcs_48_3}, - {1, arcs_48_4}, + {1, arcs_48_0}, + {2, arcs_48_1}, + {1, arcs_48_2}, + {1, arcs_48_3}, + {1, arcs_48_4}, }; static arc arcs_49_0[1] = { - {111, 1}, + {111, 1}, }; static arc arcs_49_1[2] = { - {33, 2}, - {25, 3}, + {33, 2}, + {25, 3}, }; static arc arcs_49_2[1] = { - {25, 3}, + {25, 3}, }; static arc arcs_49_3[1] = { - {109, 4}, + {109, 4}, }; static arc arcs_49_4[1] = { - {0, 4}, + {0, 4}, }; static state states_49[5] = { - {1, arcs_49_0}, - {2, arcs_49_1}, - {1, arcs_49_2}, - {1, arcs_49_3}, - {1, arcs_49_4}, + {1, arcs_49_0}, + {2, arcs_49_1}, + {1, arcs_49_2}, + {1, arcs_49_3}, + {1, arcs_49_4}, }; static arc arcs_50_0[1] = { - {112, 1}, + {112, 1}, }; static arc arcs_50_1[2] = { - {113, 0}, - {0, 1}, + {113, 0}, + {0, 1}, }; static state states_50[2] = { - {1, arcs_50_0}, - {2, arcs_50_1}, + {1, arcs_50_0}, + {2, arcs_50_1}, }; static arc arcs_51_0[1] = { - {114, 1}, + {114, 1}, }; static arc arcs_51_1[2] = { - {115, 0}, - {0, 1}, + {115, 0}, + {0, 1}, }; static state states_51[2] = { - {1, arcs_51_0}, - {2, arcs_51_1}, + {1, arcs_51_0}, + {2, arcs_51_1}, }; static arc arcs_52_0[2] = { - {116, 1}, - {117, 2}, + {116, 1}, + {117, 2}, }; static arc arcs_52_1[1] = { - {114, 2}, + {114, 2}, }; static arc arcs_52_2[1] = { - {0, 2}, + {0, 2}, }; static state states_52[3] = { - {2, arcs_52_0}, - {1, arcs_52_1}, - {1, arcs_52_2}, + {2, arcs_52_0}, + {1, arcs_52_1}, + {1, arcs_52_2}, }; static arc arcs_53_0[1] = { - {103, 1}, + {103, 1}, }; static arc arcs_53_1[2] = { - {118, 0}, - {0, 1}, + {118, 0}, + {0, 1}, }; static state states_53[2] = { - {1, arcs_53_0}, - {2, arcs_53_1}, + {1, arcs_53_0}, + {2, arcs_53_1}, }; static arc arcs_54_0[10] = { - {119, 1}, - {120, 1}, - {121, 1}, - {122, 1}, - {123, 1}, - {124, 1}, - {125, 1}, - {97, 1}, - {116, 2}, - {126, 3}, + {119, 1}, + {120, 1}, + {121, 1}, + {122, 1}, + {123, 1}, + {124, 1}, + {125, 1}, + {97, 1}, + {116, 2}, + {126, 3}, }; static arc arcs_54_1[1] = { - {0, 1}, + {0, 1}, }; static arc arcs_54_2[1] = { - {97, 1}, + {97, 1}, }; static arc arcs_54_3[2] = { - {116, 1}, - {0, 3}, + {116, 1}, + {0, 3}, }; static state states_54[4] = { - {10, arcs_54_0}, - {1, arcs_54_1}, - {1, arcs_54_2}, - {2, arcs_54_3}, + {10, arcs_54_0}, + {1, arcs_54_1}, + {1, arcs_54_2}, + {2, arcs_54_3}, }; static arc arcs_55_0[1] = { - {31, 1}, + {31, 1}, }; static arc arcs_55_1[1] = { - {103, 2}, + {103, 2}, }; static arc arcs_55_2[1] = { - {0, 2}, + {0, 2}, }; static state states_55[3] = { - {1, arcs_55_0}, - {1, arcs_55_1}, - {1, arcs_55_2}, + {1, arcs_55_0}, + {1, arcs_55_1}, + {1, arcs_55_2}, }; static arc arcs_56_0[1] = { - {127, 1}, + {127, 1}, }; static arc arcs_56_1[2] = { - {128, 0}, - {0, 1}, + {128, 0}, + {0, 1}, }; static state states_56[2] = { - {1, arcs_56_0}, - {2, arcs_56_1}, + {1, arcs_56_0}, + {2, arcs_56_1}, }; static arc arcs_57_0[1] = { - {129, 1}, + {129, 1}, }; static arc arcs_57_1[2] = { - {130, 0}, - {0, 1}, + {130, 0}, + {0, 1}, }; static state states_57[2] = { - {1, arcs_57_0}, - {2, arcs_57_1}, + {1, arcs_57_0}, + {2, arcs_57_1}, }; static arc arcs_58_0[1] = { - {131, 1}, + {131, 1}, }; static arc arcs_58_1[2] = { - {132, 0}, - {0, 1}, + {132, 0}, + {0, 1}, }; static state states_58[2] = { - {1, arcs_58_0}, - {2, arcs_58_1}, + {1, arcs_58_0}, + {2, arcs_58_1}, }; static arc arcs_59_0[1] = { - {133, 1}, + {133, 1}, }; static arc arcs_59_1[3] = { - {134, 0}, - {135, 0}, - {0, 1}, + {134, 0}, + {135, 0}, + {0, 1}, }; static state states_59[2] = { - {1, arcs_59_0}, - {3, arcs_59_1}, + {1, arcs_59_0}, + {3, arcs_59_1}, }; static arc arcs_60_0[1] = { - {136, 1}, + {136, 1}, }; static arc arcs_60_1[3] = { - {137, 0}, - {138, 0}, - {0, 1}, + {137, 0}, + {138, 0}, + {0, 1}, }; static state states_60[2] = { - {1, arcs_60_0}, - {3, arcs_60_1}, + {1, arcs_60_0}, + {3, arcs_60_1}, }; static arc arcs_61_0[1] = { - {139, 1}, + {139, 1}, }; static arc arcs_61_1[5] = { - {31, 0}, - {140, 0}, - {141, 0}, - {142, 0}, - {0, 1}, + {31, 0}, + {140, 0}, + {141, 0}, + {142, 0}, + {0, 1}, }; static state states_61[2] = { - {1, arcs_61_0}, - {5, arcs_61_1}, + {1, arcs_61_0}, + {5, arcs_61_1}, }; static arc arcs_62_0[4] = { - {137, 1}, - {138, 1}, - {143, 1}, - {144, 2}, + {137, 1}, + {138, 1}, + {143, 1}, + {144, 2}, }; static arc arcs_62_1[1] = { - {139, 2}, + {139, 2}, }; static arc arcs_62_2[1] = { - {0, 2}, + {0, 2}, }; static state states_62[3] = { - {4, arcs_62_0}, - {1, arcs_62_1}, - {1, arcs_62_2}, + {4, arcs_62_0}, + {1, arcs_62_1}, + {1, arcs_62_2}, }; static arc arcs_63_0[1] = { - {145, 1}, + {145, 1}, }; static arc arcs_63_1[3] = { - {146, 1}, - {32, 2}, - {0, 1}, + {146, 1}, + {32, 2}, + {0, 1}, }; static arc arcs_63_2[1] = { - {139, 3}, + {139, 3}, }; static arc arcs_63_3[1] = { - {0, 3}, + {0, 3}, }; static state states_63[4] = { - {1, arcs_63_0}, - {3, arcs_63_1}, - {1, arcs_63_2}, - {1, arcs_63_3}, + {1, arcs_63_0}, + {3, arcs_63_1}, + {1, arcs_63_2}, + {1, arcs_63_3}, }; static arc arcs_64_0[10] = { - {13, 1}, - {148, 2}, - {150, 3}, - {21, 4}, - {153, 4}, - {154, 5}, - {79, 4}, - {155, 4}, - {156, 4}, - {157, 4}, + {13, 1}, + {148, 2}, + {150, 3}, + {21, 4}, + {153, 4}, + {154, 5}, + {79, 4}, + {155, 4}, + {156, 4}, + {157, 4}, }; static arc arcs_64_1[3] = { - {47, 6}, - {147, 6}, - {15, 4}, + {47, 6}, + {147, 6}, + {15, 4}, }; static arc arcs_64_2[2] = { - {147, 7}, - {149, 4}, + {147, 7}, + {149, 4}, }; static arc arcs_64_3[2] = { - {151, 8}, - {152, 4}, + {151, 8}, + {152, 4}, }; static arc arcs_64_4[1] = { - {0, 4}, + {0, 4}, }; static arc arcs_64_5[2] = { - {154, 5}, - {0, 5}, + {154, 5}, + {0, 5}, }; static arc arcs_64_6[1] = { - {15, 4}, + {15, 4}, }; static arc arcs_64_7[1] = { - {149, 4}, + {149, 4}, }; static arc arcs_64_8[1] = { - {152, 4}, + {152, 4}, }; static state states_64[9] = { - {10, arcs_64_0}, - {3, arcs_64_1}, - {2, arcs_64_2}, - {2, arcs_64_3}, - {1, arcs_64_4}, - {2, arcs_64_5}, - {1, arcs_64_6}, - {1, arcs_64_7}, - {1, arcs_64_8}, + {10, arcs_64_0}, + {3, arcs_64_1}, + {2, arcs_64_2}, + {2, arcs_64_3}, + {1, arcs_64_4}, + {2, arcs_64_5}, + {1, arcs_64_6}, + {1, arcs_64_7}, + {1, arcs_64_8}, }; static arc arcs_65_0[2] = { - {24, 1}, - {48, 1}, + {24, 1}, + {48, 1}, }; static arc arcs_65_1[3] = { - {158, 2}, - {30, 3}, - {0, 1}, + {158, 2}, + {30, 3}, + {0, 1}, }; static arc arcs_65_2[1] = { - {0, 2}, + {0, 2}, }; static arc arcs_65_3[3] = { - {24, 4}, - {48, 4}, - {0, 3}, + {24, 4}, + {48, 4}, + {0, 3}, }; static arc arcs_65_4[2] = { - {30, 3}, - {0, 4}, + {30, 3}, + {0, 4}, }; static state states_65[5] = { - {2, arcs_65_0}, - {3, arcs_65_1}, - {1, arcs_65_2}, - {3, arcs_65_3}, - {2, arcs_65_4}, + {2, arcs_65_0}, + {3, arcs_65_1}, + {1, arcs_65_2}, + {3, arcs_65_3}, + {2, arcs_65_4}, }; static arc arcs_66_0[3] = { - {13, 1}, - {148, 2}, - {78, 3}, + {13, 1}, + {148, 2}, + {78, 3}, }; static arc arcs_66_1[2] = { - {14, 4}, - {15, 5}, + {14, 4}, + {15, 5}, }; static arc arcs_66_2[1] = { - {159, 6}, + {159, 6}, }; static arc arcs_66_3[1] = { - {21, 5}, + {21, 5}, }; static arc arcs_66_4[1] = { - {15, 5}, + {15, 5}, }; static arc arcs_66_5[1] = { - {0, 5}, + {0, 5}, }; static arc arcs_66_6[1] = { - {149, 5}, + {149, 5}, }; static state states_66[7] = { - {3, arcs_66_0}, - {2, arcs_66_1}, - {1, arcs_66_2}, - {1, arcs_66_3}, - {1, arcs_66_4}, - {1, arcs_66_5}, - {1, arcs_66_6}, + {3, arcs_66_0}, + {2, arcs_66_1}, + {1, arcs_66_2}, + {1, arcs_66_3}, + {1, arcs_66_4}, + {1, arcs_66_5}, + {1, arcs_66_6}, }; static arc arcs_67_0[1] = { - {160, 1}, + {160, 1}, }; static arc arcs_67_1[2] = { - {30, 2}, - {0, 1}, + {30, 2}, + {0, 1}, }; static arc arcs_67_2[2] = { - {160, 1}, - {0, 2}, + {160, 1}, + {0, 2}, }; static state states_67[3] = { - {1, arcs_67_0}, - {2, arcs_67_1}, - {2, arcs_67_2}, + {1, arcs_67_0}, + {2, arcs_67_1}, + {2, arcs_67_2}, }; static arc arcs_68_0[2] = { - {24, 1}, - {25, 2}, + {24, 1}, + {25, 2}, }; static arc arcs_68_1[2] = { - {25, 2}, - {0, 1}, + {25, 2}, + {0, 1}, }; static arc arcs_68_2[3] = { - {24, 3}, - {161, 4}, - {0, 2}, + {24, 3}, + {161, 4}, + {0, 2}, }; static arc arcs_68_3[2] = { - {161, 4}, - {0, 3}, + {161, 4}, + {0, 3}, }; static arc arcs_68_4[1] = { - {0, 4}, + {0, 4}, }; static state states_68[5] = { - {2, arcs_68_0}, - {2, arcs_68_1}, - {3, arcs_68_2}, - {2, arcs_68_3}, - {1, arcs_68_4}, + {2, arcs_68_0}, + {2, arcs_68_1}, + {3, arcs_68_2}, + {2, arcs_68_3}, + {1, arcs_68_4}, }; static arc arcs_69_0[1] = { - {25, 1}, + {25, 1}, }; static arc arcs_69_1[2] = { - {24, 2}, - {0, 1}, + {24, 2}, + {0, 1}, }; static arc arcs_69_2[1] = { - {0, 2}, + {0, 2}, }; static state states_69[3] = { - {1, arcs_69_0}, - {2, arcs_69_1}, - {1, arcs_69_2}, + {1, arcs_69_0}, + {2, arcs_69_1}, + {1, arcs_69_2}, }; static arc arcs_70_0[2] = { - {103, 1}, - {48, 1}, + {103, 1}, + {48, 1}, }; static arc arcs_70_1[2] = { - {30, 2}, - {0, 1}, + {30, 2}, + {0, 1}, }; static arc arcs_70_2[3] = { - {103, 1}, - {48, 1}, - {0, 2}, + {103, 1}, + {48, 1}, + {0, 2}, }; static state states_70[3] = { - {2, arcs_70_0}, - {2, arcs_70_1}, - {3, arcs_70_2}, + {2, arcs_70_0}, + {2, arcs_70_1}, + {3, arcs_70_2}, }; static arc arcs_71_0[1] = { - {24, 1}, + {24, 1}, }; static arc arcs_71_1[2] = { - {30, 2}, - {0, 1}, + {30, 2}, + {0, 1}, }; static arc arcs_71_2[2] = { - {24, 1}, - {0, 2}, + {24, 1}, + {0, 2}, }; static state states_71[3] = { - {1, arcs_71_0}, - {2, arcs_71_1}, - {2, arcs_71_2}, + {1, arcs_71_0}, + {2, arcs_71_1}, + {2, arcs_71_2}, }; static arc arcs_72_0[1] = { - {24, 1}, + {24, 1}, }; static arc arcs_72_1[4] = { - {25, 2}, - {158, 3}, - {30, 4}, - {0, 1}, + {25, 2}, + {158, 3}, + {30, 4}, + {0, 1}, }; static arc arcs_72_2[1] = { - {24, 5}, + {24, 5}, }; static arc arcs_72_3[1] = { - {0, 3}, + {0, 3}, }; static arc arcs_72_4[2] = { - {24, 6}, - {0, 4}, + {24, 6}, + {0, 4}, }; static arc arcs_72_5[3] = { - {158, 3}, - {30, 7}, - {0, 5}, + {158, 3}, + {30, 7}, + {0, 5}, }; static arc arcs_72_6[2] = { - {30, 4}, - {0, 6}, + {30, 4}, + {0, 6}, }; static arc arcs_72_7[2] = { - {24, 8}, - {0, 7}, + {24, 8}, + {0, 7}, }; static arc arcs_72_8[1] = { - {25, 9}, + {25, 9}, }; static arc arcs_72_9[1] = { - {24, 10}, + {24, 10}, }; static arc arcs_72_10[2] = { - {30, 7}, - {0, 10}, + {30, 7}, + {0, 10}, }; static state states_72[11] = { - {1, arcs_72_0}, - {4, arcs_72_1}, - {1, arcs_72_2}, - {1, arcs_72_3}, - {2, arcs_72_4}, - {3, arcs_72_5}, - {2, arcs_72_6}, - {2, arcs_72_7}, - {1, arcs_72_8}, - {1, arcs_72_9}, - {2, arcs_72_10}, + {1, arcs_72_0}, + {4, arcs_72_1}, + {1, arcs_72_2}, + {1, arcs_72_3}, + {2, arcs_72_4}, + {3, arcs_72_5}, + {2, arcs_72_6}, + {2, arcs_72_7}, + {1, arcs_72_8}, + {1, arcs_72_9}, + {2, arcs_72_10}, }; static arc arcs_73_0[1] = { - {162, 1}, + {162, 1}, }; static arc arcs_73_1[1] = { - {21, 2}, + {21, 2}, }; static arc arcs_73_2[2] = { - {13, 3}, - {25, 4}, + {13, 3}, + {25, 4}, }; static arc arcs_73_3[2] = { - {14, 5}, - {15, 6}, + {14, 5}, + {15, 6}, }; static arc arcs_73_4[1] = { - {26, 7}, + {26, 7}, }; static arc arcs_73_5[1] = { - {15, 6}, + {15, 6}, }; static arc arcs_73_6[1] = { - {25, 4}, + {25, 4}, }; static arc arcs_73_7[1] = { - {0, 7}, + {0, 7}, }; static state states_73[8] = { - {1, arcs_73_0}, - {1, arcs_73_1}, - {2, arcs_73_2}, - {2, arcs_73_3}, - {1, arcs_73_4}, - {1, arcs_73_5}, - {1, arcs_73_6}, - {1, arcs_73_7}, + {1, arcs_73_0}, + {1, arcs_73_1}, + {2, arcs_73_2}, + {2, arcs_73_3}, + {1, arcs_73_4}, + {1, arcs_73_5}, + {1, arcs_73_6}, + {1, arcs_73_7}, }; static arc arcs_74_0[3] = { - {163, 1}, - {31, 2}, - {32, 3}, + {163, 1}, + {31, 2}, + {32, 3}, }; static arc arcs_74_1[2] = { - {30, 4}, - {0, 1}, + {30, 4}, + {0, 1}, }; static arc arcs_74_2[1] = { - {24, 5}, + {24, 5}, }; static arc arcs_74_3[1] = { - {24, 6}, + {24, 6}, }; static arc arcs_74_4[4] = { - {163, 1}, - {31, 2}, - {32, 3}, - {0, 4}, + {163, 1}, + {31, 2}, + {32, 3}, + {0, 4}, }; static arc arcs_74_5[2] = { - {30, 7}, - {0, 5}, + {30, 7}, + {0, 5}, }; static arc arcs_74_6[1] = { - {0, 6}, + {0, 6}, }; static arc arcs_74_7[2] = { - {163, 5}, - {32, 3}, + {163, 5}, + {32, 3}, }; static state states_74[8] = { - {3, arcs_74_0}, - {2, arcs_74_1}, - {1, arcs_74_2}, - {1, arcs_74_3}, - {4, arcs_74_4}, - {2, arcs_74_5}, - {1, arcs_74_6}, - {2, arcs_74_7}, + {3, arcs_74_0}, + {2, arcs_74_1}, + {1, arcs_74_2}, + {1, arcs_74_3}, + {4, arcs_74_4}, + {2, arcs_74_5}, + {1, arcs_74_6}, + {2, arcs_74_7}, }; static arc arcs_75_0[1] = { - {24, 1}, + {24, 1}, }; static arc arcs_75_1[3] = { - {158, 2}, - {29, 3}, - {0, 1}, + {158, 2}, + {29, 3}, + {0, 1}, }; static arc arcs_75_2[1] = { - {0, 2}, + {0, 2}, }; static arc arcs_75_3[1] = { - {24, 2}, + {24, 2}, }; static state states_75[4] = { - {1, arcs_75_0}, - {3, arcs_75_1}, - {1, arcs_75_2}, - {1, arcs_75_3}, + {1, arcs_75_0}, + {3, arcs_75_1}, + {1, arcs_75_2}, + {1, arcs_75_3}, }; static arc arcs_76_0[2] = { - {158, 1}, - {165, 1}, + {158, 1}, + {165, 1}, }; static arc arcs_76_1[1] = { - {0, 1}, + {0, 1}, }; static state states_76[2] = { - {2, arcs_76_0}, - {1, arcs_76_1}, + {2, arcs_76_0}, + {1, arcs_76_1}, }; static arc arcs_77_0[1] = { - {96, 1}, + {96, 1}, }; static arc arcs_77_1[1] = { - {62, 2}, + {62, 2}, }; static arc arcs_77_2[1] = { - {97, 3}, + {97, 3}, }; static arc arcs_77_3[1] = { - {107, 4}, + {107, 4}, }; static arc arcs_77_4[2] = { - {164, 5}, - {0, 4}, + {164, 5}, + {0, 4}, }; static arc arcs_77_5[1] = { - {0, 5}, + {0, 5}, }; static state states_77[6] = { - {1, arcs_77_0}, - {1, arcs_77_1}, - {1, arcs_77_2}, - {1, arcs_77_3}, - {2, arcs_77_4}, - {1, arcs_77_5}, + {1, arcs_77_0}, + {1, arcs_77_1}, + {1, arcs_77_2}, + {1, arcs_77_3}, + {2, arcs_77_4}, + {1, arcs_77_5}, }; static arc arcs_78_0[1] = { - {92, 1}, + {92, 1}, }; static arc arcs_78_1[1] = { - {109, 2}, + {109, 2}, }; static arc arcs_78_2[2] = { - {164, 3}, - {0, 2}, + {164, 3}, + {0, 2}, }; static arc arcs_78_3[1] = { - {0, 3}, + {0, 3}, }; static state states_78[4] = { - {1, arcs_78_0}, - {1, arcs_78_1}, - {2, arcs_78_2}, - {1, arcs_78_3}, + {1, arcs_78_0}, + {1, arcs_78_1}, + {2, arcs_78_2}, + {1, arcs_78_3}, }; static arc arcs_79_0[1] = { - {21, 1}, + {21, 1}, }; static arc arcs_79_1[1] = { - {0, 1}, + {0, 1}, }; static state states_79[2] = { - {1, arcs_79_0}, - {1, arcs_79_1}, + {1, arcs_79_0}, + {1, arcs_79_1}, }; static arc arcs_80_0[1] = { - {167, 1}, + {167, 1}, }; static arc arcs_80_1[2] = { - {9, 2}, - {0, 1}, + {9, 2}, + {0, 1}, }; static arc arcs_80_2[1] = { - {0, 2}, + {0, 2}, }; static state states_80[3] = { - {1, arcs_80_0}, - {2, arcs_80_1}, - {1, arcs_80_2}, + {1, arcs_80_0}, + {2, arcs_80_1}, + {1, arcs_80_2}, }; static dfa dfas[81] = { - {256, "single_input", 0, 3, states_0, - "\004\050\060\200\000\000\000\240\340\223\160\220\045\200\020\000\000\206\120\076\204"}, - {257, "file_input", 0, 2, states_1, - "\204\050\060\200\000\000\000\240\340\223\160\220\045\200\020\000\000\206\120\076\204"}, - {258, "eval_input", 0, 3, states_2, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, - {259, "decorator", 0, 7, states_3, - "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {260, "decorators", 0, 2, states_4, - "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {261, "decorated", 0, 3, states_5, - "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {262, "funcdef", 0, 8, states_6, - "\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {263, "parameters", 0, 4, states_7, - "\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {264, "typedargslist", 0, 12, states_8, - "\000\000\040\200\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {265, "tfpdef", 0, 4, states_9, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {266, "varargslist", 0, 12, states_10, - "\000\000\040\200\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {267, "vfpdef", 0, 2, states_11, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {268, "stmt", 0, 2, states_12, - "\000\050\060\200\000\000\000\240\340\223\160\220\045\200\020\000\000\206\120\076\204"}, - {269, "simple_stmt", 0, 4, states_13, - "\000\040\040\200\000\000\000\240\340\223\160\000\000\200\020\000\000\206\120\076\200"}, - {270, "small_stmt", 0, 2, states_14, - "\000\040\040\200\000\000\000\240\340\223\160\000\000\200\020\000\000\206\120\076\200"}, - {271, "expr_stmt", 0, 6, states_15, - "\000\040\040\200\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, - {272, "testlist_star_expr", 0, 3, states_16, - "\000\040\040\200\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, - {273, "augassign", 0, 2, states_17, - "\000\000\000\000\000\000\376\037\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {274, "del_stmt", 0, 3, states_18, - "\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {275, "pass_stmt", 0, 2, states_19, - "\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {276, "flow_stmt", 0, 2, states_20, - "\000\000\000\000\000\000\000\000\340\001\000\000\000\000\000\000\000\000\000\000\200"}, - {277, "break_stmt", 0, 2, states_21, - "\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000"}, - {278, "continue_stmt", 0, 2, states_22, - "\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000\000\000\000"}, - {279, "return_stmt", 0, 3, states_23, - "\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000"}, - {280, "yield_stmt", 0, 2, states_24, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200"}, - {281, "raise_stmt", 0, 5, states_25, - "\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000"}, - {282, "import_stmt", 0, 2, states_26, - "\000\000\000\000\000\000\000\000\000\022\000\000\000\000\000\000\000\000\000\000\000"}, - {283, "import_name", 0, 3, states_27, - "\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000"}, - {284, "import_from", 0, 8, states_28, - "\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000"}, - {285, "import_as_name", 0, 4, states_29, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {286, "dotted_as_name", 0, 4, states_30, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {287, "import_as_names", 0, 3, states_31, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {288, "dotted_as_names", 0, 2, states_32, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {289, "dotted_name", 0, 2, states_33, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {290, "global_stmt", 0, 3, states_34, - "\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000"}, - {291, "nonlocal_stmt", 0, 3, states_35, - "\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000"}, - {292, "assert_stmt", 0, 5, states_36, - "\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000\000"}, - {293, "compound_stmt", 0, 2, states_37, - "\000\010\020\000\000\000\000\000\000\000\000\220\045\000\000\000\000\000\000\000\004"}, - {294, "if_stmt", 0, 8, states_38, - "\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000"}, - {295, "while_stmt", 0, 8, states_39, - "\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000"}, - {296, "for_stmt", 0, 10, states_40, - "\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000"}, - {297, "try_stmt", 0, 13, states_41, - "\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000"}, - {298, "with_stmt", 0, 5, states_42, - "\000\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000"}, - {299, "with_item", 0, 4, states_43, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, - {300, "except_clause", 0, 5, states_44, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000"}, - {301, "suite", 0, 5, states_45, - "\004\040\040\200\000\000\000\240\340\223\160\000\000\200\020\000\000\206\120\076\200"}, - {302, "test", 0, 6, states_46, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, - {303, "test_nocond", 0, 2, states_47, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, - {304, "lambdef", 0, 5, states_48, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000"}, - {305, "lambdef_nocond", 0, 5, states_49, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000"}, - {306, "or_test", 0, 2, states_50, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\020\000\000\206\120\076\000"}, - {307, "and_test", 0, 2, states_51, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\020\000\000\206\120\076\000"}, - {308, "not_test", 0, 3, states_52, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\020\000\000\206\120\076\000"}, - {309, "comparison", 0, 2, states_53, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, - {310, "comp_op", 0, 4, states_54, - "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\220\177\000\000\000\000\000"}, - {311, "star_expr", 0, 3, states_55, - "\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {312, "expr", 0, 2, states_56, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, - {313, "xor_expr", 0, 2, states_57, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, - {314, "and_expr", 0, 2, states_58, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, - {315, "shift_expr", 0, 2, states_59, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, - {316, "arith_expr", 0, 2, states_60, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, - {317, "term", 0, 2, states_61, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, - {318, "factor", 0, 3, states_62, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, - {319, "power", 0, 4, states_63, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\120\076\000"}, - {320, "atom", 0, 9, states_64, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\120\076\000"}, - {321, "testlist_comp", 0, 5, states_65, - "\000\040\040\200\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, - {322, "trailer", 0, 7, states_66, - "\000\040\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\020\000\000"}, - {323, "subscriptlist", 0, 3, states_67, - "\000\040\040\002\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, - {324, "subscript", 0, 5, states_68, - "\000\040\040\002\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, - {325, "sliceop", 0, 3, states_69, - "\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {326, "exprlist", 0, 3, states_70, - "\000\040\040\200\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, - {327, "testlist", 0, 3, states_71, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, - {328, "dictorsetmaker", 0, 11, states_72, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, - {329, "classdef", 0, 8, states_73, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004"}, - {330, "arglist", 0, 8, states_74, - "\000\040\040\200\001\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, - {331, "argument", 0, 4, states_75, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, - {332, "comp_iter", 0, 2, states_76, - "\000\000\000\000\000\000\000\000\000\000\000\020\001\000\000\000\000\000\000\000\000"}, - {333, "comp_for", 0, 6, states_77, - "\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000"}, - {334, "comp_if", 0, 4, states_78, - "\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000"}, - {335, "encoding_decl", 0, 2, states_79, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {336, "yield_expr", 0, 3, states_80, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200"}, + {256, "single_input", 0, 3, states_0, + "\004\050\060\200\000\000\000\240\340\223\160\220\045\200\020\000\000\206\120\076\204"}, + {257, "file_input", 0, 2, states_1, + "\204\050\060\200\000\000\000\240\340\223\160\220\045\200\020\000\000\206\120\076\204"}, + {258, "eval_input", 0, 3, states_2, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {259, "decorator", 0, 7, states_3, + "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {260, "decorators", 0, 2, states_4, + "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {261, "decorated", 0, 3, states_5, + "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {262, "funcdef", 0, 8, states_6, + "\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {263, "parameters", 0, 4, states_7, + "\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {264, "typedargslist", 0, 12, states_8, + "\000\000\040\200\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {265, "tfpdef", 0, 4, states_9, + "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {266, "varargslist", 0, 12, states_10, + "\000\000\040\200\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {267, "vfpdef", 0, 2, states_11, + "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {268, "stmt", 0, 2, states_12, + "\000\050\060\200\000\000\000\240\340\223\160\220\045\200\020\000\000\206\120\076\204"}, + {269, "simple_stmt", 0, 4, states_13, + "\000\040\040\200\000\000\000\240\340\223\160\000\000\200\020\000\000\206\120\076\200"}, + {270, "small_stmt", 0, 2, states_14, + "\000\040\040\200\000\000\000\240\340\223\160\000\000\200\020\000\000\206\120\076\200"}, + {271, "expr_stmt", 0, 6, states_15, + "\000\040\040\200\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {272, "testlist_star_expr", 0, 3, states_16, + "\000\040\040\200\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {273, "augassign", 0, 2, states_17, + "\000\000\000\000\000\000\376\037\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {274, "del_stmt", 0, 3, states_18, + "\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {275, "pass_stmt", 0, 2, states_19, + "\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {276, "flow_stmt", 0, 2, states_20, + "\000\000\000\000\000\000\000\000\340\001\000\000\000\000\000\000\000\000\000\000\200"}, + {277, "break_stmt", 0, 2, states_21, + "\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000"}, + {278, "continue_stmt", 0, 2, states_22, + "\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000\000\000\000"}, + {279, "return_stmt", 0, 3, states_23, + "\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000"}, + {280, "yield_stmt", 0, 2, states_24, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200"}, + {281, "raise_stmt", 0, 5, states_25, + "\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000"}, + {282, "import_stmt", 0, 2, states_26, + "\000\000\000\000\000\000\000\000\000\022\000\000\000\000\000\000\000\000\000\000\000"}, + {283, "import_name", 0, 3, states_27, + "\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000"}, + {284, "import_from", 0, 8, states_28, + "\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000"}, + {285, "import_as_name", 0, 4, states_29, + "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {286, "dotted_as_name", 0, 4, states_30, + "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {287, "import_as_names", 0, 3, states_31, + "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {288, "dotted_as_names", 0, 2, states_32, + "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {289, "dotted_name", 0, 2, states_33, + "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {290, "global_stmt", 0, 3, states_34, + "\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000"}, + {291, "nonlocal_stmt", 0, 3, states_35, + "\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000"}, + {292, "assert_stmt", 0, 5, states_36, + "\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000\000"}, + {293, "compound_stmt", 0, 2, states_37, + "\000\010\020\000\000\000\000\000\000\000\000\220\045\000\000\000\000\000\000\000\004"}, + {294, "if_stmt", 0, 8, states_38, + "\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000"}, + {295, "while_stmt", 0, 8, states_39, + "\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000"}, + {296, "for_stmt", 0, 10, states_40, + "\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000"}, + {297, "try_stmt", 0, 13, states_41, + "\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000"}, + {298, "with_stmt", 0, 5, states_42, + "\000\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000"}, + {299, "with_item", 0, 4, states_43, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {300, "except_clause", 0, 5, states_44, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000"}, + {301, "suite", 0, 5, states_45, + "\004\040\040\200\000\000\000\240\340\223\160\000\000\200\020\000\000\206\120\076\200"}, + {302, "test", 0, 6, states_46, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {303, "test_nocond", 0, 2, states_47, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {304, "lambdef", 0, 5, states_48, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000"}, + {305, "lambdef_nocond", 0, 5, states_49, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000"}, + {306, "or_test", 0, 2, states_50, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\020\000\000\206\120\076\000"}, + {307, "and_test", 0, 2, states_51, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\020\000\000\206\120\076\000"}, + {308, "not_test", 0, 3, states_52, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\020\000\000\206\120\076\000"}, + {309, "comparison", 0, 2, states_53, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + {310, "comp_op", 0, 4, states_54, + "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\220\177\000\000\000\000\000"}, + {311, "star_expr", 0, 3, states_55, + "\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {312, "expr", 0, 2, states_56, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + {313, "xor_expr", 0, 2, states_57, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + {314, "and_expr", 0, 2, states_58, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + {315, "shift_expr", 0, 2, states_59, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + {316, "arith_expr", 0, 2, states_60, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + {317, "term", 0, 2, states_61, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + {318, "factor", 0, 3, states_62, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + {319, "power", 0, 4, states_63, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\120\076\000"}, + {320, "atom", 0, 9, states_64, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\120\076\000"}, + {321, "testlist_comp", 0, 5, states_65, + "\000\040\040\200\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {322, "trailer", 0, 7, states_66, + "\000\040\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\020\000\000"}, + {323, "subscriptlist", 0, 3, states_67, + "\000\040\040\002\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {324, "subscript", 0, 5, states_68, + "\000\040\040\002\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {325, "sliceop", 0, 3, states_69, + "\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {326, "exprlist", 0, 3, states_70, + "\000\040\040\200\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + {327, "testlist", 0, 3, states_71, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {328, "dictorsetmaker", 0, 11, states_72, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {329, "classdef", 0, 8, states_73, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004"}, + {330, "arglist", 0, 8, states_74, + "\000\040\040\200\001\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {331, "argument", 0, 4, states_75, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + {332, "comp_iter", 0, 2, states_76, + "\000\000\000\000\000\000\000\000\000\000\000\020\001\000\000\000\000\000\000\000\000"}, + {333, "comp_for", 0, 6, states_77, + "\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000"}, + {334, "comp_if", 0, 4, states_78, + "\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000"}, + {335, "encoding_decl", 0, 2, states_79, + "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {336, "yield_expr", 0, 3, states_80, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200"}, }; static label labels[168] = { - {0, "EMPTY"}, - {256, 0}, - {4, 0}, - {269, 0}, - {293, 0}, - {257, 0}, - {268, 0}, - {0, 0}, - {258, 0}, - {327, 0}, - {259, 0}, - {50, 0}, - {289, 0}, - {7, 0}, - {330, 0}, - {8, 0}, - {260, 0}, - {261, 0}, - {329, 0}, - {262, 0}, - {1, "def"}, - {1, 0}, - {263, 0}, - {51, 0}, - {302, 0}, - {11, 0}, - {301, 0}, - {264, 0}, - {265, 0}, - {22, 0}, - {12, 0}, - {16, 0}, - {36, 0}, - {266, 0}, - {267, 0}, - {270, 0}, - {13, 0}, - {271, 0}, - {274, 0}, - {275, 0}, - {276, 0}, - {282, 0}, - {290, 0}, - {291, 0}, - {292, 0}, - {272, 0}, - {273, 0}, - {336, 0}, - {311, 0}, - {37, 0}, - {38, 0}, - {39, 0}, - {40, 0}, - {41, 0}, - {42, 0}, - {43, 0}, - {44, 0}, - {45, 0}, - {46, 0}, - {47, 0}, - {49, 0}, - {1, "del"}, - {326, 0}, - {1, "pass"}, - {277, 0}, - {278, 0}, - {279, 0}, - {281, 0}, - {280, 0}, - {1, "break"}, - {1, "continue"}, - {1, "return"}, - {1, "raise"}, - {1, "from"}, - {283, 0}, - {284, 0}, - {1, "import"}, - {288, 0}, - {23, 0}, - {52, 0}, - {287, 0}, - {285, 0}, - {1, "as"}, - {286, 0}, - {1, "global"}, - {1, "nonlocal"}, - {1, "assert"}, - {294, 0}, - {295, 0}, - {296, 0}, - {297, 0}, - {298, 0}, - {1, "if"}, - {1, "elif"}, - {1, "else"}, - {1, "while"}, - {1, "for"}, - {1, "in"}, - {1, "try"}, - {300, 0}, - {1, "finally"}, - {1, "with"}, - {299, 0}, - {312, 0}, - {1, "except"}, - {5, 0}, - {6, 0}, - {306, 0}, - {304, 0}, - {303, 0}, - {305, 0}, - {1, "lambda"}, - {307, 0}, - {1, "or"}, - {308, 0}, - {1, "and"}, - {1, "not"}, - {309, 0}, - {310, 0}, - {20, 0}, - {21, 0}, - {28, 0}, - {31, 0}, - {30, 0}, - {29, 0}, - {29, 0}, - {1, "is"}, - {313, 0}, - {18, 0}, - {314, 0}, - {33, 0}, - {315, 0}, - {19, 0}, - {316, 0}, - {34, 0}, - {35, 0}, - {317, 0}, - {14, 0}, - {15, 0}, - {318, 0}, - {17, 0}, - {24, 0}, - {48, 0}, - {32, 0}, - {319, 0}, - {320, 0}, - {322, 0}, - {321, 0}, - {9, 0}, - {10, 0}, - {26, 0}, - {328, 0}, - {27, 0}, - {2, 0}, - {3, 0}, - {1, "None"}, - {1, "True"}, - {1, "False"}, - {333, 0}, - {323, 0}, - {324, 0}, - {325, 0}, - {1, "class"}, - {331, 0}, - {332, 0}, - {334, 0}, - {335, 0}, - {1, "yield"}, + {0, "EMPTY"}, + {256, 0}, + {4, 0}, + {269, 0}, + {293, 0}, + {257, 0}, + {268, 0}, + {0, 0}, + {258, 0}, + {327, 0}, + {259, 0}, + {50, 0}, + {289, 0}, + {7, 0}, + {330, 0}, + {8, 0}, + {260, 0}, + {261, 0}, + {329, 0}, + {262, 0}, + {1, "def"}, + {1, 0}, + {263, 0}, + {51, 0}, + {302, 0}, + {11, 0}, + {301, 0}, + {264, 0}, + {265, 0}, + {22, 0}, + {12, 0}, + {16, 0}, + {36, 0}, + {266, 0}, + {267, 0}, + {270, 0}, + {13, 0}, + {271, 0}, + {274, 0}, + {275, 0}, + {276, 0}, + {282, 0}, + {290, 0}, + {291, 0}, + {292, 0}, + {272, 0}, + {273, 0}, + {336, 0}, + {311, 0}, + {37, 0}, + {38, 0}, + {39, 0}, + {40, 0}, + {41, 0}, + {42, 0}, + {43, 0}, + {44, 0}, + {45, 0}, + {46, 0}, + {47, 0}, + {49, 0}, + {1, "del"}, + {326, 0}, + {1, "pass"}, + {277, 0}, + {278, 0}, + {279, 0}, + {281, 0}, + {280, 0}, + {1, "break"}, + {1, "continue"}, + {1, "return"}, + {1, "raise"}, + {1, "from"}, + {283, 0}, + {284, 0}, + {1, "import"}, + {288, 0}, + {23, 0}, + {52, 0}, + {287, 0}, + {285, 0}, + {1, "as"}, + {286, 0}, + {1, "global"}, + {1, "nonlocal"}, + {1, "assert"}, + {294, 0}, + {295, 0}, + {296, 0}, + {297, 0}, + {298, 0}, + {1, "if"}, + {1, "elif"}, + {1, "else"}, + {1, "while"}, + {1, "for"}, + {1, "in"}, + {1, "try"}, + {300, 0}, + {1, "finally"}, + {1, "with"}, + {299, 0}, + {312, 0}, + {1, "except"}, + {5, 0}, + {6, 0}, + {306, 0}, + {304, 0}, + {303, 0}, + {305, 0}, + {1, "lambda"}, + {307, 0}, + {1, "or"}, + {308, 0}, + {1, "and"}, + {1, "not"}, + {309, 0}, + {310, 0}, + {20, 0}, + {21, 0}, + {28, 0}, + {31, 0}, + {30, 0}, + {29, 0}, + {29, 0}, + {1, "is"}, + {313, 0}, + {18, 0}, + {314, 0}, + {33, 0}, + {315, 0}, + {19, 0}, + {316, 0}, + {34, 0}, + {35, 0}, + {317, 0}, + {14, 0}, + {15, 0}, + {318, 0}, + {17, 0}, + {24, 0}, + {48, 0}, + {32, 0}, + {319, 0}, + {320, 0}, + {322, 0}, + {321, 0}, + {9, 0}, + {10, 0}, + {26, 0}, + {328, 0}, + {27, 0}, + {2, 0}, + {3, 0}, + {1, "None"}, + {1, "True"}, + {1, "False"}, + {333, 0}, + {323, 0}, + {324, 0}, + {325, 0}, + {1, "class"}, + {331, 0}, + {332, 0}, + {334, 0}, + {335, 0}, + {1, "yield"}, }; grammar _PyParser_Grammar = { - 81, - dfas, - {168, labels}, - 256 + 81, + dfas, + {168, labels}, + 256 }; -- cgit v1.2.1 From 737239f6f90fe530a0e75462a3bf6b4679abe49f Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 17 May 2010 08:58:51 +0000 Subject: handle_system_exit() flushs files to warranty the output order PyObject_Print() writes into the C object stderr, whereas PySys_WriteStderr() writes into the Python object sys.stderr. Each object has its own buffer, so call sys.stderr.flush() and fflush(stderr). --- Python/pythonrun.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 4932c4ad4c..d3981961ee 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1367,7 +1367,11 @@ handle_system_exit(void) if (PyLong_Check(value)) exitcode = (int)PyLong_AsLong(value); else { + PyObject *sys_stderr = PySys_GetObject("stderr"); + if (sys_stderr != NULL) + PyObject_CallMethod(sys_stderr, "flush", NULL); PyObject_Print(value, stderr, Py_PRINT_RAW); + fflush(stderr); PySys_WriteStderr("\n"); exitcode = 1; } -- cgit v1.2.1 From f6e4e2c2fa3e76a272ca41f744f0cc4e68b193e7 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 19 May 2010 00:34:15 +0000 Subject: Issue #6697: Check that _PyUnicode_AsString() result is not NULL --- Python/pythonrun.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index d3981961ee..58388c22d9 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -138,8 +138,8 @@ add_flag(int flag, const char *envs) static char* get_codeset(void) { - char* codeset; - PyObject *codec, *name; + char* codeset, *name_str; + PyObject *codec, *name = NULL; codeset = nl_langinfo(CODESET); if (!codeset || codeset[0] == '\0') @@ -154,12 +154,16 @@ get_codeset(void) if (!name) goto error; - codeset = strdup(_PyUnicode_AsString(name)); + name_str = _PyUnicode_AsString(name); + if (name == NULL) + goto error; + codeset = strdup(name_str); Py_DECREF(name); return codeset; error: Py_XDECREF(codec); + Py_XDECREF(name); return NULL; } #endif @@ -1060,22 +1064,34 @@ PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags if (!oenc) return -1; enc = _PyUnicode_AsString(oenc); + if (enc == NULL) + return -1; } v = PySys_GetObject("ps1"); if (v != NULL) { v = PyObject_Str(v); if (v == NULL) PyErr_Clear(); - else if (PyUnicode_Check(v)) + else if (PyUnicode_Check(v)) { ps1 = _PyUnicode_AsString(v); + if (ps1 == NULL) { + PyErr_Clear(); + ps1 = ""; + } + } } w = PySys_GetObject("ps2"); if (w != NULL) { w = PyObject_Str(w); if (w == NULL) PyErr_Clear(); - else if (PyUnicode_Check(w)) + else if (PyUnicode_Check(w)) { ps2 = _PyUnicode_AsString(w); + if (ps2 == NULL) { + PyErr_Clear(); + ps2 = ""; + } + } } arena = PyArena_New(); if (arena == NULL) { -- cgit v1.2.1 From 7cb80215eb0e3492f5227875ae546f981301703d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 19 May 2010 00:54:06 +0000 Subject: Issue #6697: Fix a crash if a keyword contains a surrogate --- Python/getargs.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index 4fa2b5bffb..e8efb3c279 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1755,18 +1755,21 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, "keywords must be strings"); return cleanreturn(0, freelist); } + /* check that _PyUnicode_AsString() result is not NULL */ ks = _PyUnicode_AsString(key); - for (i = 0; i < len; i++) { - if (!strcmp(ks, kwlist[i])) { - match = 1; - break; + if (ks != NULL) { + for (i = 0; i < len; i++) { + if (!strcmp(ks, kwlist[i])) { + match = 1; + break; + } } } if (!match) { PyErr_Format(PyExc_TypeError, - "'%s' is an invalid keyword " + "'%U' is an invalid keyword " "argument for this function", - ks); + key); return cleanreturn(0, freelist); } } -- cgit v1.2.1 From 23aea573c7b3213e2e6f6262784336a2bc3286be Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 19 May 2010 01:06:22 +0000 Subject: Issue #6697: Fix a crash if sys.stdin or sys.stdout encoding contain a surrogate This is *very* unlikely :-) --- Python/bltinmodule.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index a658f9b968..e1f2931dbc 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1610,6 +1610,7 @@ builtin_input(PyObject *self, PyObject *args) char *prompt; char *s; PyObject *stdin_encoding; + char *stdin_encoding_str; PyObject *result; stdin_encoding = PyObject_GetAttrString(fin, "encoding"); @@ -1617,6 +1618,11 @@ builtin_input(PyObject *self, PyObject *args) /* stdin is a text stream, so it must have an encoding. */ return NULL; + stdin_encoding_str = _PyUnicode_AsString(stdin_encoding); + if (stdin_encoding_str == NULL) { + Py_DECREF(stdin_encoding); + return NULL; + } tmp = PyObject_CallMethod(fout, "flush", ""); if (tmp == NULL) PyErr_Clear(); @@ -1625,12 +1631,18 @@ builtin_input(PyObject *self, PyObject *args) if (promptarg != NULL) { PyObject *stringpo; PyObject *stdout_encoding; - stdout_encoding = PyObject_GetAttrString(fout, - "encoding"); + char *stdout_encoding_str; + stdout_encoding = PyObject_GetAttrString(fout, "encoding"); if (stdout_encoding == NULL) { Py_DECREF(stdin_encoding); return NULL; } + stdout_encoding_str = _PyUnicode_AsString(stdout_encoding); + if (stdout_encoding_str == NULL) { + Py_DECREF(stdin_encoding); + Py_DECREF(stdout_encoding); + return NULL; + } stringpo = PyObject_Str(promptarg); if (stringpo == NULL) { Py_DECREF(stdin_encoding); @@ -1638,7 +1650,7 @@ builtin_input(PyObject *self, PyObject *args) return NULL; } po = PyUnicode_AsEncodedString(stringpo, - _PyUnicode_AsString(stdout_encoding), NULL); + stdout_encoding_str, NULL); Py_DECREF(stdout_encoding); Py_DECREF(stringpo); if (po == NULL) { @@ -1676,10 +1688,7 @@ builtin_input(PyObject *self, PyObject *args) result = NULL; } else { - result = PyUnicode_Decode - (s, len-1, - _PyUnicode_AsString(stdin_encoding), - NULL); + result = PyUnicode_Decode(s, len-1, stdin_encoding_str, NULL); } } Py_DECREF(stdin_encoding); -- cgit v1.2.1 From 1d7bed6f68baa1ba111dc0d51b92d4f2bb0fc842 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 19 May 2010 16:53:30 +0000 Subject: Issue #8589: Decode PYTHONWARNINGS environment variable with the file system encoding and surrogateespace error handler instead of the locale encoding to be consistent with os.environ. Add PySys_AddWarnOptionUnicode() function. --- Python/sysmodule.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index ac14751506..ce06d7d3fe 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1048,21 +1048,26 @@ PySys_ResetWarnOptions(void) } void -PySys_AddWarnOption(const wchar_t *s) +PySys_AddWarnOptionUnicode(PyObject *unicode) { - PyObject *str; - if (warnoptions == NULL || !PyList_Check(warnoptions)) { Py_XDECREF(warnoptions); warnoptions = PyList_New(0); if (warnoptions == NULL) return; } - str = PyUnicode_FromWideChar(s, -1); - if (str != NULL) { - PyList_Append(warnoptions, str); - Py_DECREF(str); - } + PyList_Append(warnoptions, unicode); +} + +void +PySys_AddWarnOption(const wchar_t *s) +{ + PyObject *unicode; + unicode = PyUnicode_FromWideChar(s, -1); + if (unicode == NULL) + return; + PySys_AddWarnOptionUnicode(unicode); + Py_DECREF(unicode); } int -- cgit v1.2.1 From c0e3f0787e625295074aee19d585f02b9b5a209a Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 19 May 2010 20:40:50 +0000 Subject: Issue #8766: Initialize _warnings module before importing the first module. Fix a crash if an empty directory called "encodings" exists in sys.path. --- Python/_warnings.c | 2 +- Python/pythonrun.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/_warnings.c b/Python/_warnings.c index c49f3f3223..b1b2b71b8d 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -116,7 +116,7 @@ get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno, _filters = warnings_filters; } - if (!PyList_Check(_filters)) { + if (_filters == NULL || !PyList_Check(_filters)) { PyErr_SetString(PyExc_ValueError, MODULE_NAME ".filters must be a list"); return NULL; diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 58388c22d9..b469c4a625 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -265,13 +265,15 @@ Py_InitializeEx(int install_sigs) _PyImportHooks_Init(); + /* Initialize _warnings. */ + _PyWarnings_Init(); + initfsencoding(); if (install_sigs) initsigs(); /* Signal handling stuff, including initintr() */ /* Initialize warnings. */ - _PyWarnings_Init(); if (PySys_HasWarnOptions()) { PyObject *warnings_module = PyImport_ImportModule("warnings"); if (!warnings_module) -- cgit v1.2.1 From 342ae037401f101f3d063da411041d9878efd5ba Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Fri, 21 May 2010 17:25:34 +0000 Subject: Merged revisions 81398 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r81398 | antoine.pitrou | 2010-05-21 19:12:38 +0200 (ven., 21 mai 2010) | 6 lines Issue #5753: A new C API function, :cfunc:`PySys_SetArgvEx`, allows embedders of the interpreter to set sys.argv without also modifying sys.path. This helps fix `CVE-2008-5983 `_. ........ --- Python/sysmodule.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index ce06d7d3fe..77b120fbe2 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1668,7 +1668,7 @@ _wrealpath(const wchar_t *path, wchar_t *resolved_path) #endif void -PySys_SetArgv(int argc, wchar_t **argv) +PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) { #if defined(HAVE_REALPATH) wchar_t fullpath[MAXPATHLEN]; @@ -1681,7 +1681,7 @@ PySys_SetArgv(int argc, wchar_t **argv) Py_FatalError("no mem for sys.argv"); if (PySys_SetObject("argv", av) != 0) Py_FatalError("can't assign sys.argv"); - if (path != NULL) { + if (updatepath && path != NULL) { wchar_t *argv0 = argv[0]; wchar_t *p = NULL; Py_ssize_t n = 0; @@ -1768,6 +1768,12 @@ PySys_SetArgv(int argc, wchar_t **argv) Py_DECREF(av); } +void +PySys_SetArgv(int argc, wchar_t **argv) +{ + PySys_SetArgvEx(argc, argv, 1); +} + /* Reimplementation of PyFile_WriteString() no calling indirectly PyErr_CheckSignals(): avoid the call to PyObject_Str(). */ -- cgit v1.2.1 From 17b0f141ce9882104863d5a7914759a43843de29 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 21 May 2010 23:45:42 +0000 Subject: Issue #3798: sys.exit(message) writes the message to sys.stderr file, instead of the C file stderr, to use stderr encoding and error handler --- Python/pythonrun.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index b469c4a625..1581c90fb3 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1386,10 +1386,12 @@ handle_system_exit(void) exitcode = (int)PyLong_AsLong(value); else { PyObject *sys_stderr = PySys_GetObject("stderr"); - if (sys_stderr != NULL) - PyObject_CallMethod(sys_stderr, "flush", NULL); - PyObject_Print(value, stderr, Py_PRINT_RAW); - fflush(stderr); + if (sys_stderr != NULL && sys_stderr != Py_None) { + PyFile_WriteObject(value, sys_stderr, Py_PRINT_RAW); + } else { + PyObject_Print(value, stderr, Py_PRINT_RAW); + fflush(stderr); + } PySys_WriteStderr("\n"); exitcode = 1; } -- cgit v1.2.1 From dc57afcc7e7f4450d0ba47b67b6feec201c13a94 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sun, 23 May 2010 13:33:13 +0000 Subject: Issue #8188: Introduce a new scheme for computing hashes of numbers (instances of int, float, complex, decimal.Decimal and fractions.Fraction) that makes it easy to maintain the invariant that hash(x) == hash(y) whenever x and y have equal value. --- Python/sysmodule.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 77b120fbe2..4c87d54c7c 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -570,6 +570,57 @@ sys_setrecursionlimit(PyObject *self, PyObject *args) return Py_None; } +static PyTypeObject Hash_InfoType; + +PyDoc_STRVAR(hash_info_doc, +"hash_info\n\ +\n\ +A struct sequence providing parameters used for computing\n\ +numeric hashes. The attributes are read only."); + +static PyStructSequence_Field hash_info_fields[] = { + {"width", "width of the type used for hashing, in bits"}, + {"modulus", "prime number giving the modulus on which the hash " + "function is based"}, + {"inf", "value to be used for hash of a positive infinity"}, + {"nan", "value to be used for hash of a nan"}, + {"imag", "multiplier used for the imaginary part of a complex number"}, + {NULL, NULL} +}; + +static PyStructSequence_Desc hash_info_desc = { + "sys.hash_info", + hash_info_doc, + hash_info_fields, + 5, +}; + +PyObject * +get_hash_info(void) +{ + PyObject *hash_info; + int field = 0; + hash_info = PyStructSequence_New(&Hash_InfoType); + if (hash_info == NULL) + return NULL; + PyStructSequence_SET_ITEM(hash_info, field++, + PyLong_FromLong(8*sizeof(long))); + PyStructSequence_SET_ITEM(hash_info, field++, + PyLong_FromLong(_PyHASH_MODULUS)); + PyStructSequence_SET_ITEM(hash_info, field++, + PyLong_FromLong(_PyHASH_INF)); + PyStructSequence_SET_ITEM(hash_info, field++, + PyLong_FromLong(_PyHASH_NAN)); + PyStructSequence_SET_ITEM(hash_info, field++, + PyLong_FromLong(_PyHASH_IMAG)); + if (PyErr_Occurred()) { + Py_CLEAR(hash_info); + return NULL; + } + return hash_info; +} + + PyDoc_STRVAR(setrecursionlimit_doc, "setrecursionlimit(n)\n\ \n\ @@ -1482,6 +1533,11 @@ _PySys_Init(void) PyFloat_GetInfo()); SET_SYS_FROM_STRING("int_info", PyLong_GetInfo()); + /* initialize hash_info */ + if (Hash_InfoType.tp_name == 0) + PyStructSequence_InitType(&Hash_InfoType, &hash_info_desc); + SET_SYS_FROM_STRING("hash_info", + get_hash_info()); SET_SYS_FROM_STRING("maxunicode", PyLong_FromLong(PyUnicode_GetMax())); SET_SYS_FROM_STRING("builtin_module_names", -- cgit v1.2.1 From dbf0531ca28d0bd7e848a01172204ba0e93479af Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 28 May 2010 21:55:10 +0000 Subject: Issue #8837: Remove "O?" format of PyArg_Parse*() functions. The format is no used anymore and it was never documented. --- Python/getargs.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index e8efb3c279..ce9f152c9f 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1292,17 +1292,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, 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 *); -- cgit v1.2.1 From a5149be3a59b4b56f6cbf22a65d637867bcb0cc5 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 29 May 2010 00:13:06 +0000 Subject: Remove dead code --- Python/getargs.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index ce9f152c9f..4f7bf7a5d7 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1029,18 +1029,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, else return converterr("string or None", arg, msgbuf, bufsize); - if (*format == '#') { - FETCH_SIZE; - assert(0); /* XXX redundant with if-case */ - if (arg == Py_None) { - STORE_SIZE(0); - } - else { - STORE_SIZE(PyBytes_Size(arg)); - } - format++; - } - else if (*p != NULL && uarg != NULL && + if (*p != NULL && uarg != NULL && (Py_ssize_t) strlen(*p) != PyBytes_GET_SIZE(uarg)) return converterr( "string without null bytes or None", -- cgit v1.2.1 From 7b451e50418084f74c9c9a2ce4928782929df2d5 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 30 May 2010 14:49:32 +0000 Subject: use atomic structures in non-thread version --- Python/ceval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 297b44973b..5af2943960 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -598,7 +598,7 @@ static struct { } pendingcalls[NPENDINGCALLS]; static volatile int pendingfirst = 0; static volatile int pendinglast = 0; -static volatile int pendingcalls_to_do = 0; +static _Py_atomic_int pendingcalls_to_do = {0}; int Py_AddPendingCall(int (*func)(void *), void *arg) -- cgit v1.2.1 From dd156c4f9dd2cb07ac485895245f7c142fd2feb8 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 6 Jun 2010 20:27:51 +0000 Subject: Simplify getbuffer(): convertbuffer() fails anyway if bf_getbuffer is NULL --- Python/getargs.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index 4f7bf7a5d7..1806bf87ae 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1410,7 +1410,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, static Py_ssize_t convertbuffer(PyObject *arg, void **p, char **errmsg) { - PyBufferProcs *pb = arg->ob_type->tp_as_buffer; + PyBufferProcs *pb = Py_TYPE(arg)->tp_as_buffer; Py_ssize_t count; Py_buffer view; @@ -1438,31 +1438,23 @@ convertbuffer(PyObject *arg, void **p, char **errmsg) static int getbuffer(PyObject *arg, Py_buffer *view, char **errmsg) { - void *buf; - Py_ssize_t count; - PyBufferProcs *pb = arg->ob_type->tp_as_buffer; + PyBufferProcs *pb = Py_TYPE(arg)->tp_as_buffer; if (pb == NULL) { *errmsg = "bytes or buffer"; return -1; } - if (pb->bf_getbuffer) { - if (PyObject_GetBuffer(arg, view, 0) < 0) { - *errmsg = "convertible to a buffer"; - return -1; - } - if (!PyBuffer_IsContiguous(view, 'C')) { - *errmsg = "contiguous buffer"; - return -1; - } - return 0; + if (pb->bf_getbuffer == NULL) { + *errmsg = "convertible to a buffer"; + return -1; } - - count = convertbuffer(arg, &buf, errmsg); - if (count < 0) { + if (PyObject_GetBuffer(arg, view, 0) < 0) { *errmsg = "convertible to a buffer"; - return count; + return -1; + } + if (!PyBuffer_IsContiguous(view, 'C')) { + *errmsg = "contiguous buffer"; + return -1; } - PyBuffer_FillInfo(view, NULL, buf, count, 1, 0); return 0; } -- cgit v1.2.1 From a12b7a5e8fa33d4f371cd34651714f027c5ea626 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 6 Jun 2010 20:38:02 +0000 Subject: convertsimple(): call PyErr_NoMemory() on PyMem_NEW() failure Raise a more revelant error (MemoryError instead of TypeError) --- Python/getargs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index 1806bf87ae..b4b5db283c 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1172,6 +1172,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, *buffer = PyMem_NEW(char, size + 1); if (*buffer == NULL) { Py_DECREF(s); + PyErr_NoMemory(); return converterr( "(memory error)", arg, msgbuf, bufsize); @@ -1215,6 +1216,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, *buffer = PyMem_NEW(char, size + 1); if (*buffer == NULL) { Py_DECREF(s); + PyErr_NoMemory(); return converterr("(memory error)", arg, msgbuf, bufsize); } -- cgit v1.2.1 From 046dd2b5f082e1f3975d7cea07826db45c72c259 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 7 Jun 2010 19:57:46 +0000 Subject: Issue #8848: U / U# formats of Py_BuildValue() are just alias to s / s# --- Python/Python-ast.c | 2 +- Python/errors.c | 2 +- Python/modsupport.c | 34 +--------------------------------- Python/sysmodule.c | 2 +- 4 files changed, 4 insertions(+), 36 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 05fa5416de..bedd7d7de7 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -527,7 +527,7 @@ static PyTypeObject* make_type(char *type, PyTypeObject* base, char**fields, int } PyTuple_SET_ITEM(fnames, i, field); } - result = PyObject_CallFunction((PyObject*)&PyType_Type, "U(O){sOss}", + result = PyObject_CallFunction((PyObject*)&PyType_Type, "s(O){sOss}", type, base, "_fields", fnames, "__module__", "_ast"); Py_DECREF(fnames); return (PyTypeObject*)result; diff --git a/Python/errors.c b/Python/errors.c index 37669739c1..4ae661a16f 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -679,7 +679,7 @@ PyErr_NewException(const char *name, PyObject *base, PyObject *dict) goto failure; } /* Create a real new-style class. */ - result = PyObject_CallFunction((PyObject *)&PyType_Type, "UOO", + result = PyObject_CallFunction((PyObject *)&PyType_Type, "sOO", dot+1, bases, dict); failure: Py_XDECREF(bases); diff --git a/Python/modsupport.c b/Python/modsupport.c index a68e10bc41..5f5d842eea 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -302,39 +302,7 @@ do_mkvalue(const char **p_format, va_list *p_va, int flags) 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 = PyUnicode_FromStringAndSize(str, n); - } - return v; - } - - case 'U': + case 'U': /* XXX deprecated alias */ { PyObject *v; char *str = va_arg(*p_va, char *); diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 4c87d54c7c..f1da9730c4 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1510,7 +1510,7 @@ _PySys_Init(void) PyLong_FromLong(PY_VERSION_HEX)); svnversion_init(); SET_SYS_FROM_STRING("subversion", - Py_BuildValue("(UUU)", "CPython", branch, + Py_BuildValue("(sss)", "CPython", branch, svn_revision)); SET_SYS_FROM_STRING("dont_write_bytecode", PyBool_FromLong(Py_DontWriteBytecodeFlag)); -- cgit v1.2.1 From ea1eb94ef3c07f1a17798ab62b20d374266920a7 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 8 Jun 2010 20:46:00 +0000 Subject: sys_pyfile_write() does nothing if file is NULL mywrite() falls back to the C file object if sys_pyfile_write() returns an error. This patch fixes a segfault is Py_FatalError() is called in an early stage of Python initialization. --- Python/sysmodule.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index f1da9730c4..9ec8ab1489 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1839,6 +1839,9 @@ sys_pyfile_write(const char *text, PyObject *file) PyObject *unicode = NULL, *writer = NULL, *args = NULL, *result = NULL; int err; + if (file == NULL) + return -1; + unicode = PyUnicode_FromString(text); if (unicode == NULL) goto error; -- cgit v1.2.1 From bb4e6d2cdb19b9ad4d8439844127032223299b8f Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 8 Jun 2010 21:00:13 +0000 Subject: Py_FatalError(): don't sys sys.last_xxx variables Call PyErr_PrintEx(0) instead of PyErr_Print() to avoid a crash if Py_FatalError() is called in an early stage of Python initialization (if PySys is not yet initialized). --- Python/pythonrun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 1581c90fb3..05a980085d 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -2055,7 +2055,7 @@ Py_FatalError(const char *msg) fprintf(stderr, "Fatal Python error: %s\n", msg); fflush(stderr); /* it helps in Windows debug build */ if (PyErr_Occurred()) { - PyErr_Print(); + PyErr_PrintEx(0); } #ifdef MS_WINDOWS { -- cgit v1.2.1 From b6a0126b4eabe96869ef204f02261402bd02365b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 8 Jun 2010 21:45:51 +0000 Subject: PyArg_Parse*("Z#") raises an error for unknown type instead of ignoring the error and leave the pointer to the string and the size unchanged (not initialized). Fix also the type in the error message of "Z", "Z#" and "Y" formats. --- Python/getargs.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index b4b5db283c..31b9d35716 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1051,6 +1051,8 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, *p = PyUnicode_AS_UNICODE(arg); STORE_SIZE(PyUnicode_GET_SIZE(arg)); } + else + return converterr("str or None", arg, msgbuf, bufsize); format++; } else { Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); @@ -1060,8 +1062,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, else if (PyUnicode_Check(arg)) *p = PyUnicode_AS_UNICODE(arg); else - return converterr("string or None", - arg, msgbuf, bufsize); + return converterr("str or None", arg, msgbuf, bufsize); } break; } @@ -1258,7 +1259,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, if (PyByteArray_Check(arg)) *p = arg; else - return converterr("buffer", arg, msgbuf, bufsize); + return converterr("bytearray", arg, msgbuf, bufsize); break; } -- cgit v1.2.1 From 9d9d2dbc453236f7fa5555d17885e1eabbaf23f6 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 8 Jun 2010 22:54:19 +0000 Subject: Issue #8838, #8339: Remove codecs.charbuffer_encode() and "t#" parsing format Remove last references to the "char buffer" of the buffer protocol from Python3. --- Python/getargs.c | 41 +---------------------------------------- 1 file changed, 1 insertion(+), 40 deletions(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index 31b9d35716..2a26a8f9f3 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -864,7 +864,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, break; } - /* XXX WAAAAH! 's', 'y', 'z', 'u', 'Z', 'e', 'w', 't' codes all + /* XXX WAAAAH! 's', 'y', 'z', 'u', 'Z', 'e', 'w' codes all need to be cleaned up! */ case 's': {/* text string */ @@ -1362,45 +1362,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, break; } - /*TEO: This can be eliminated --- here only for backward - compatibility */ - case 't': { /* 8-bit character buffer, read-only access */ - char **p = va_arg(*p_va, char **); - PyBufferProcs *pb = arg->ob_type->tp_as_buffer; - Py_ssize_t count; - Py_buffer view; - - if (*format++ != '#') - return converterr( - "invalid use of 't' format character", - arg, msgbuf, bufsize); - if (pb == NULL || pb->bf_getbuffer == NULL) - return converterr( - "bytes or read-only character buffer", - arg, msgbuf, bufsize); - - if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) != 0) - return converterr("string or single-segment read-only buffer", - arg, msgbuf, bufsize); - - count = view.len; - *p = view.buf; - if (pb->bf_releasebuffer) - return converterr( - "string or pinned buffer", - arg, msgbuf, bufsize); - - PyBuffer_Release(&view); - - if (count < 0) - return converterr("(unspecified)", arg, msgbuf, bufsize); - { - FETCH_SIZE; - STORE_SIZE(count); - } - break; - } - default: return converterr("impossible", arg, msgbuf, bufsize); -- cgit v1.2.1 From d00354254b00b4ae88c65010b3015b1f7c3fab65 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Thu, 10 Jun 2010 16:05:10 +0000 Subject: Issue #8950: Make PyArg_Parse* with 'L' code raise for float inputs, instead of warning. This makes it consistent with the other integer codes. --- Python/getargs.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index 2a26a8f9f3..127b1473a6 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -582,19 +582,6 @@ converterr(const char *expected, PyObject *arg, char *msgbuf, size_t bufsize) #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_warning(PyObject *arg) -{ - if (PyFloat_Check(arg) && - PyErr_Warn(PyExc_DeprecationWarning, - "integer argument expected, got float" )) - return 1; - else - return 0; -} - /* Explicitly check for float arguments when integers are expected. Return 1 for error, 0 if ok. */ static int @@ -791,14 +778,13 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, case 'L': {/* PY_LONG_LONG */ PY_LONG_LONG *p = va_arg( *p_va, PY_LONG_LONG * ); PY_LONG_LONG ival; - if (float_argument_warning(arg)) + if (float_argument_error(arg)) return converterr("long", arg, msgbuf, bufsize); ival = PyLong_AsLongLong(arg); - if (ival == (PY_LONG_LONG)-1 && PyErr_Occurred() ) { + if (ival == (PY_LONG_LONG)-1 && PyErr_Occurred()) return converterr("long", arg, msgbuf, bufsize); - } else { + else *p = ival; - } break; } -- cgit v1.2.1 From 24e0c93aebd29160d263fb92dfdca097342fcd5f Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 11 Jun 2010 00:36:33 +0000 Subject: Issue #8965: initfsencoding() doesn't change the encoding on Mac OS X File system encoding have to be hardcoded to "utf-8" on Mac OS X. r81190 introduced a regression: the encoding was changed depending on the locale. --- Python/pythonrun.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 05a980085d..5b7cd20251 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -703,24 +703,26 @@ initfsencoding(void) #if defined(HAVE_LANGINFO_H) && defined(CODESET) char *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. */ - codeset = get_codeset(); - if (codeset != NULL) { - Py_FileSystemDefaultEncoding = codeset; - Py_HasFileSystemDefaultEncoding = 0; - return; - } + if (Py_FileSystemDefaultEncoding == NULL) { + /* 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. */ + codeset = get_codeset(); + if (codeset != NULL) { + Py_FileSystemDefaultEncoding = codeset; + Py_HasFileSystemDefaultEncoding = 0; + return; + } - PyErr_Clear(); - fprintf(stderr, - "Unable to get the locale encoding: " - "fallback to utf-8\n"); - Py_FileSystemDefaultEncoding = "utf-8"; - Py_HasFileSystemDefaultEncoding = 1; + PyErr_Clear(); + fprintf(stderr, + "Unable to get the locale encoding: " + "fallback to utf-8\n"); + Py_FileSystemDefaultEncoding = "utf-8"; + Py_HasFileSystemDefaultEncoding = 1; + } #endif /* the encoding is mbcs, utf-8 or ascii */ -- cgit v1.2.1 From d43f4f361ceeee0b799207f1a5531b07dc54380a Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 11 Jun 2010 21:53:07 +0000 Subject: Merged revisions 81906 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r81906 | benjamin.peterson | 2010-06-11 16:40:37 -0500 (Fri, 11 Jun 2010) | 1 line different spellings are just unacceptable ........ --- Python/symtable.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/symtable.c b/Python/symtable.c index 83f02315b6..55c9f472fc 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1533,7 +1533,7 @@ 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 + operation. It is different than a->name when a->name is a dotted package name (e.g. spam.eggs) */ PyObject *store_name; -- cgit v1.2.1 From 9a25f2657511270dacd4bf55964921f620799839 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 13 Jun 2010 18:21:50 +0000 Subject: Issue #8592: PyArg_Parse*() functions raise a TypeError for "y", "u" and "Z" formats if the string contains a null byte/character. Write unit tests for string formats. --- Python/getargs.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index 127b1473a6..d4d8d8417b 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -935,10 +935,15 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, count = convertbuffer(arg, p, &buf); if (count < 0) return converterr(buf, arg, msgbuf, bufsize); - else if (*format == '#') { + if (*format == '#') { FETCH_SIZE; STORE_SIZE(count); format++; + } else { + if (strlen(*p) != count) + return converterr( + "bytes without null bytes", + arg, msgbuf, bufsize); } break; } @@ -1045,9 +1050,13 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, if (arg == Py_None) *p = 0; - else if (PyUnicode_Check(arg)) + else if (PyUnicode_Check(arg)) { *p = PyUnicode_AS_UNICODE(arg); - else + if (Py_UNICODE_strlen(*p) != PyUnicode_GET_SIZE(arg)) + return converterr( + "str without null character or None", + arg, msgbuf, bufsize); + } else return converterr("str or None", arg, msgbuf, bufsize); } break; @@ -1227,6 +1236,11 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, FETCH_SIZE; STORE_SIZE(PyUnicode_GET_SIZE(arg)); format++; + } else { + if (Py_UNICODE_strlen(*p) != PyUnicode_GET_SIZE(arg)) + return converterr( + "str without null character", + arg, msgbuf, bufsize); } break; } -- cgit v1.2.1 From 4364d850379c3b2d3838fb9727d0bc2711a5c1f8 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 13 Jun 2010 20:31:26 +0000 Subject: getargs.c: remove last reference to "t#" format "t#" format was removed from convertitem() (convertsimple) but not skipitem(). --- Python/getargs.c | 1 - 1 file changed, 1 deletion(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index d4d8d8417b..20f4814e8b 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1768,7 +1768,6 @@ skipitem(const char **p_format, va_list *p_va, int flags) case 'z': /* string or None */ case 'y': /* bytes */ case 'u': /* unicode string */ - case 't': /* buffer, read-only */ case 'w': /* buffer, read-write */ { (void) va_arg(*p_va, char **); -- cgit v1.2.1 From af43f50cd72640f3e72f68fa7c789c45cdaac839 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Thu, 17 Jun 2010 12:33:22 +0000 Subject: Issue #9011: Remove buggy and unnecessary ST->AST compilation code dealing with unary minus applied to a constant. The removed code was mutating the ST, causing a second compilation to fail. (The peephole optimizer already takes care of optimizing this case, so there's no lost optimization opportunity here.) --- Python/ast.c | 26 -------------------------- 1 file changed, 26 deletions(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index 0703abc9a7..34dc30f04d 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -1678,34 +1678,8 @@ ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr) 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; -- cgit v1.2.1 From 038a84f24c322e32ca611eabbcec4830fb2b30f1 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Thu, 17 Jun 2010 18:38:20 +0000 Subject: Typo repair. --- Python/import.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index d23eb6a941..df00802d1a 100644 --- a/Python/import.c +++ b/Python/import.c @@ -558,10 +558,10 @@ PyImport_GetMagicTag(void) copy can be retrieved from there by calling _PyImport_FindExtension(). - Modules which do support multiple multiple initialization set - their m_size field to a non-negative number (indicating the size - of the module-specific state). They are still recorded in the - extensions dictionary, to avoid loading shared libraries twice. + Modules which do support multiple initialization set their m_size + field to a non-negative number (indicating the size of the + module-specific state). They are still recorded in the extensions + dictionary, to avoid loading shared libraries twice. */ int -- cgit v1.2.1 From 86ae93c37f42628dac90832d2194e39afa157539 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 17 Jun 2010 23:08:50 +0000 Subject: Issue #6543: Write the traceback in the terminal encoding instead of utf-8. Fix the encoding of the modules filename. Reindent also traceback.h, just because I hate tabs :-) --- Python/_warnings.c | 3 +- Python/compile.c | 2 +- Python/pythonrun.c | 2 +- Python/traceback.c | 105 +++++++++++++++++++++++++++++------------------------ 4 files changed, 61 insertions(+), 51 deletions(-) (limited to 'Python') diff --git a/Python/_warnings.c b/Python/_warnings.c index b1b2b71b8d..55f7fda94f 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -282,8 +282,7 @@ show_warning(PyObject *filename, int lineno, PyObject *text, PyObject PyFile_WriteString("\n", f_stderr); } else - if (_Py_DisplaySourceLine(f_stderr, _PyUnicode_AsString(filename), - lineno, 2) < 0) + if (_Py_DisplaySourceLine(f_stderr, filename, lineno, 2) < 0) return; PyErr_Clear(); } diff --git a/Python/compile.c b/Python/compile.c index fa7dcef5fb..c9f6e8d701 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3942,7 +3942,7 @@ makecode(struct compiler *c, struct assembler *a) freevars = dict_keys_inorder(c->u->u_freevars, PyTuple_Size(cellvars)); if (!freevars) goto error; - filename = PyUnicode_DecodeFSDefault(c->c_filename); + filename = PyUnicode_FromString(c->c_filename); if (!filename) goto error; diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 5b7cd20251..f45d7dc9fa 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1190,7 +1190,7 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, d = PyModule_GetDict(m); if (PyDict_GetItemString(d, "__file__") == NULL) { PyObject *f; - f = PyUnicode_DecodeFSDefault(filename); + f = PyUnicode_FromString(filename); if (f == NULL) return -1; if (PyDict_SetItemString(d, "__file__", f) < 0) { diff --git a/Python/traceback.c b/Python/traceback.c index 51a92269aa..9c9c357c39 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -133,33 +133,38 @@ PyTraceBack_Here(PyFrameObject *frame) return 0; } -static int -_Py_FindSourceFile(const char* filename, char* namebuf, size_t namelen, int open_flags) +static PyObject * +_Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject *io) { - int i; - int fd = -1; + Py_ssize_t i; + PyObject *binary; PyObject *v; - Py_ssize_t _npath; - int npath; + Py_ssize_t npath; size_t taillen; PyObject *syspath; const char* path; const char* tail; + const char* filepath; Py_ssize_t len; + filepath = _PyUnicode_AsString(filename); + if (filepath == NULL) { + PyErr_Clear(); + return NULL; + } + /* Search tail of filename in sys.path before giving up */ - tail = strrchr(filename, SEP); + tail = strrchr(filepath, SEP); if (tail == NULL) - tail = filename; + tail = filepath; else tail++; taillen = strlen(tail); syspath = PySys_GetObject("path"); if (syspath == NULL || !PyList_Check(syspath)) - return -1; - _npath = PyList_Size(syspath); - npath = Py_SAFE_DOWNCAST(_npath, Py_ssize_t, int); + return NULL; + npath = PyList_Size(syspath); for (i = 0; i < npath; i++) { v = PyList_GetItem(syspath, i); @@ -170,6 +175,10 @@ _Py_FindSourceFile(const char* filename, char* namebuf, size_t namelen, int open if (!PyUnicode_Check(v)) continue; path = _PyUnicode_AsStringAndSize(v, &len); + if (path == NULL) { + PyErr_Clear(); + continue; + } if (len + 1 + (Py_ssize_t)taillen >= (Py_ssize_t)namelen - 1) continue; /* Too long */ strcpy(namebuf, path); @@ -178,31 +187,27 @@ _Py_FindSourceFile(const char* filename, char* namebuf, size_t namelen, int open if (len > 0 && namebuf[len-1] != SEP) namebuf[len++] = SEP; strcpy(namebuf+len, tail); - Py_BEGIN_ALLOW_THREADS - fd = open(namebuf, open_flags); - Py_END_ALLOW_THREADS - if (0 <= fd) { - return fd; - } + + binary = PyObject_CallMethod(io, "open", "ss", namebuf, "rb"); + if (binary != NULL) + return binary; + PyErr_Clear(); } - return -1; + return NULL; } int -_Py_DisplaySourceLine(PyObject *f, const char *filename, int lineno, int indent) +_Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent) { int err = 0; int fd; int i; char *found_encoding; char *encoding; + PyObject *io; + PyObject *binary; PyObject *fob = NULL; PyObject *lineobj = NULL; -#ifdef O_BINARY - const int open_flags = O_RDONLY | O_BINARY; /* necessary for Windows */ -#else - const int open_flags = O_RDONLY; -#endif char buf[MAXPATHLEN+1]; Py_UNICODE *u, *p; Py_ssize_t len; @@ -210,27 +215,32 @@ _Py_DisplaySourceLine(PyObject *f, const char *filename, int lineno, int indent) /* open the file */ if (filename == NULL) return 0; - Py_BEGIN_ALLOW_THREADS - fd = open(filename, open_flags); - Py_END_ALLOW_THREADS - if (fd < 0) { - fd = _Py_FindSourceFile(filename, buf, sizeof(buf), open_flags); - if (fd < 0) + + io = PyImport_ImportModuleNoBlock("io"); + if (io == NULL) + return -1; + binary = PyObject_CallMethod(io, "open", "Os", filename, "rb"); + + if (binary == NULL) { + binary = _Py_FindSourceFile(filename, buf, sizeof(buf), io); + if (binary == NULL) { + Py_DECREF(io); return 0; - filename = buf; + } } /* use the right encoding to decode the file as unicode */ + fd = PyObject_AsFileDescriptor(binary); found_encoding = PyTokenizer_FindEncoding(fd); - encoding = (found_encoding != NULL) ? found_encoding : - (char*)PyUnicode_GetDefaultEncoding(); + encoding = (found_encoding != NULL) ? found_encoding : "utf-8"; lseek(fd, 0, 0); /* Reset position */ - fob = PyFile_FromFd(fd, (char*)filename, "r", -1, (char*)encoding, - NULL, NULL, 1); + fob = PyObject_CallMethod(io, "TextIOWrapper", "Os", binary, encoding); + Py_DECREF(io); + Py_DECREF(binary); PyMem_FREE(found_encoding); + if (fob == NULL) { PyErr_Clear(); - close(fd); return 0; } @@ -287,17 +297,19 @@ _Py_DisplaySourceLine(PyObject *f, const char *filename, int lineno, int indent) } static int -tb_displayline(PyObject *f, const char *filename, int lineno, const char *name) +tb_displayline(PyObject *f, PyObject *filename, int lineno, PyObject *name) { - int err = 0; - char linebuf[2000]; + int err; + PyObject *line; if (filename == NULL || name == NULL) return -1; - /* This is needed by Emacs' compile command */ -#define FMT " File \"%.500s\", line %d, in %.500s\n" - PyOS_snprintf(linebuf, sizeof(linebuf), FMT, filename, lineno, name); - err = PyFile_WriteString(linebuf, f); + line = PyUnicode_FromFormat(" File \"%U\", line %d, in %U\n", + filename, lineno, name); + if (line == NULL) + return -1; + err = PyFile_WriteObject(line, f, Py_PRINT_RAW); + Py_DECREF(line); if (err != 0) return err; return _Py_DisplaySourceLine(f, filename, lineno, 4); @@ -316,10 +328,9 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit) while (tb != NULL && err == 0) { if (depth <= limit) { err = tb_displayline(f, - _PyUnicode_AsString( - tb->tb_frame->f_code->co_filename), - tb->tb_lineno, - _PyUnicode_AsString(tb->tb_frame->f_code->co_name)); + tb->tb_frame->f_code->co_filename, + tb->tb_lineno, + tb->tb_frame->f_code->co_name); } depth--; tb = tb->tb_next; -- cgit v1.2.1 From 9d5759dfe84bb0a234a76e5b0a9e8440f3a56f24 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Tue, 22 Jun 2010 21:49:39 +0000 Subject: Merged revisions 82169 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r82169 | antoine.pitrou | 2010-06-22 23:42:05 +0200 (mar., 22 juin 2010) | 4 lines Fix misindents in compile.c (for Benjamin). Of course, whoever used the wrong indentation rules needs to be spanked. ........ --- Python/compile.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'Python') diff --git a/Python/compile.c b/Python/compile.c index c9f6e8d701..aae0339c2c 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -968,7 +968,7 @@ compiler_addop_o(struct compiler *c, int opcode, PyObject *dict, { int arg = compiler_add_o(c, dict, o); if (arg < 0) - return 0; + return 0; return compiler_addop_i(c, opcode, arg); } @@ -979,11 +979,11 @@ compiler_addop_name(struct compiler *c, int opcode, PyObject *dict, int arg; PyObject *mangled = _Py_Mangle(c->u->u_private, o); if (!mangled) - return 0; + return 0; arg = compiler_add_o(c, dict, mangled); Py_DECREF(mangled); if (arg < 0) - return 0; + return 0; return compiler_addop_i(c, opcode, arg); } @@ -1134,7 +1134,7 @@ static int compiler_isdocstring(stmt_ty s) { if (s->kind != Expr_kind) - return 0; + return 0; return s->v.Expr.value->kind == Str_kind; } @@ -1240,11 +1240,11 @@ compiler_lookup_arg(PyObject *dict, PyObject *name) PyObject *k, *v; k = PyTuple_Pack(2, name, name->ob_type); if (k == NULL) - return -1; + return -1; v = PyDict_GetItem(dict, k); Py_DECREF(k); if (v == NULL) - return -1; + return -1; return PyLong_AS_LONG(v); } @@ -3073,7 +3073,7 @@ compiler_with(struct compiler *c, stmt_ty s) block = compiler_new_block(c); finally = compiler_new_block(c); if (!block || !finally) - return 0; + return 0; /* Evaluate EXPR */ VISIT(c, expr, s->v.With.context_expr); @@ -3082,15 +3082,15 @@ compiler_with(struct compiler *c, stmt_ty s) /* SETUP_WITH pushes a finally block. */ compiler_use_next_block(c, block); if (!compiler_push_fblock(c, FINALLY_TRY, block)) { - return 0; + return 0; } if (s->v.With.optional_vars) { - VISIT(c, expr, s->v.With.optional_vars); + VISIT(c, expr, s->v.With.optional_vars); } else { /* Discard result from context.__enter__() */ - ADDOP(c, POP_TOP); + ADDOP(c, POP_TOP); } /* BLOCK code */ @@ -3103,7 +3103,7 @@ compiler_with(struct compiler *c, stmt_ty s) ADDOP_O(c, LOAD_CONST, Py_None, consts); compiler_use_next_block(c, finally); if (!compiler_push_fblock(c, FINALLY_END, finally)) - return 0; + return 0; /* Finally block starts; context.__exit__ is on the stack under the exception or return information. Just issue our magic -- cgit v1.2.1 From 1a72a4bdbc72c24c2fc9cc726186c2b6c543e409 Mon Sep 17 00:00:00 2001 From: Stefan Krah Date: Wed, 23 Jun 2010 18:42:39 +0000 Subject: Issue #8930: Remaining indentation fixes after the Grand Unified Indenting. --- Python/ceval.c | 84 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 42 insertions(+), 42 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 5af2943960..2055acf26c 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -87,7 +87,7 @@ void dump_tsc(int opcode, int ticked, uint64 inst0, uint64 inst1, inst = inst1 - inst0 - intr; loop = loop1 - loop0 - intr; fprintf(stderr, "opcode=%03d t=%d inst=%06lld loop=%06lld\n", - opcode, ticked, inst, loop); + opcode, ticked, inst, loop); } #endif @@ -126,10 +126,10 @@ static int prtrace(PyObject *, char *); static int call_trace(Py_tracefunc, PyObject *, PyFrameObject *, int, PyObject *); static int call_trace_protected(Py_tracefunc, PyObject *, - PyFrameObject *, int, 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 *); + PyFrameObject *, int *, int *, int *); static PyObject * cmp_outcome(int, PyObject *, PyObject *); static PyObject * import_from(PyObject *, PyObject *); @@ -718,14 +718,14 @@ _Py_CheckRecursiveCall(char *where) /* 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 */ - WHY_SILENCED = 0x0080 /* Exception silenced by 'with' */ + 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 */ + WHY_SILENCED = 0x0080 /* Exception silenced by 'with' */ }; static enum why_code do_raise(PyObject *, PyObject *); @@ -1005,38 +1005,38 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) /* 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 PEEK(n) (stack_pointer[-(n)]) -#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 SET_VALUE(n, v) (stack_pointer[-(n)] = (v)) -#define BASIC_STACKADJ(n) (stack_pointer += n) -#define BASIC_PUSH(v) (*stack_pointer++ = (v)) -#define BASIC_POP() (*--stack_pointer) +#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 PEEK(n) (stack_pointer[-(n)]) +#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 SET_VALUE(n, v) (stack_pointer[-(n)] = (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); } + lltrace && prtrace(TOP(), "push")); \ + assert(STACK_LEVEL() <= co->co_stacksize); } #define POP() ((void)(lltrace && prtrace(TOP(), "pop")), \ - BASIC_POP()) + BASIC_POP()) #define STACKADJ(n) { (void)(BASIC_STACKADJ(n), \ - lltrace && prtrace(TOP(), "stackadj")); \ - assert(STACK_LEVEL() <= co->co_stacksize); } + lltrace && prtrace(TOP(), "stackadj")); \ + assert(STACK_LEVEL() <= co->co_stacksize); } #define EXT_POP(STACK_POINTER) ((void)(lltrace && \ - prtrace((STACK_POINTER)[-1], "ext_pop")), \ - *--(STACK_POINTER)) + prtrace((STACK_POINTER)[-1], "ext_pop")), \ + *--(STACK_POINTER)) #else -#define PUSH(v) BASIC_PUSH(v) -#define POP() BASIC_POP() -#define STACKADJ(n) BASIC_STACKADJ(n) +#define PUSH(v) BASIC_PUSH(v) +#define POP() BASIC_POP() +#define STACKADJ(n) BASIC_STACKADJ(n) #define EXT_POP(STACK_POINTER) (*--(STACK_POINTER)) #endif @@ -1051,8 +1051,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) 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) + GETLOCAL(i) = value; \ + Py_XDECREF(tmp); } while (0) #define UNWIND_BLOCK(b) \ @@ -1318,7 +1318,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) it doesn't have to be remembered across a full loop */ if (HAS_ARG(opcode)) oparg = NEXTARG(); - dispatch_opcode: + dispatch_opcode: #ifdef DYNAMIC_EXECUTION_PROFILE #ifdef DXPAIRS dxpairs[lastopcode][opcode]++; @@ -2174,8 +2174,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) break; if (oparg < PyTuple_GET_SIZE(co->co_cellvars)) { v = PyTuple_GET_ITEM(co->co_cellvars, - oparg); - format_exc_check_arg( + oparg); + format_exc_check_arg( PyExc_UnboundLocalError, UNBOUNDLOCAL_ERROR_MSG, v); @@ -2695,7 +2695,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) func = *pfunc; if (PyMethod_Check(func) - && PyMethod_GET_SELF(func) != NULL) { + && PyMethod_GET_SELF(func) != NULL) { PyObject *self = PyMethod_GET_SELF(func); Py_INCREF(self); func = PyMethod_GET_FUNCTION(func); -- cgit v1.2.1 From dfca49ec2ca05151f8f1bf09be0f126f8338e526 Mon Sep 17 00:00:00 2001 From: Alexander Belopolsky Date: Wed, 23 Jun 2010 21:40:15 +0000 Subject: Issue #9051: Instances of timezone class can now be pickled. --- Python/Python-ast.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index bedd7d7de7..54c4e0160d 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -2,7 +2,7 @@ /* - __version__ 73626. + __version__ 82163. This module must be committed separately after each AST grammar change; The __version__ number is set to the revision number of the commit @@ -6773,7 +6773,7 @@ PyInit__ast(void) NULL; if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0) return NULL; - if (PyModule_AddStringConstant(m, "__version__", "73626") < 0) + if (PyModule_AddStringConstant(m, "__version__", "82163") < 0) return NULL; if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return NULL; -- cgit v1.2.1 From d03298c85a782dc64e7204b110f9b5600dd4a3bd Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 24 Jun 2010 22:08:25 +0000 Subject: Issue #8949: "z" format of PyArg_Parse*() functions doesn't accept bytes objects, as described in the documentation. --- Python/getargs.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index 20f4814e8b..bce99ae798 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1005,11 +1005,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, if (arg == Py_None) *p = 0; - else if (PyBytes_Check(arg)) { - /* Enable null byte check below */ - uarg = arg; - *p = PyBytes_AS_STRING(arg); - } else if (PyUnicode_Check(arg)) { uarg = UNICODE_DEFAULT_ENCODING(arg); if (uarg == NULL) -- cgit v1.2.1 From ee0db16e8ebe529fdb25f6e8171d484ae7ba1715 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 24 Jun 2010 22:31:12 +0000 Subject: PyArg_Parse*() functions: factorize code for s/z and u/Z formats --- Python/getargs.c | 121 ++++++++++++------------------------------------------- 1 file changed, 25 insertions(+), 96 deletions(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index bce99ae798..ab95e1e547 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -853,70 +853,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, /* XXX WAAAAH! 's', 'y', 'z', 'u', 'Z', 'e', 'w' codes all need to be cleaned up! */ - case 's': {/* text string */ - if (*format == '*') { - Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *); - - if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - PyBuffer_FillInfo(p, arg, - PyBytes_AS_STRING(uarg), PyBytes_GET_SIZE(uarg), - 1, 0); - } - else { /* any buffer-like object */ - char *buf; - if (getbuffer(arg, p, &buf) < 0) - return converterr(buf, arg, msgbuf, bufsize); - } - if (addcleanup(p, freelist, cleanup_buffer)) { - return converterr( - "(cleanup problem)", - arg, msgbuf, bufsize); - } - format++; - } else if (*format == '#') { - void **p = (void **)va_arg(*p_va, char **); - FETCH_SIZE; - - if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - *p = PyBytes_AS_STRING(uarg); - STORE_SIZE(PyBytes_GET_SIZE(uarg)); - } - else { /* any buffer-like object */ - /* XXX Really? */ - 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 (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - *p = PyBytes_AS_STRING(uarg); - } - else - return converterr("string", arg, msgbuf, bufsize); - if ((Py_ssize_t) strlen(*p) != PyBytes_GET_SIZE(uarg)) - return converterr("string without null bytes", - arg, msgbuf, bufsize); - } - break; - } - case 'y': {/* any buffer-like object, but not PyUnicode */ void **p = (void **)va_arg(*p_va, char **); char *buf; @@ -948,11 +884,14 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, break; } - case 'z': {/* like 's' or 's#', but None is okay, stored as NULL */ + case 's': /* text string */ + case 'z': /* text string or None */ + { if (*format == '*') { + /* "s*" or "z*" */ Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *); - if (arg == Py_None) + if (c == 'z' && arg == Py_None) PyBuffer_FillInfo(p, NULL, NULL, 0, 1, 0); else if (PyUnicode_Check(arg)) { uarg = UNICODE_DEFAULT_ENCODING(arg); @@ -975,11 +914,12 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, } format++; } else if (*format == '#') { /* any buffer-like object */ + /* "s#" or "z#" */ void **p = (void **)va_arg(*p_va, char **); FETCH_SIZE; - if (arg == Py_None) { - *p = 0; + if (c == 'z' && arg == Py_None) { + *p = NULL; STORE_SIZE(0); } else if (PyUnicode_Check(arg)) { @@ -1000,11 +940,12 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, } format++; } else { + /* "s" or "z" */ char **p = va_arg(*p_va, char **); uarg = NULL; - if (arg == Py_None) - *p = 0; + if (c == 'z' && arg == Py_None) + *p = NULL; else if (PyUnicode_Check(arg)) { uarg = UNICODE_DEFAULT_ENCODING(arg); if (uarg == NULL) @@ -1013,24 +954,28 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, *p = PyBytes_AS_STRING(uarg); } else - return converterr("string or None", + return converterr(c == 'z' ? "str or None" : "str", arg, msgbuf, bufsize); if (*p != NULL && uarg != NULL && (Py_ssize_t) strlen(*p) != PyBytes_GET_SIZE(uarg)) return converterr( - "string without null bytes or None", + c == 'z' ? "str without null bytes or None" + : "str without null bytes", arg, msgbuf, bufsize); } break; } - case 'Z': {/* unicode, may be NULL (None) */ + case 'u': /* raw unicode buffer (Py_UNICODE *) */ + case 'Z': /* raw unicode buffer or None */ + { if (*format == '#') { /* any buffer-like object */ + /* "s#" or "Z#" */ Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); FETCH_SIZE; - if (arg == Py_None) { - *p = 0; + if (c == 'Z' && arg == Py_None) { + *p = NULL; STORE_SIZE(0); } else if (PyUnicode_Check(arg)) { @@ -1041,10 +986,11 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, return converterr("str or None", arg, msgbuf, bufsize); format++; } else { + /* "s" or "Z" */ Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); - if (arg == Py_None) - *p = 0; + if (c == 'Z' && arg == Py_None) + *p = NULL; else if (PyUnicode_Check(arg)) { *p = PyUnicode_AS_UNICODE(arg); if (Py_UNICODE_strlen(*p) != PyUnicode_GET_SIZE(arg)) @@ -1052,7 +998,8 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, "str without null character or None", arg, msgbuf, bufsize); } else - return converterr("str or None", arg, msgbuf, bufsize); + return converterr(c == 'Z' ? "str or None" : "str", + arg, msgbuf, bufsize); } break; } @@ -1222,24 +1169,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, break; } - case 'u': {/* raw unicode buffer (Py_UNICODE *) */ - Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); - if (!PyUnicode_Check(arg)) - return converterr("str", arg, msgbuf, bufsize); - *p = PyUnicode_AS_UNICODE(arg); - if (*format == '#') { /* store pointer and size */ - FETCH_SIZE; - STORE_SIZE(PyUnicode_GET_SIZE(arg)); - format++; - } else { - if (Py_UNICODE_strlen(*p) != PyUnicode_GET_SIZE(arg)) - return converterr( - "str without null character", - arg, msgbuf, bufsize); - } - break; - } - case 'S': { /* PyBytes object */ PyObject **p = va_arg(*p_va, PyObject **); if (PyBytes_Check(arg)) -- cgit v1.2.1 From 547ff8c05e9b5e68709dcba8eeb86794753eb68b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 24 Jun 2010 22:57:10 +0000 Subject: getbuffer(): release the buffer on error (if the buffer is not contiguous) --- Python/getargs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index ab95e1e547..41b4af56cf 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1340,6 +1340,7 @@ getbuffer(PyObject *arg, Py_buffer *view, char **errmsg) return -1; } if (!PyBuffer_IsContiguous(view, 'C')) { + PyBuffer_Release(view); *errmsg = "contiguous buffer"; return -1; } -- cgit v1.2.1 From be9c850f53cefba77db579038f9093c9869a5d43 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 25 Jun 2010 00:02:38 +0000 Subject: Issue #8850: Remove "w" and "w#" formats from PyArg_Parse*() functions, use "w*" format instead. Add tests for "w*" format. --- Python/getargs.c | 64 +++++++++++++++----------------------------------------- 1 file changed, 17 insertions(+), 47 deletions(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index 41b4af56cf..7b929481d2 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1231,58 +1231,28 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, } - case 'w': { /* memory buffer, read-write access */ + case 'w': { /* "w*": memory buffer, read-write access */ void **p = va_arg(*p_va, void **); - PyBufferProcs *pb = arg->ob_type->tp_as_buffer; - Py_ssize_t count; - int temp=-1; - Py_buffer view; - - if (pb && pb->bf_releasebuffer && *format != '*') - /* Buffer must be released, yet caller does not use - the Py_buffer protocol. */ - return converterr("pinned buffer", arg, msgbuf, bufsize); + if (*format != '*') + return converterr( + "invalid use of 'w' format character", + arg, msgbuf, bufsize); + format++; - if (pb && pb->bf_getbuffer && *format == '*') { - /* Caller is interested in Py_buffer, and the object - supports it directly. */ - format++; - if (PyObject_GetBuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) { - PyErr_Clear(); - return converterr("read-write buffer", arg, msgbuf, bufsize); - } - if (addcleanup(p, freelist, cleanup_buffer)) { - return converterr( - "(cleanup problem)", - arg, msgbuf, bufsize); - } - if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) - return converterr("contiguous buffer", arg, msgbuf, bufsize); - break; - } - - /* Here we have processed w*, only w and w# remain. */ - if (pb == NULL || - pb->bf_getbuffer == NULL || - ((temp = PyObject_GetBuffer(arg, &view, - PyBUF_SIMPLE)) != 0) || - view.readonly == 1) { - if (temp==0) { - PyBuffer_Release(&view); - } - return converterr("single-segment read-write buffer", - arg, msgbuf, bufsize); + /* Caller is interested in Py_buffer, and the object + supports it directly. */ + if (PyObject_GetBuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) { + PyErr_Clear(); + return converterr("read-write buffer", arg, msgbuf, bufsize); } - - if ((count = view.len) < 0) - return converterr("(unspecified)", arg, msgbuf, bufsize); - *p = view.buf; - if (*format == '#') { - FETCH_SIZE; - STORE_SIZE(count); - format++; + if (addcleanup(p, freelist, cleanup_buffer)) { + return converterr( + "(cleanup problem)", + arg, msgbuf, bufsize); } + if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) + return converterr("contiguous buffer", arg, msgbuf, bufsize); break; } -- cgit v1.2.1 From 142b3f5685806ec7e1a0ebba13eacd7762616078 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 25 Jun 2010 19:30:21 +0000 Subject: only take into account positional arguments count in related error messages --- Python/ceval.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 2055acf26c..6e4911ae92 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3100,11 +3100,11 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, if (!(co->co_flags & CO_VARARGS)) { PyErr_Format(PyExc_TypeError, "%U() takes %s %d " - "argument%s (%d given)", + "positional argument%s (%d given)", co->co_name, defcount ? "at most" : "exactly", - total_args, - total_args == 1 ? "" : "s", + co->co_argcount, + co->co_argcount == 1 ? "" : "s", argcount + kwcount); goto fail; } -- cgit v1.2.1 From 61922f057eff2bf4e6d5e3b56645fa85b28f0fc5 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 27 Jun 2010 21:45:24 +0000 Subject: Merged revisions 81465-81466,81468,81679,81735,81760,81868,82183 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r81465 | georg.brandl | 2010-05-22 06:29:19 -0500 (Sat, 22 May 2010) | 2 lines Issue #3924: Ignore cookies with invalid "version" field in cookielib. ........ r81466 | georg.brandl | 2010-05-22 06:31:16 -0500 (Sat, 22 May 2010) | 1 line Underscore the name of an internal utility function. ........ r81468 | georg.brandl | 2010-05-22 06:43:25 -0500 (Sat, 22 May 2010) | 1 line #8635: document enumerate() start parameter in docstring. ........ r81679 | benjamin.peterson | 2010-06-03 16:21:03 -0500 (Thu, 03 Jun 2010) | 1 line use a set for membership testing ........ r81735 | michael.foord | 2010-06-05 06:46:59 -0500 (Sat, 05 Jun 2010) | 1 line Extract error message truncating into a method (unittest.TestCase._truncateMessage). ........ r81760 | michael.foord | 2010-06-05 14:38:42 -0500 (Sat, 05 Jun 2010) | 1 line Issue 8302. SkipTest exception is setUpClass or setUpModule is now reported as a skip rather than an error. ........ r81868 | benjamin.peterson | 2010-06-09 14:45:04 -0500 (Wed, 09 Jun 2010) | 1 line fix code formatting ........ r82183 | benjamin.peterson | 2010-06-23 15:29:26 -0500 (Wed, 23 Jun 2010) | 1 line cpython only gc tests ........ --- Python/Python-ast.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 54c4e0160d..c37dda7f00 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -537,8 +537,9 @@ static int add_attributes(PyTypeObject* type, char**attrs, int num_fields) { int i, result; PyObject *s, *l = PyTuple_New(num_fields); - if (!l) return 0; - for(i = 0; i < num_fields; i++) { + if (!l) + return 0; + for (i = 0; i < num_fields; i++) { s = PyUnicode_FromString(attrs[i]); if (!s) { Py_DECREF(l); -- cgit v1.2.1 From 81db4d0e78c8b06bcaedec3cd00d4014c0b9a339 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 27 Jun 2010 22:37:28 +0000 Subject: Merged revisions 81380 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r81380 | brett.cannon | 2010-05-20 13:37:55 -0500 (Thu, 20 May 2010) | 8 lines Turned out that if you used explicit relative import syntax (e.g. from .os import sep) and it failed, import would still try the implicit relative import semantics of an absolute import (from os import sep). That's not right, so when level is negative, only do explicit relative import semantics. Fixes issue #7902. Thanks to Meador Inge for the patch. ........ --- Python/import.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index df00802d1a..194e360562 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2385,7 +2385,8 @@ import_module_level(char *name, PyObject *globals, PyObject *locals, if (parent == NULL) return NULL; - head = load_next(parent, Py_None, &name, buf, &buflen); + head = load_next(parent, level < 0 ? Py_None : parent, &name, buf, + &buflen); if (head == NULL) return NULL; -- cgit v1.2.1 From 60647ee9a19696c2740f340867eeac9fa9816754 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 28 Jun 2010 00:01:59 +0000 Subject: Merged revisions 77402,77505,77510 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77402 | brett.cannon | 2010-01-09 20:56:19 -0600 (Sat, 09 Jan 2010) | 12 lines DeprecationWarning is now silent by default. This was originally suggested by Guido, discussed on the stdlib-sig mailing list, and given the OK by Guido directly to me. What this change essentially means is that Python has taken a policy of silencing warnings that are only of interest to developers by default. This should prevent users from seeing warnings which are triggered by an application being run against a new interpreter before the app developer has a chance to update their code. Closes issue #7319. Thanks to Antoine Pitrou, Ezio Melotti, and Brian Curtin for helping with the issue. ........ r77505 | brett.cannon | 2010-01-14 14:00:28 -0600 (Thu, 14 Jan 2010) | 7 lines The silencing of DeprecationWarning was not taking -3 into consideration. Since Py3K warnings are DeprecationWarning by default this was causing -3 to essentially be a no-op. Now DeprecationWarning is only silenced if -3 is not used. Closes issue #7700. Thanks Ezio Melotti and Florent Xicluna for patch help. ........ r77510 | brett.cannon | 2010-01-14 19:31:45 -0600 (Thu, 14 Jan 2010) | 1 line Remove C++/C99-style comments. ........ --- Python/_warnings.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'Python') diff --git a/Python/_warnings.c b/Python/_warnings.c index 55f7fda94f..dd7bb57965 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -251,7 +251,7 @@ show_warning(PyObject *filename, int lineno, PyObject *text, PyObject name = PyObject_GetAttrString(category, "__name__"); if (name == NULL) /* XXX Can an object lack a '__name__' attribute? */ - return; + return; f_stderr = PySys_GetObject("stderr"); if (f_stderr == NULL) { @@ -846,28 +846,35 @@ create_filter(PyObject *category, const char *action) static PyObject * init_filters(void) { - PyObject *filters = PyList_New(3); + /* Don't silence DeprecationWarning if -3 was used. */ + PyObject *filters = PyList_New(4); + unsigned int pos = 0; /* Post-incremented in each use. */ + unsigned int x; const char *bytes_action; + if (filters == NULL) return NULL; - PyList_SET_ITEM(filters, 0, + PyList_SET_ITEM(filters, pos++, + create_filter(PyExc_DeprecationWarning, "ignore")); + PyList_SET_ITEM(filters, pos++, create_filter(PyExc_PendingDeprecationWarning, "ignore")); - PyList_SET_ITEM(filters, 1, create_filter(PyExc_ImportWarning, "ignore")); + PyList_SET_ITEM(filters, pos++, + create_filter(PyExc_ImportWarning, "ignore")); if (Py_BytesWarningFlag > 1) bytes_action = "error"; else if (Py_BytesWarningFlag) bytes_action = "default"; else bytes_action = "ignore"; - PyList_SET_ITEM(filters, 2, create_filter(PyExc_BytesWarning, + PyList_SET_ITEM(filters, pos++, create_filter(PyExc_BytesWarning, bytes_action)); - if (PyList_GET_ITEM(filters, 0) == NULL || - PyList_GET_ITEM(filters, 1) == NULL || - PyList_GET_ITEM(filters, 2) == NULL) { - Py_DECREF(filters); - return NULL; + for (x = 0; x < pos; x += 1) { + if (PyList_GET_ITEM(filters, x) == NULL) { + Py_DECREF(filters); + return NULL; + } } return filters; -- cgit v1.2.1 From 68329b8e5bac8f788048f3aa52ebf4e345793fa4 Mon Sep 17 00:00:00 2001 From: Matthias Klose Date: Tue, 6 Jul 2010 10:53:30 +0000 Subject: - sysmodule.c (get_hash_info): Define as static function. --- Python/sysmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 9ec8ab1489..61c9b1ef33 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -595,7 +595,7 @@ static PyStructSequence_Desc hash_info_desc = { 5, }; -PyObject * +static PyObject * get_hash_info(void) { PyObject *hash_info; -- cgit v1.2.1 From 4604302f01b95df559dc826a157fe3b2f33bf7cf Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sat, 10 Jul 2010 10:32:36 +0000 Subject: #3071: tell how many values were expected when unpacking too many. --- Python/ceval.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 6e4911ae92..2d4b16a39a 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3464,7 +3464,8 @@ unpack_iterable(PyObject *v, int argcnt, int argcntafter, PyObject **sp) return 1; } Py_DECREF(w); - PyErr_SetString(PyExc_ValueError, "too many values to unpack"); + PyErr_Format(PyExc_ValueError, "too many values to unpack " + "(expected %d)", argcnt); goto Error; } -- cgit v1.2.1 From 3e296ccb56e0540e87282733fdaccb290e7a0959 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Mon, 12 Jul 2010 14:18:21 +0000 Subject: Regenerate Python/graminit.c. --- Python/graminit.c | 100 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 82 insertions(+), 18 deletions(-) (limited to 'Python') diff --git a/Python/graminit.c b/Python/graminit.c index 691e1687c6..a8af5833a9 100644 --- a/Python/graminit.c +++ b/Python/graminit.c @@ -180,8 +180,8 @@ static arc arcs_8_4[1] = { {24, 9}, }; static arc arcs_8_5[4] = { - {28, 1}, - {31, 2}, + {28, 10}, + {31, 11}, {32, 3}, {0, 5}, }; @@ -190,7 +190,7 @@ static arc arcs_8_6[2] = { {0, 6}, }; static arc arcs_8_7[2] = { - {28, 10}, + {28, 12}, {32, 3}, }; static arc arcs_8_8[1] = { @@ -201,14 +201,40 @@ static arc arcs_8_9[2] = { {0, 9}, }; static arc arcs_8_10[3] = { - {30, 7}, - {29, 11}, + {30, 5}, + {29, 4}, {0, 10}, }; -static arc arcs_8_11[1] = { +static arc arcs_8_11[3] = { + {28, 13}, + {30, 14}, + {0, 11}, +}; +static arc arcs_8_12[3] = { + {30, 7}, + {29, 15}, + {0, 12}, +}; +static arc arcs_8_13[2] = { + {30, 14}, + {0, 13}, +}; +static arc arcs_8_14[2] = { + {28, 16}, + {32, 3}, +}; +static arc arcs_8_15[1] = { {24, 6}, }; -static state states_8[12] = { +static arc arcs_8_16[3] = { + {30, 14}, + {29, 17}, + {0, 16}, +}; +static arc arcs_8_17[1] = { + {24, 13}, +}; +static state states_8[18] = { {3, arcs_8_0}, {3, arcs_8_1}, {3, arcs_8_2}, @@ -220,7 +246,13 @@ static state states_8[12] = { {1, arcs_8_8}, {2, arcs_8_9}, {3, arcs_8_10}, - {1, arcs_8_11}, + {3, arcs_8_11}, + {3, arcs_8_12}, + {2, arcs_8_13}, + {2, arcs_8_14}, + {1, arcs_8_15}, + {3, arcs_8_16}, + {1, arcs_8_17}, }; static arc arcs_9_0[1] = { {21, 1}, @@ -263,8 +295,8 @@ static arc arcs_10_4[1] = { {24, 9}, }; static arc arcs_10_5[4] = { - {34, 1}, - {31, 2}, + {34, 10}, + {31, 11}, {32, 3}, {0, 5}, }; @@ -273,7 +305,7 @@ static arc arcs_10_6[2] = { {0, 6}, }; static arc arcs_10_7[2] = { - {34, 10}, + {34, 12}, {32, 3}, }; static arc arcs_10_8[1] = { @@ -284,14 +316,40 @@ static arc arcs_10_9[2] = { {0, 9}, }; static arc arcs_10_10[3] = { - {30, 7}, - {29, 11}, + {30, 5}, + {29, 4}, {0, 10}, }; -static arc arcs_10_11[1] = { +static arc arcs_10_11[3] = { + {34, 13}, + {30, 14}, + {0, 11}, +}; +static arc arcs_10_12[3] = { + {30, 7}, + {29, 15}, + {0, 12}, +}; +static arc arcs_10_13[2] = { + {30, 14}, + {0, 13}, +}; +static arc arcs_10_14[2] = { + {34, 16}, + {32, 3}, +}; +static arc arcs_10_15[1] = { {24, 6}, }; -static state states_10[12] = { +static arc arcs_10_16[3] = { + {30, 14}, + {29, 17}, + {0, 16}, +}; +static arc arcs_10_17[1] = { + {24, 13}, +}; +static state states_10[18] = { {3, arcs_10_0}, {3, arcs_10_1}, {3, arcs_10_2}, @@ -303,7 +361,13 @@ static state states_10[12] = { {1, arcs_10_8}, {2, arcs_10_9}, {3, arcs_10_10}, - {1, arcs_10_11}, + {3, arcs_10_11}, + {3, arcs_10_12}, + {2, arcs_10_13}, + {2, arcs_10_14}, + {1, arcs_10_15}, + {3, arcs_10_16}, + {1, arcs_10_17}, }; static arc arcs_11_0[1] = { {21, 1}, @@ -1755,11 +1819,11 @@ static dfa dfas[81] = { "\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {263, "parameters", 0, 4, states_7, "\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {264, "typedargslist", 0, 12, states_8, + {264, "typedargslist", 0, 18, states_8, "\000\000\040\200\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {265, "tfpdef", 0, 4, states_9, "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {266, "varargslist", 0, 12, states_10, + {266, "varargslist", 0, 18, states_10, "\000\000\040\200\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {267, "vfpdef", 0, 2, states_11, "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, -- cgit v1.2.1 From a1047ef59eacea8f3b31386bb6c4a766d6237fd7 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 20 Jul 2010 22:37:19 +0000 Subject: move test_trace.py so as not to conflict with future tests for the trace module --- Python/ceval.c | 16 ++++++++-------- Python/compile.c | 4 +++- Python/symtable.c | 11 +++++++++-- 3 files changed, 20 insertions(+), 11 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 2d4b16a39a..368ad695ea 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2052,6 +2052,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) break; TARGET(LOAD_NAME) + TARGET(LOAD_NAME_LOCAL_ONLY) w = GETITEM(names, oparg); if ((v = f->f_locals) == NULL) { PyErr_Format(PyExc_SystemError, @@ -2073,15 +2074,14 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) } } if (x == NULL) { - x = PyDict_GetItem(f->f_globals, w); + if (opcode != LOAD_NAME_LOCAL_ONLY) { + x = PyDict_GetItem(f->f_globals, w); + if (x == NULL) + x = PyDict_GetItem(f->f_builtins, 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; - } + format_exc_check_arg(PyExc_NameError, NAME_ERROR_MSG, w); + break; } Py_INCREF(x); } diff --git a/Python/compile.c b/Python/compile.c index aae0339c2c..83c9e0211e 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -787,6 +787,7 @@ opcode_stack_effect(int opcode, int oparg) case LOAD_CONST: return 1; case LOAD_NAME: + case LOAD_NAME_LOCAL_ONLY: return 1; case BUILD_TUPLE: case BUILD_LIST: @@ -2481,6 +2482,7 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) optype = OP_DEREF; break; case LOCAL: + case LOCAL_ONLY: if (c->u->u_ste->ste_type == FunctionBlock) optype = OP_FAST; break; @@ -2556,7 +2558,7 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) break; case OP_NAME: switch (ctx) { - case Load: op = LOAD_NAME; break; + case Load: op = (scope == LOCAL_ONLY) ? LOAD_NAME_LOCAL_ONLY : LOAD_NAME; break; case Store: op = STORE_NAME; break; case Del: op = DELETE_NAME; break; case AugLoad: diff --git a/Python/symtable.c b/Python/symtable.c index 55c9f472fc..37bdf2a105 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -432,7 +432,14 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags, return PySet_Add(free, name) >= 0; } if (flags & DEF_BOUND) { - SET_SCOPE(scopes, name, LOCAL); + if (ste->ste_type == ClassBlock && + !(flags & DEF_PARAM) && + bound && PySet_Contains(bound, name)) { + SET_SCOPE(scopes, name, LOCAL_ONLY); + } + else { + SET_SCOPE(scopes, name, LOCAL); + } if (PySet_Add(local, name) < 0) return 0; if (PySet_Discard(global, name) < 0) @@ -489,7 +496,7 @@ analyze_cells(PyObject *scopes, PyObject *free, const char *restricted) long scope; assert(PyLong_Check(v)); scope = PyLong_AS_LONG(v); - if (scope != LOCAL) + if (scope != LOCAL && scope != LOCAL_ONLY) continue; if (!PySet_Contains(free, name)) continue; -- cgit v1.2.1 From b1dabe110111af235ea2829b44e9e9f44aed91ef Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 20 Jul 2010 22:39:34 +0000 Subject: revert unintended changes --- Python/ceval.c | 16 ++++++++-------- Python/compile.c | 4 +--- Python/symtable.c | 11 ++--------- 3 files changed, 11 insertions(+), 20 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 368ad695ea..2d4b16a39a 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2052,7 +2052,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) break; TARGET(LOAD_NAME) - TARGET(LOAD_NAME_LOCAL_ONLY) w = GETITEM(names, oparg); if ((v = f->f_locals) == NULL) { PyErr_Format(PyExc_SystemError, @@ -2074,14 +2073,15 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) } } if (x == NULL) { - if (opcode != LOAD_NAME_LOCAL_ONLY) { - x = PyDict_GetItem(f->f_globals, w); - if (x == NULL) - x = PyDict_GetItem(f->f_builtins, w); - } + x = PyDict_GetItem(f->f_globals, w); if (x == NULL) { - format_exc_check_arg(PyExc_NameError, NAME_ERROR_MSG, w); - break; + x = PyDict_GetItem(f->f_builtins, w); + if (x == NULL) { + format_exc_check_arg( + PyExc_NameError, + NAME_ERROR_MSG, w); + break; + } } Py_INCREF(x); } diff --git a/Python/compile.c b/Python/compile.c index 83c9e0211e..aae0339c2c 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -787,7 +787,6 @@ opcode_stack_effect(int opcode, int oparg) case LOAD_CONST: return 1; case LOAD_NAME: - case LOAD_NAME_LOCAL_ONLY: return 1; case BUILD_TUPLE: case BUILD_LIST: @@ -2482,7 +2481,6 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) optype = OP_DEREF; break; case LOCAL: - case LOCAL_ONLY: if (c->u->u_ste->ste_type == FunctionBlock) optype = OP_FAST; break; @@ -2558,7 +2556,7 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) break; case OP_NAME: switch (ctx) { - case Load: op = (scope == LOCAL_ONLY) ? LOAD_NAME_LOCAL_ONLY : LOAD_NAME; break; + case Load: op = LOAD_NAME; break; case Store: op = STORE_NAME; break; case Del: op = DELETE_NAME; break; case AugLoad: diff --git a/Python/symtable.c b/Python/symtable.c index 37bdf2a105..55c9f472fc 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -432,14 +432,7 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags, return PySet_Add(free, name) >= 0; } if (flags & DEF_BOUND) { - if (ste->ste_type == ClassBlock && - !(flags & DEF_PARAM) && - bound && PySet_Contains(bound, name)) { - SET_SCOPE(scopes, name, LOCAL_ONLY); - } - else { - SET_SCOPE(scopes, name, LOCAL); - } + SET_SCOPE(scopes, name, LOCAL); if (PySet_Add(local, name) < 0) return 0; if (PySet_Discard(global, name) < 0) @@ -496,7 +489,7 @@ analyze_cells(PyObject *scopes, PyObject *free, const char *restricted) long scope; assert(PyLong_Check(v)); scope = PyLong_AS_LONG(v); - if (scope != LOCAL && scope != LOCAL_ONLY) + if (scope != LOCAL) continue; if (!PySet_Contains(free, name)) continue; -- cgit v1.2.1 From ed5b199596c6d8fb8397e2f7ac93d24a59ebab5d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 28 Jul 2010 00:40:58 +0000 Subject: Issue #8991: convertbuffer() rejects discontigious buffers --- Python/getargs.c | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index 7b929481d2..e4bd50d7b3 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1246,13 +1246,15 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, PyErr_Clear(); return converterr("read-write buffer", arg, msgbuf, bufsize); } + if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) { + PyBuffer_Release((Py_buffer*)p); + return converterr("contiguous buffer", arg, msgbuf, bufsize); + } if (addcleanup(p, freelist, cleanup_buffer)) { return converterr( "(cleanup problem)", arg, msgbuf, bufsize); } - if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) - return converterr("contiguous buffer", arg, msgbuf, bufsize); break; } @@ -1274,41 +1276,26 @@ convertbuffer(PyObject *arg, void **p, char **errmsg) *errmsg = NULL; *p = NULL; - if (pb == NULL || - pb->bf_getbuffer == NULL || - pb->bf_releasebuffer != NULL) { - *errmsg = "bytes or read-only buffer"; + if (pb != NULL && pb->bf_releasebuffer != NULL) { + *errmsg = "read-only pinned buffer"; return -1; } - if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) != 0) { - *errmsg = "bytes or single-segment read-only buffer"; + if (getbuffer(arg, &view, errmsg) < 0) return -1; - } count = view.len; *p = view.buf; PyBuffer_Release(&view); return count; } -/* XXX for 3.x, getbuffer and convertbuffer can probably - be merged again. */ static int getbuffer(PyObject *arg, Py_buffer *view, char **errmsg) { - PyBufferProcs *pb = Py_TYPE(arg)->tp_as_buffer; - if (pb == NULL) { + if (PyObject_GetBuffer(arg, view, PyBUF_SIMPLE) != 0) { *errmsg = "bytes or buffer"; return -1; } - if (pb->bf_getbuffer == NULL) { - *errmsg = "convertible to a buffer"; - return -1; - } - if (PyObject_GetBuffer(arg, view, 0) < 0) { - *errmsg = "convertible to a buffer"; - return -1; - } if (!PyBuffer_IsContiguous(view, 'C')) { PyBuffer_Release(view); *errmsg = "contiguous buffer"; -- cgit v1.2.1 From 0853927bef9e694ebb94a5ac91d9ca46b69ddcb1 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sat, 31 Jul 2010 09:01:16 +0000 Subject: Update copyright years and add releases to release list. Also update Sphinx version number. --- Python/getcopyright.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/getcopyright.c b/Python/getcopyright.c index a5e7fa6396..43a0293885 100644 --- a/Python/getcopyright.c +++ b/Python/getcopyright.c @@ -2,7 +2,7 @@ #include "Python.h" -static char cprt[] = +static char cprt[] = "\ Copyright (c) 2001-2010 Python Software Foundation.\n\ All Rights Reserved.\n\ -- cgit v1.2.1 From 3c42b5fe6165dbf64e9479b6b75c52088030e878 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sat, 31 Jul 2010 19:29:15 +0000 Subject: Remove trailing whitespace. --- Python/getversion.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/getversion.c b/Python/getversion.c index 7af16fc810..7bd6efd0a0 100644 --- a/Python/getversion.c +++ b/Python/getversion.c @@ -9,7 +9,7 @@ const char * Py_GetVersion(void) { static char version[250]; - PyOS_snprintf(version, sizeof(version), "%.80s (%.80s) %.80s", + PyOS_snprintf(version, sizeof(version), "%.80s (%.80s) %.80s", PY_VERSION, Py_GetBuildInfo(), Py_GetCompiler()); return version; } -- cgit v1.2.1 From 3d274b327dd0211aae4b809de8f4eaf524c68e26 Mon Sep 17 00:00:00 2001 From: Alexander Belopolsky Date: Thu, 5 Aug 2010 17:34:27 +0000 Subject: Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API exposed in Python.h. This function is similar to POSIX gettimeofday(struct timeval *tp), but available on platforms without gettimeofday(). --- Python/pythonrun.c | 2 ++ Python/pytime.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 Python/pytime.c (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index f45d7dc9fa..79a19f8dd7 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -268,6 +268,8 @@ Py_InitializeEx(int install_sigs) /* Initialize _warnings. */ _PyWarnings_Init(); + _PyTime_Init(); + initfsencoding(); if (install_sigs) diff --git a/Python/pytime.c b/Python/pytime.c new file mode 100644 index 0000000000..6fb7695911 --- /dev/null +++ b/Python/pytime.c @@ -0,0 +1,60 @@ +#include "Python.h" + +#ifdef __APPLE__ +#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_FTIME) + /* + * _PyTime_gettimeofday falls back to ftime when getttimeofday fails because the latter + * might fail on some platforms. This fallback is unwanted on MacOSX because + * that makes it impossible to use a binary build on OSX 10.4 on earlier + * releases of the OS. Therefore claim we don't support ftime. + */ +# undef HAVE_FTIME +#endif +#endif + +#ifdef HAVE_FTIME +#include +#if !defined(MS_WINDOWS) && !defined(PYOS_OS2) +extern int ftime(struct timeb *); +#endif /* MS_WINDOWS */ +#endif /* HAVE_FTIME */ + +void +_PyTime_gettimeofday(_PyTime_timeval *tp) +{ + /* There are three ways to get the time: + (1) gettimeofday() -- resolution in microseconds + (2) ftime() -- resolution in milliseconds + (3) time() -- resolution in seconds + In all cases the return value in a timeval struct. + Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may + fail, so we fall back on ftime() or time(). + Note: clock resolution does not imply clock accuracy! */ +#ifdef HAVE_GETTIMEOFDAY +#ifdef GETTIMEOFDAY_NO_TZ + if (gettimeofday(tp) == 0) + return; +#else /* !GETTIMEOFDAY_NO_TZ */ + if (gettimeofday(tp, (struct timezone *)NULL) == 0) + return; +#endif /* !GETTIMEOFDAY_NO_TZ */ +#endif /* !HAVE_GETTIMEOFDAY */ +#if defined(HAVE_FTIME) + { + struct timeb t; + ftime(&t); + tp->tv_sec = t.time; + tp->tv_usec = t.millitm * 1000; + } +#else /* !HAVE_FTIME */ + tp->tv_sec = time(NULL); + tp->tv_usec = 0; +#endif /* !HAVE_FTIME */ + return; +} + +void +_PyTime_Init() +{ + /* Do nothing. Needed to force linking. */ +} -- cgit v1.2.1 From 9847d74fb7da263e9d1943d6c635656d54f44de6 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sun, 8 Aug 2010 20:46:42 +0000 Subject: Issue #5319: Print an error if flushing stdout fails at interpreter shutdown. --- Python/pythonrun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 79a19f8dd7..233fc16ea1 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -320,7 +320,7 @@ flush_std_files(void) if (fout != NULL && fout != Py_None) { tmp = PyObject_CallMethod(fout, "flush", ""); if (tmp == NULL) - PyErr_Clear(); + PyErr_WriteUnraisable(fout); else Py_DECREF(tmp); } -- cgit v1.2.1 From 9cf5be7cb4a473c73ca651db5ebee9dda4cad25a Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 8 Aug 2010 22:12:45 +0000 Subject: Issue #9425: fix setup_context() for non-ascii filenames setup_context() replaces .pyc or .pyo filename suffix by .py, but it didn't work if the filename contains a non-ascii character because the function used the wrong unit for the length (number of characters instead of the number of bytes). With this patch, it uses unicode filenames instead of bytes filenames, to fix the bug and to be fully unicode compliant. --- Python/_warnings.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'Python') diff --git a/Python/_warnings.c b/Python/_warnings.c index dd7bb57965..6067ce3a47 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -498,23 +498,21 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, *filename = PyDict_GetItemString(globals, "__file__"); if (*filename != NULL) { Py_ssize_t len = PyUnicode_GetSize(*filename); - const char *file_str = _PyUnicode_AsString(*filename); - if (file_str == NULL || (len < 0 && PyErr_Occurred())) - goto handle_error; + Py_UNICODE *unicode = PyUnicode_AS_UNICODE(*filename); /* if filename.lower().endswith((".pyc", ".pyo")): */ if (len >= 4 && - file_str[len-4] == '.' && - tolower(file_str[len-3]) == 'p' && - tolower(file_str[len-2]) == 'y' && - (tolower(file_str[len-1]) == 'c' || - tolower(file_str[len-1]) == 'o')) + unicode[len-4] == '.' && + Py_UNICODE_TOLOWER(unicode[len-3]) == 'p' && + Py_UNICODE_TOLOWER(unicode[len-2]) == 'y' && + (Py_UNICODE_TOLOWER(unicode[len-1]) == 'c' || + Py_UNICODE_TOLOWER(unicode[len-1]) == 'o')) { - *filename = PyUnicode_FromStringAndSize(file_str, len-1); - if (*filename == NULL) - goto handle_error; - } - else + *filename = PyUnicode_FromUnicode(unicode, len-1); + if (*filename == NULL) + goto handle_error; + } + else Py_INCREF(*filename); } else { -- cgit v1.2.1 From 258aa419f44f3c3b45a9ac1db3f6f02519f3d91b Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sun, 8 Aug 2010 22:18:46 +0000 Subject: Issue #477863: Print a warning at shutdown if gc.garbage is not empty. --- Python/pythonrun.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 233fc16ea1..a7a54ba710 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -404,6 +404,9 @@ Py_Finalize(void) while (PyGC_Collect() > 0) /* nothing */; #endif + /* We run this while most interpreter state is still alive, so that + debug information can be printed out */ + _PyGC_Fini(); /* Destroy all modules */ PyImport_Cleanup(); -- cgit v1.2.1 From c0d267968da847149d2f96af1036ada254843c3b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 9 Aug 2010 00:59:10 +0000 Subject: Issue #9425: Create load_builtin() subfunction Just move the code and some variables. --- Python/import.c | 70 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 30 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 194e360562..c06aa1c646 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2013,15 +2013,52 @@ find_init_module(char *buf) static int init_builtin(char *); /* Forward */ +static PyObject* +load_builtin(char *name, char *pathname, int type) +{ + PyObject *m, *modules; + int err; + + if (pathname != NULL && pathname[0] != '\0') + name = pathname; + + 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); + return m; +} + /* 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 *pathname, int type, PyObject *loader) { - PyObject *modules; PyObject *m; - int err; /* First check that there's an open file (if we need one) */ switch (type) { @@ -2057,34 +2094,7 @@ load_module(char *name, FILE *fp, char *pathname, int type, PyObject *loader) case C_BUILTIN: case PY_FROZEN: - if (pathname != NULL && pathname[0] != '\0') - name = pathname; - 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); + m = load_builtin(name, pathname, type); break; case IMP_HOOK: { -- cgit v1.2.1 From 9d33a144f448496eb3c381dcbe253bbe5c74b8d4 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Tue, 10 Aug 2010 13:48:51 +0000 Subject: =?UTF-8?q?Issue=20#8411:=20new=20condition=20variable=20emulation?= =?UTF-8?q?=20under=20Windows=20for=20the=20new=20GIL,=20by=20Kristj=C3=A1?= =?UTF-8?q?n.=20=20Unfortunately=20the=203.x=20Windows=20buildbots=20are?= =?UTF-8?q?=20in=20a=20wreck,=20so=20we'll=20have=20to=20watch=20them=20wh?= =?UTF-8?q?en=20they=20become=20fit=20again.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Python/ceval_gil.h | 157 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 105 insertions(+), 52 deletions(-) (limited to 'Python') diff --git a/Python/ceval_gil.h b/Python/ceval_gil.h index a284c5d8ce..7d72016083 100644 --- a/Python/ceval_gil.h +++ b/Python/ceval_gil.h @@ -106,7 +106,6 @@ do { \ #define COND_INIT(cond) \ if (pthread_cond_init(&cond, NULL)) { \ Py_FatalError("pthread_cond_init(" #cond ") failed"); }; -#define COND_RESET(cond) #define COND_SIGNAL(cond) \ if (pthread_cond_signal(&cond)) { \ Py_FatalError("pthread_cond_signal(" #cond ") failed"); }; @@ -141,64 +140,120 @@ do { \ #include -#define MUTEX_T HANDLE -#define MUTEX_INIT(mut) \ - if (!(mut = CreateMutex(NULL, FALSE, NULL))) { \ - Py_FatalError("CreateMutex(" #mut ") failed"); }; +#define MUTEX_T CRITICAL_SECTION +#define MUTEX_INIT(mut) do { \ + if (!(InitializeCriticalSectionAndSpinCount(&(mut), 4000))) \ + Py_FatalError("CreateMutex(" #mut ") failed"); \ +} while (0) +#define MUTEX_FINI(mut) \ + DeleteCriticalSection(&(mut)) #define MUTEX_LOCK(mut) \ - if (WaitForSingleObject(mut, INFINITE) != WAIT_OBJECT_0) { \ - Py_FatalError("WaitForSingleObject(" #mut ") failed"); }; + EnterCriticalSection(&(mut)) #define MUTEX_UNLOCK(mut) \ - if (!ReleaseMutex(mut)) { \ - Py_FatalError("ReleaseMutex(" #mut ") failed"); }; - -/* We emulate condition variables with events. It is sufficient here. - WaitForMultipleObjects() allows the event to be caught and the mutex - to be taken atomically. - As for SignalObjectAndWait(), its semantics are unfortunately a bit - more foggy. Many sources on the Web define it as atomically releasing - the first object while starting to wait on the second, but MSDN states - it is *not* atomic... - - In any case, the emulation here is tailored for our particular use case. - For example, we don't care how many threads are woken up when a condition - gets signalled. Generic emulations of the pthread_cond_* API using + LeaveCriticalSection(&(mut)) + +/* We emulate condition variables with a semaphore. + We use a Semaphore rather than an auto-reset event, because although + an auto-resent event might appear to solve the lost-wakeup bug (race + condition between releasing the outer lock and waiting) because it + maintains state even though a wait hasn't happened, there is still + a lost wakeup problem if more than one thread are interrupted in the + critical place. A semaphore solves that. + Because it is ok to signal a condition variable with no one + waiting, we need to keep track of the number of + waiting threads. Otherwise, the semaphore's state could rise + without bound. + + Generic emulations of the pthread_cond_* API using Win32 functions can be found on the Web. The following read can be edificating (or not): http://www.cse.wustl.edu/~schmidt/win32-cv-1.html */ -#define COND_T HANDLE +typedef struct COND_T +{ + HANDLE sem; /* the semaphore */ + int n_waiting; /* how many are unreleased */ +} COND_T; + +__inline static void _cond_init(COND_T *cond) +{ + /* A semaphore with a large max value, The positive value + * is only needed to catch those "lost wakeup" events and + * race conditions when a timed wait elapses. + */ + if (!(cond->sem = CreateSemaphore(NULL, 0, 1000, NULL))) + Py_FatalError("CreateSemaphore() failed"); + cond->n_waiting = 0; +} + +__inline static void _cond_fini(COND_T *cond) +{ + BOOL ok = CloseHandle(cond->sem); + if (!ok) + Py_FatalError("CloseHandle() failed"); +} + +__inline static void _cond_wait(COND_T *cond, MUTEX_T *mut) +{ + ++cond->n_waiting; + MUTEX_UNLOCK(*mut); + /* "lost wakeup bug" would occur if the caller were interrupted here, + * but we are safe because we are using a semaphore wich has an internal + * count. + */ + if (WaitForSingleObject(cond->sem, INFINITE) == WAIT_FAILED) + Py_FatalError("WaitForSingleObject() failed"); + MUTEX_LOCK(*mut); +} + +__inline static int _cond_timed_wait(COND_T *cond, MUTEX_T *mut, + int us) +{ + DWORD r; + ++cond->n_waiting; + MUTEX_UNLOCK(*mut); + r = WaitForSingleObject(cond->sem, us / 1000); + if (r == WAIT_FAILED) + Py_FatalError("WaitForSingleObject() failed"); + MUTEX_LOCK(*mut); + if (r == WAIT_TIMEOUT) + --cond->n_waiting; + /* Here we have a benign race condition with _cond_signal. If the + * wait operation has timed out, but before we can acquire the + * mutex again to decrement n_waiting, a thread holding the mutex + * still sees a positive n_waiting value and may call + * ReleaseSemaphore and decrement n_waiting. + * This will cause n_waiting to be decremented twice. + * This is benign, though, because ReleaseSemaphore will also have + * been called, leaving the semaphore state positive. We may + * thus end up with semaphore in state 1, and n_waiting == -1, and + * the next time someone calls _cond_wait(), that thread will + * pass right through, decrementing the semaphore state and + * incrementing n_waiting, thus correcting the extra _cond_signal. + */ + return r == WAIT_TIMEOUT; +} + +__inline static void _cond_signal(COND_T *cond) { + /* NOTE: This must be called with the mutex held */ + if (cond->n_waiting > 0) { + if (!ReleaseSemaphore(cond->sem, 1, NULL)) + Py_FatalError("ReleaseSemaphore() failed"); + --cond->n_waiting; + } +} + #define COND_INIT(cond) \ - /* auto-reset, non-signalled */ \ - if (!(cond = CreateEvent(NULL, FALSE, FALSE, NULL))) { \ - Py_FatalError("CreateMutex(" #cond ") failed"); }; -#define COND_RESET(cond) \ - if (!ResetEvent(cond)) { \ - Py_FatalError("ResetEvent(" #cond ") failed"); }; + _cond_init(&(cond)) +#define COND_FINI(cond) \ + _cond_fini(&(cond)) #define COND_SIGNAL(cond) \ - if (!SetEvent(cond)) { \ - Py_FatalError("SetEvent(" #cond ") failed"); }; + _cond_signal(&(cond)) #define COND_WAIT(cond, mut) \ - { \ - if (SignalObjectAndWait(mut, cond, INFINITE, FALSE) != WAIT_OBJECT_0) \ - Py_FatalError("SignalObjectAndWait(" #mut ", " #cond") failed"); \ - MUTEX_LOCK(mut); \ - } -#define COND_TIMED_WAIT(cond, mut, microseconds, timeout_result) \ - { \ - DWORD r; \ - HANDLE objects[2] = { cond, mut }; \ - MUTEX_UNLOCK(mut); \ - r = WaitForMultipleObjects(2, objects, TRUE, microseconds / 1000); \ - if (r == WAIT_TIMEOUT) { \ - MUTEX_LOCK(mut); \ - timeout_result = 1; \ - } \ - else if (r != WAIT_OBJECT_0) \ - Py_FatalError("WaitForSingleObject(" #cond ") failed"); \ - else \ - timeout_result = 0; \ - } + _cond_wait(&(cond), &(mut)) +#define COND_TIMED_WAIT(cond, mut, us, timeout_result) do { \ + (timeout_result) = _cond_timed_wait(&(cond), &(mut), us); \ +} while (0) #else @@ -282,7 +337,6 @@ static void drop_gil(PyThreadState *tstate) the GIL and drop it again, and reset the condition before we even had a chance to wait for it. */ COND_WAIT(switch_cond, switch_mutex); - COND_RESET(switch_cond); } MUTEX_UNLOCK(switch_mutex); } @@ -301,7 +355,6 @@ static void take_gil(PyThreadState *tstate) if (!_Py_atomic_load_relaxed(&gil_locked)) goto _ready; - COND_RESET(gil_cond); while (_Py_atomic_load_relaxed(&gil_locked)) { int timed_out = 0; unsigned long saved_switchnum; -- cgit v1.2.1 From 35ce36d96009a24d4f588bf27c1c07e2af4fc822 Mon Sep 17 00:00:00 2001 From: Alexander Belopolsky Date: Wed, 11 Aug 2010 17:31:17 +0000 Subject: Issue #2443: Added a new macro, Py_VA_COPY, which is equivalent to C99 va_copy, but available on all python platforms. Untabified a few unrelated files. --- Python/getargs.c | 40 ++++------------------------------------ Python/modsupport.c | 10 +--------- 2 files changed, 5 insertions(+), 45 deletions(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index e4bd50d7b3..abf55ce041 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -105,15 +105,7 @@ 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 + Py_VA_COPY(lva, va); return vgetargs1(args, format, &lva, 0); } @@ -123,15 +115,7 @@ _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 + Py_VA_COPY(lva, va); return vgetargs1(args, format, &lva, FLAG_SIZE_T); } @@ -1376,15 +1360,7 @@ PyArg_VaParseTupleAndKeywords(PyObject *args, 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 + Py_VA_COPY(lva, va); retval = vgetargskeywords(args, keywords, format, kwlist, &lva, 0); return retval; @@ -1408,15 +1384,7 @@ _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *args, 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 + Py_VA_COPY(lva, va); retval = vgetargskeywords(args, keywords, format, kwlist, &lva, FLAG_SIZE_T); diff --git a/Python/modsupport.c b/Python/modsupport.c index 5f5d842eea..85b0d66358 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -456,15 +456,7 @@ va_build_value(const char *format, va_list va, int flags) 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 + Py_VA_COPY(lva, va); if (n < 0) return NULL; -- cgit v1.2.1 From 03475a856ee2943e4a781b80ff0cac6c44f0e109 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 13 Aug 2010 13:07:29 +0000 Subject: Issue #9425: NullImporter constructor is fully unicode compliant * On non-Windows OSes: the constructor accepts bytes filenames and use surrogateescape for unicode filenames * On Windows: use GetFileAttributesW() instead of GetFileAttributesA() --- Python/import.c | 90 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 52 insertions(+), 38 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index c06aa1c646..4cdce74702 100644 --- a/Python/import.c +++ b/Python/import.c @@ -3623,56 +3623,70 @@ typedef struct { static int NullImporter_init(NullImporter *self, PyObject *args, PyObject *kwds) { - char *path; - Py_ssize_t pathlen; +#ifndef MS_WINDOWS + PyObject *path; + struct stat statbuf; + int rv; if (!_PyArg_NoKeywords("NullImporter()", kwds)) return -1; - if (!PyArg_ParseTuple(args, "es:NullImporter", - Py_FileSystemDefaultEncoding, &path)) + if (!PyArg_ParseTuple(args, "O&:NullImporter", + PyUnicode_FSConverter, &path)) return -1; - pathlen = strlen(path); - if (pathlen == 0) { - PyMem_Free(path); + if (PyBytes_GET_SIZE(path) == 0) { + Py_DECREF(path); PyErr_SetString(PyExc_ImportError, "empty pathname"); return -1; - } else { -#ifndef MS_WINDOWS - struct stat statbuf; - int rv; - - rv = stat(path, &statbuf); - PyMem_Free(path); - if (rv == 0) { - /* it exists */ - if (S_ISDIR(statbuf.st_mode)) { - /* it's a directory */ - PyErr_SetString(PyExc_ImportError, - "existing directory"); - return -1; - } + } + + rv = stat(PyBytes_AS_STRING(path), &statbuf); + Py_DECREF(path); + if (rv == 0) { + /* it exists */ + if (S_ISDIR(statbuf.st_mode)) { + /* it's a directory */ + PyErr_SetString(PyExc_ImportError, "existing directory"); + return -1; } + } #else /* MS_WINDOWS */ - DWORD rv; - /* see issue1293 and issue3677: - * stat() on Windows doesn't recognise paths like - * "e:\\shared\\" and "\\\\whiterab-c2znlh\\shared" as dirs. - */ - rv = GetFileAttributesA(path); - PyMem_Free(path); - if (rv != INVALID_FILE_ATTRIBUTES) { - /* it exists */ - if (rv & FILE_ATTRIBUTE_DIRECTORY) { - /* it's a directory */ - PyErr_SetString(PyExc_ImportError, - "existing directory"); - return -1; - } + PyObject *pathobj; + DWORD rv; + wchar_t path[MAXPATHLEN+1]; + Py_ssize_t len; + + if (!_PyArg_NoKeywords("NullImporter()", kwds)) + return -1; + + if (!PyArg_ParseTuple(args, "U:NullImporter", + &pathobj)) + return -1; + + if (PyUnicode_GET_SIZE(pathobj) == 0) { + PyErr_SetString(PyExc_ImportError, "empty pathname"); + return -1; + } + + len = PyUnicode_AsWideChar((PyUnicodeObject*)pathobj, + path, sizeof(path) / sizeof(path[0])); + if (len == -1) + return -1; + /* see issue1293 and issue3677: + * stat() on Windows doesn't recognise paths like + * "e:\\shared\\" and "\\\\whiterab-c2znlh\\shared" as dirs. + */ + rv = GetFileAttributesW(path); + if (rv != INVALID_FILE_ATTRIBUTES) { + /* it exists */ + if (rv & FILE_ATTRIBUTE_DIRECTORY) { + /* it's a directory */ + PyErr_SetString(PyExc_ImportError, "existing directory"); + return -1; } -#endif } +#endif return 0; } -- cgit v1.2.1 From 5c829d60a6fdece8817e469ceff6441101193fc7 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 13 Aug 2010 14:03:48 +0000 Subject: Issue #9425: Create PyErr_WarnFormat() function Similar to PyErr_WarnEx() but use PyUnicode_FromFormatV() to format the warning message. Strip also some trailing spaces. --- Python/_warnings.c | 46 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) (limited to 'Python') diff --git a/Python/_warnings.c b/Python/_warnings.c index 6067ce3a47..63bcbffea9 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -710,19 +710,17 @@ warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds) /* Function to issue a warning message; may raise an exception. */ -int -PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level) + +static int +warn_unicode(PyObject *category, PyObject *message, + Py_ssize_t stack_level) { PyObject *res; - PyObject *message = PyUnicode_FromString(text); - if (message == NULL) - return -1; if (category == NULL) category = PyExc_RuntimeWarning; res = do_warn(message, category, stack_level); - Py_DECREF(message); if (res == NULL) return -1; Py_DECREF(res); @@ -730,6 +728,42 @@ PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level) return 0; } +int +PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level, + const char *format, ...) +{ + int ret; + PyObject *message; + va_list vargs; + +#ifdef HAVE_STDARG_PROTOTYPES + va_start(vargs, format); +#else + va_start(vargs); +#endif + message = PyUnicode_FromFormatV(format, vargs); + if (message != NULL) { + ret = warn_unicode(category, message, stack_level); + Py_DECREF(message); + } + else + ret = -1; + va_end(vargs); + return ret; +} + +int +PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level) +{ + int ret; + PyObject *message = PyUnicode_FromString(text); + if (message == NULL) + return -1; + ret = warn_unicode(category, message, stack_level); + Py_DECREF(message); + return ret; +} + /* PyErr_Warn is only for backwards compatability and will be removed. Use PyErr_WarnEx instead. */ -- cgit v1.2.1 From 30309e01ea5a6eb0dae3c5dd3cce1df41668d1db Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Fri, 13 Aug 2010 21:15:58 +0000 Subject: Issue #9203: Computed gotos are now enabled by default on supported compilers (which are detected by the configure script). They can still be disable selectively by specifying --without-computed-gotos. --- Python/ceval.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 2d4b16a39a..c2c4e78f19 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -840,11 +840,24 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) -fno-crossjumping). */ -#if defined(USE_COMPUTED_GOTOS) && defined(DYNAMIC_EXECUTION_PROFILE) +#ifdef DYNAMIC_EXECUTION_PROFILE #undef USE_COMPUTED_GOTOS +#define USE_COMPUTED_GOTOS 0 +#endif + +#ifdef HAVE_COMPUTED_GOTOS + #ifndef USE_COMPUTED_GOTOS + #define USE_COMPUTED_GOTOS 1 + #endif +#else + #if defined(USE_COMPUTED_GOTOS) && USE_COMPUTED_GOTOS + #error "Computed gotos are not supported on this compiler." + #endif + #undef USE_COMPUTED_GOTOS + #define USE_COMPUTED_GOTOS 0 #endif -#ifdef USE_COMPUTED_GOTOS +#if USE_COMPUTED_GOTOS /* Import the static jump table */ #include "opcode_targets.h" @@ -990,7 +1003,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) */ -#if defined(DYNAMIC_EXECUTION_PROFILE) || defined(USE_COMPUTED_GOTOS) +#if defined(DYNAMIC_EXECUTION_PROFILE) || USE_COMPUTED_GOTOS #define PREDICT(op) if (0) goto PRED_##op #define PREDICTED(op) PRED_##op: #define PREDICTED_WITH_ARG(op) PRED_##op: @@ -2838,7 +2851,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) oparg = oparg<<16 | NEXTARG(); goto dispatch_opcode; -#ifdef USE_COMPUTED_GOTOS +#if USE_COMPUTED_GOTOS _unknown_opcode: #endif default: -- cgit v1.2.1 From 40a356615f312ecac49e8415dce0406a14abccb4 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 14 Aug 2010 14:50:26 +0000 Subject: Issue #9425: Create private _Py_stat() function Use stat() or _wstat() depending on the OS. --- Python/import.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 4cdce74702..79a378e3c5 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1962,6 +1962,39 @@ case_ok(char *buf, Py_ssize_t len, Py_ssize_t namelen, char *name) #ifdef HAVE_STAT + +/* Call _wstat() on Windows, or stat() otherwise. Only fill st_mode + attribute on Windows. Return 0 on success, -1 on stat error or (if + PyErr_Occurred()) unicode error. */ + +int +_Py_stat(PyObject *unicode, struct stat *statbuf) +{ +#ifdef MS_WINDOWS + wchar_t path[MAXPATHLEN+1]; + Py_ssize_t len; + int err; + struct _stat wstatbuf; + + len = PyUnicode_AsWideChar((PyUnicodeObject*)unicode, path, + sizeof(path) / sizeof(path[0])); + if (len == -1) + return -1; + err = _wstat(path, &wstatbuf); + if (!err) + statbuf->st_mode = wstatbuf.st_mode; + return err; +#else + int ret; + PyObject *bytes = PyUnicode_EncodeFSDefault(unicode); + if (bytes == NULL) + return -1; + ret = stat(PyBytes_AS_STRING(bytes), statbuf); + Py_DECREF(bytes); + return ret; +#endif +} + /* Helper to look for __init__.py or __init__.py[co] in potential package */ static int find_init_module(char *buf) -- cgit v1.2.1 From 90a0012b66d904fca5938082c466d3fcc8932f21 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 14 Aug 2010 16:59:08 +0000 Subject: _Py_stat(): ensure that path ends with a nul character --- Python/import.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 79a378e3c5..84ddc03c52 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1976,10 +1976,11 @@ _Py_stat(PyObject *unicode, struct stat *statbuf) int err; struct _stat wstatbuf; - len = PyUnicode_AsWideChar((PyUnicodeObject*)unicode, path, - sizeof(path) / sizeof(path[0])); + len = PyUnicode_AsWideChar((PyUnicodeObject*)unicode, path, MAXPATHLEN); if (len == -1) return -1; + path[len] = L'\0'; + err = _wstat(path, &wstatbuf); if (!err) statbuf->st_mode = wstatbuf.st_mode; -- cgit v1.2.1 From dac1f8784805e12be45ced0d06e9668d932f6d3c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 14 Aug 2010 17:06:04 +0000 Subject: Create _Py_fopen() for PyUnicodeObject path Call _wfopen() on Windows, or fopen() otherwise. Return the new file object on success, or NULL if the file cannot be open or (if PyErr_Occurred()) on unicode error. --- Python/import.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 84ddc03c52..bb3756ef81 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1960,6 +1960,39 @@ case_ok(char *buf, Py_ssize_t len, Py_ssize_t namelen, char *name) #endif } +/* Call _wfopen() on Windows, or fopen() otherwise. Return the new file + object on success, or NULL if the file cannot be open or (if + PyErr_Occurred()) on unicode error */ + +FILE* +_Py_fopen(PyObject *unicode, const char *mode) +{ +#ifdef MS_WINDOWS + wchar_t path[MAXPATHLEN+1]; + wchar_t wmode[10]; + Py_ssize_t len; + int usize; + + len = PyUnicode_AsWideChar((PyUnicodeObject*)unicode, path, MAXPATHLEN); + if (len == -1) + return NULL; + path[len] = L'\0'; + + usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode, sizeof(wmode)); + if (usize == 0) + return NULL; + + return _wfopen(path, wmode); +#else + FILE *f; + PyObject *bytes = PyUnicode_EncodeFSDefault(unicode); + if (bytes == NULL) + return NULL; + f = fopen(PyBytes_AS_STRING(bytes), mode); + Py_DECREF(bytes); + return f; +#endif +} #ifdef HAVE_STAT -- cgit v1.2.1 From 041e14cd6ea8ec90303718040dd37ca558c77b14 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 16 Aug 2010 17:36:42 +0000 Subject: Issue #9599: Create PySys_FormatStdout() and PySys_FormatStderr() Write a message formatted by PyUnicode_FromFormatV() to sys.stdout and sys.stderr. --- Python/sysmodule.c | 82 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 67 insertions(+), 15 deletions(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 61c9b1ef33..7bf2c4c3b5 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1834,18 +1834,14 @@ PySys_SetArgv(int argc, wchar_t **argv) PyErr_CheckSignals(): avoid the call to PyObject_Str(). */ static int -sys_pyfile_write(const char *text, PyObject *file) +sys_pyfile_write_unicode(PyObject *unicode, PyObject *file) { - PyObject *unicode = NULL, *writer = NULL, *args = NULL, *result = NULL; + PyObject *writer = NULL, *args = NULL, *result = NULL; int err; if (file == NULL) return -1; - unicode = PyUnicode_FromString(text); - if (unicode == NULL) - goto error; - writer = PyObject_GetAttrString(file, "write"); if (writer == NULL) goto error; @@ -1865,13 +1861,29 @@ sys_pyfile_write(const char *text, PyObject *file) error: err = -1; finally: - Py_XDECREF(unicode); Py_XDECREF(writer); Py_XDECREF(args); Py_XDECREF(result); return err; } +static int +sys_pyfile_write(const char *text, PyObject *file) +{ + PyObject *unicode = NULL; + int err; + + if (file == NULL) + return -1; + + unicode = PyUnicode_FromString(text); + if (unicode == NULL) + return -1; + + err = sys_pyfile_write_unicode(unicode, file); + Py_DECREF(unicode); + return err; +} /* APIs to write to sys.stdout or sys.stderr using a printf-like interface. Adapted from code submitted by Just van Rossum. @@ -1884,8 +1896,8 @@ finally: no exceptions are raised. PyErr_CheckSignals() is not called to avoid the execution of the Python - signal handlers: they may raise a new exception whereas mywrite() ignores - all exceptions. + signal handlers: they may raise a new exception whereas sys_write() + ignores all exceptions. Both take a printf-style format string as their first argument followed by a variable length argument list determined by the format string. @@ -1902,7 +1914,7 @@ finally: */ static void -mywrite(char *name, FILE *fp, const char *format, va_list va) +sys_write(char *name, FILE *fp, const char *format, va_list va) { PyObject *file; PyObject *error_type, *error_value, *error_traceback; @@ -1918,10 +1930,8 @@ mywrite(char *name, FILE *fp, const char *format, va_list va) } if (written < 0 || (size_t)written >= sizeof(buffer)) { const char *truncated = "... truncated"; - if (sys_pyfile_write(truncated, file) != 0) { - PyErr_Clear(); + if (sys_pyfile_write(truncated, file) != 0) fputs(truncated, fp); - } } PyErr_Restore(error_type, error_value, error_traceback); } @@ -1932,7 +1942,7 @@ PySys_WriteStdout(const char *format, ...) va_list va; va_start(va, format); - mywrite("stdout", stdout, format, va); + sys_write("stdout", stdout, format, va); va_end(va); } @@ -1942,6 +1952,48 @@ PySys_WriteStderr(const char *format, ...) va_list va; va_start(va, format); - mywrite("stderr", stderr, format, va); + sys_write("stderr", stderr, format, va); + va_end(va); +} + +static void +sys_format(char *name, FILE *fp, const char *format, va_list va) +{ + PyObject *file, *message; + PyObject *error_type, *error_value, *error_traceback; + char *utf8; + + PyErr_Fetch(&error_type, &error_value, &error_traceback); + file = PySys_GetObject(name); + message = PyUnicode_FromFormatV(format, va); + if (message != NULL) { + if (sys_pyfile_write_unicode(message, file) != 0) { + PyErr_Clear(); + utf8 = _PyUnicode_AsString(message); + if (utf8 != NULL) + fputs(utf8, fp); + } + Py_DECREF(message); + } + PyErr_Restore(error_type, error_value, error_traceback); +} + +void +PySys_FormatStdout(const char *format, ...) +{ + va_list va; + + va_start(va, format); + sys_format("stdout", stdout, format, va); + va_end(va); +} + +void +PySys_FormatStderr(const char *format, ...) +{ + va_list va; + + va_start(va, format); + sys_format("stderr", stderr, format, va); va_end(va); } -- cgit v1.2.1 From 8007e7829c7c698c29c98dd592f79dbe00133ce6 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 17 Aug 2010 00:39:57 +0000 Subject: Issue #9425: save/restore exception on filename encoding _PyUnicode_AsString() raises an exception on unencodable filename. --- Python/ceval.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index c2c4e78f19..4d583a57de 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1213,7 +1213,12 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) lltrace = PyDict_GetItemString(f->f_globals, "__lltrace__") != NULL; #endif #if defined(Py_DEBUG) || defined(LLTRACE) - filename = _PyUnicode_AsString(co->co_filename); + { + PyObject *error_type, *error_value, *error_traceback; + PyErr_Fetch(&error_type, &error_value, &error_traceback); + filename = _PyUnicode_AsString(co->co_filename); + PyErr_Restore(error_type, error_value, error_traceback); + } #endif why = WHY_NOT; -- cgit v1.2.1 From 418baf91e4cc484cde0d8e8f54a406fddb47537e Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Tue, 17 Aug 2010 13:06:11 +0000 Subject: Issue #8202: Set sys.argv[0] to -m rather than -c while searching for the module to execute. Also updates all the cmd_line_script tests to validate the setting of sys.path[0] and the current working directory --- Python/sysmodule.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 7bf2c4c3b5..013f5f1a9b 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1723,6 +1723,10 @@ _wrealpath(const wchar_t *path, wchar_t *resolved_path) } #endif +#define _HAVE_SCRIPT_ARGUMENT(argc, argv) \ + (argc > 0 && argv0 != NULL && \ + wcscmp(argv0, L"-c") != 0 && wcscmp(argv0, L"-m") != 0) + void PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) { @@ -1747,7 +1751,7 @@ PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) wchar_t link[MAXPATHLEN+1]; wchar_t argv0copy[2*MAXPATHLEN+1]; int nr = 0; - if (argc > 0 && argv0 != NULL && wcscmp(argv0, L"-c") != 0) + if (_HAVE_SCRIPT_ARGUMENT(argc, argv)) nr = _Py_wreadlink(argv0, link, MAXPATHLEN); if (nr > 0) { /* It's a symlink */ @@ -1772,7 +1776,7 @@ PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) } #endif /* HAVE_READLINK */ #if SEP == '\\' /* Special case for MS filename syntax */ - if (argc > 0 && argv0 != NULL && wcscmp(argv0, L"-c") != 0) { + if (_HAVE_SCRIPT_ARGUMENT(argc, argv)) { wchar_t *q; #if defined(MS_WINDOWS) && !defined(MS_WINCE) /* This code here replaces the first element in argv with the full @@ -1798,7 +1802,7 @@ PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) } } #else /* All other filename syntaxes */ - if (argc > 0 && argv0 != NULL && wcscmp(argv0, L"-c") != 0) { + if (_HAVE_SCRIPT_ARGUMENT(argc, argv)) { #if defined(HAVE_REALPATH) if (_wrealpath(argv0, fullpath)) { argv0 = fullpath; -- cgit v1.2.1 From 32765cc90a223dc7c1434b716a9ee46e57a67f17 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 17 Aug 2010 22:26:51 +0000 Subject: Issue #8063: Call _PyGILState_Init() earlier in Py_InitializeEx(). --- Python/pythonrun.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index a7a54ba710..76a8eef2df 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -206,6 +206,11 @@ Py_InitializeEx(int install_sigs) Py_FatalError("Py_Initialize: can't make first thread"); (void) PyThreadState_Swap(tstate); + /* auto-thread-state API, if available */ +#ifdef WITH_THREAD + _PyGILState_Init(interp, tstate); +#endif /* WITH_THREAD */ + _Py_ReadyTypes(); if (!_PyFrame_Init()) @@ -288,11 +293,6 @@ Py_InitializeEx(int install_sigs) Py_FatalError( "Py_Initialize: can't initialize sys standard streams"); - /* auto-thread-state API, if available */ -#ifdef WITH_THREAD - _PyGILState_Init(interp, tstate); -#endif /* WITH_THREAD */ - if (!Py_NoSiteFlag) initsite(); /* Module site */ } -- cgit v1.2.1 From 983ba554bb9c7ce7c0e8c276fded82b44a50465a Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 17 Aug 2010 22:54:21 +0000 Subject: Remove unused functions _PyImport_FindModule and _PyImport_IsScript --- Python/import.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index bb3756ef81..a5277af938 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1790,22 +1790,6 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, 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 -- cgit v1.2.1 From eed5e45dca43ab6cf3424e21b30e2c775d292e77 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 18 Aug 2010 21:23:25 +0000 Subject: Issue #8622: Add PYTHONFSENCODING environment variable to override the filesystem encoding. initfsencoding() displays also a better error message if get_codeset() failed. --- Python/pythonrun.c | 65 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 22 deletions(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 76a8eef2df..fd31974cb8 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -134,18 +134,13 @@ add_flag(int flag, const char *envs) return flag; } -#if defined(HAVE_LANGINFO_H) && defined(CODESET) static char* -get_codeset(void) +get_codec_name(const char *encoding) { - char* codeset, *name_str; + char *name_utf8, *name_str; PyObject *codec, *name = NULL; - codeset = nl_langinfo(CODESET); - if (!codeset || codeset[0] == '\0') - return NULL; - - codec = _PyCodec_Lookup(codeset); + codec = _PyCodec_Lookup(encoding); if (!codec) goto error; @@ -154,18 +149,34 @@ get_codeset(void) if (!name) goto error; - name_str = _PyUnicode_AsString(name); + name_utf8 = _PyUnicode_AsString(name); if (name == NULL) goto error; - codeset = strdup(name_str); + name_str = strdup(name_utf8); Py_DECREF(name); - return codeset; + if (name_str == NULL) { + PyErr_NoMemory(); + return NULL; + } + return name_str; error: Py_XDECREF(codec); Py_XDECREF(name); return NULL; } + +#if defined(HAVE_LANGINFO_H) && defined(CODESET) +static char* +get_codeset(void) +{ + char* codeset = nl_langinfo(CODESET); + if (!codeset || codeset[0] == '\0') { + PyErr_SetString(PyExc_ValueError, "CODESET is not set or empty"); + return NULL; + } + return get_codec_name(codeset); +} #endif void @@ -706,25 +717,35 @@ initfsencoding(void) { PyObject *codec; #if defined(HAVE_LANGINFO_H) && defined(CODESET) - char *codeset; + char *codeset = NULL; if (Py_FileSystemDefaultEncoding == NULL) { - /* 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. */ - codeset = get_codeset(); + const char *env_encoding = Py_GETENV("PYTHONFSENCODING"); + if (env_encoding != NULL) { + codeset = get_codec_name(env_encoding); + if (!codeset) { + fprintf(stderr, "PYTHONFSENCODING is not a valid encoding:\n"); + PyErr_Print(); + } + } + if (!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. */ + codeset = get_codeset(); + } if (codeset != NULL) { Py_FileSystemDefaultEncoding = codeset; Py_HasFileSystemDefaultEncoding = 0; return; + } else { + fprintf(stderr, "Unable to get the locale encoding:\n"); + PyErr_Print(); } - PyErr_Clear(); - fprintf(stderr, - "Unable to get the locale encoding: " - "fallback to utf-8\n"); + fprintf(stderr, "Unable to get the filesystem encoding: fallback to utf-8\n"); Py_FileSystemDefaultEncoding = "utf-8"; Py_HasFileSystemDefaultEncoding = 1; } -- cgit v1.2.1 From cca93ba2bbe772b1e6b6982b3933f0532edbe2d1 Mon Sep 17 00:00:00 2001 From: Amaury Forgeot d'Arc Date: Thu, 19 Aug 2010 17:43:15 +0000 Subject: Check the return values for all functions returning an ast node. Failure to do it may result in strange error messages or even crashes, in admittedly convoluted cases that are normally syntax errors, like: def f(*xx, __debug__): pass --- Python/ast.c | 53 +++++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 26 deletions(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index 34dc30f04d..6ea830b8af 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -688,6 +688,8 @@ handle_keywordonly_args(struct compiling *c, const node *n, int start, case tfpdef: if (i + 1 < NCH(n) && TYPE(CHILD(n, i + 1)) == EQUAL) { expression = ast_for_expr(c, CHILD(n, i + 2)); + if (!expression) + goto error; asdl_seq_SET(kwdefaults, j, expression); i += 2; /* '=' and test */ } @@ -697,10 +699,8 @@ handle_keywordonly_args(struct compiling *c, const node *n, int start, if (NCH(ch) == 3) { /* ch is NAME ':' test */ annotation = ast_for_expr(c, CHILD(ch, 2)); - if (!annotation) { - ast_error(ch, "expected expression"); + if (!annotation) goto error; - } } else { annotation = NULL; @@ -794,22 +794,22 @@ ast_for_arguments(struct compiling *c, const node *n) } posargs = (nposargs ? asdl_seq_new(nposargs, c->c_arena) : NULL); if (!posargs && nposargs) - goto error; + return NULL; kwonlyargs = (nkwonlyargs ? asdl_seq_new(nkwonlyargs, c->c_arena) : NULL); if (!kwonlyargs && nkwonlyargs) - goto error; + return NULL; posdefaults = (nposdefaults ? asdl_seq_new(nposdefaults, c->c_arena) : NULL); if (!posdefaults && nposdefaults) - goto error; + return NULL; /* The length of kwonlyargs and kwdefaults are same since we set NULL as default for keyword only argument w/o default - we have sequence data structure, but no dictionary */ kwdefaults = (nkwonlyargs ? asdl_seq_new(nkwonlyargs, c->c_arena) : NULL); if (!kwdefaults && nkwonlyargs) - goto error; + return NULL; if (nposargs + nkwonlyargs > 255) { ast_error(n, "more than 255 arguments"); @@ -833,7 +833,7 @@ ast_for_arguments(struct compiling *c, const node *n) 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; + return NULL; assert(posdefaults != NULL); asdl_seq_SET(posdefaults, j++, expression); i += 2; @@ -842,11 +842,11 @@ ast_for_arguments(struct compiling *c, const node *n) else if (found_default) { ast_error(n, "non-default argument follows default argument"); - goto error; + return NULL; } arg = compiler_arg(c, ch); if (!arg) - goto error; + return NULL; asdl_seq_SET(posargs, k++, arg); i += 2; /* the name and the comma */ break; @@ -854,7 +854,7 @@ ast_for_arguments(struct compiling *c, const node *n) if (i+1 >= NCH(n)) { ast_error(CHILD(n, i), "named arguments must follow bare *"); - goto error; + return NULL; } ch = CHILD(n, i+1); /* tfpdef or COMMA */ if (TYPE(ch) == COMMA) { @@ -862,7 +862,7 @@ ast_for_arguments(struct compiling *c, const node *n) i += 2; /* now follows keyword only arguments */ res = handle_keywordonly_args(c, n, i, kwonlyargs, kwdefaults); - if (res == -1) goto error; + if (res == -1) return NULL; i = res; /* res has new position to process */ } else { @@ -874,6 +874,8 @@ ast_for_arguments(struct compiling *c, const node *n) if (NCH(ch) > 1) { /* there is an annotation on the vararg */ varargannotation = ast_for_expr(c, CHILD(ch, 2)); + if (!varargannotation) + return NULL; } i += 3; if (i < NCH(n) && (TYPE(CHILD(n, i)) == tfpdef @@ -881,7 +883,7 @@ ast_for_arguments(struct compiling *c, const node *n) int res = 0; res = handle_keywordonly_args(c, n, i, kwonlyargs, kwdefaults); - if (res == -1) goto error; + if (res == -1) return NULL; i = res; /* res has new position to process */ } } @@ -893,26 +895,24 @@ ast_for_arguments(struct compiling *c, const node *n) if (NCH(ch) > 1) { /* there is an annotation on the kwarg */ kwargannotation = ast_for_expr(c, CHILD(ch, 2)); + if (!kwargannotation) + return NULL; } if (!kwarg) - goto error; + return NULL; if (forbidden_name(kwarg, CHILD(ch, 0), 0)) - goto error; + return NULL; i += 3; break; default: PyErr_Format(PyExc_SystemError, "unexpected node in varargslist: %d @ %d", TYPE(ch), i); - goto error; + return NULL; } } return arguments(posargs, vararg, varargannotation, kwonlyargs, kwarg, kwargannotation, posdefaults, kwdefaults, c->c_arena); - error: - Py_XDECREF(vararg); - Py_XDECREF(kwarg); - return NULL; } static expr_ty @@ -997,9 +997,9 @@ ast_for_decorators(struct compiling *c, const node *n) 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); + if (!d) + return NULL; + asdl_seq_SET(decorator_seq, i, d); } return decorator_seq; } @@ -1027,7 +1027,7 @@ ast_for_funcdef(struct compiling *c, const node *n, asdl_seq *decorator_seq) if (TYPE(CHILD(n, name_i+2)) == RARROW) { returns = ast_for_expr(c, CHILD(n, name_i + 3)); if (!returns) - return NULL; + return NULL; name_i += 2; } body = ast_for_suite(c, CHILD(n, name_i + 3)); @@ -2136,11 +2136,10 @@ ast_for_expr_stmt(struct compiling *c, const node *n) return NULL; } e = ast_for_testlist(c, ch); - - /* set context to assign */ if (!e) return NULL; + /* set context to assign */ if (!set_context(c, e, Store, CHILD(n, i))) return NULL; @@ -2960,6 +2959,8 @@ ast_for_with_item(struct compiling *c, const node *n, asdl_seq *content) REQ(n, with_item); context_expr = ast_for_expr(c, CHILD(n, 0)); + if (!context_expr) + return NULL; if (NCH(n) == 3) { optional_vars = ast_for_expr(c, CHILD(n, 2)); -- cgit v1.2.1 From 79af57d60b94325a98a0b602e8cf06f5c9dafd6b Mon Sep 17 00:00:00 2001 From: Amaury Forgeot d'Arc Date: Thu, 19 Aug 2010 21:32:38 +0000 Subject: Add tests for r84209 (crashes in the Ast builder) Also remove one tab, and move a check closer to the possible failure. --- Python/ast.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index 6ea830b8af..9f6b7eaa8a 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -689,7 +689,7 @@ handle_keywordonly_args(struct compiling *c, const node *n, int start, if (i + 1 < NCH(n) && TYPE(CHILD(n, i + 1)) == EQUAL) { expression = ast_for_expr(c, CHILD(n, i + 2)); if (!expression) - goto error; + goto error; asdl_seq_SET(kwdefaults, j, expression); i += 2; /* '=' and test */ } @@ -892,14 +892,14 @@ ast_for_arguments(struct compiling *c, const node *n) ch = CHILD(n, i+1); /* tfpdef */ assert(TYPE(ch) == tfpdef || TYPE(ch) == vfpdef); kwarg = NEW_IDENTIFIER(CHILD(ch, 0)); + if (!kwarg) + return NULL; if (NCH(ch) > 1) { /* there is an annotation on the kwarg */ kwargannotation = ast_for_expr(c, CHILD(ch, 2)); if (!kwargannotation) return NULL; } - if (!kwarg) - return NULL; if (forbidden_name(kwarg, CHILD(ch, 0), 0)) return NULL; i += 3; -- cgit v1.2.1 From 0852a8452e7c0f80673eec63cad6c2ec9d35d875 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Sun, 22 Aug 2010 08:39:49 +0000 Subject: Issue 8403: Don't mask KeyboardInterrupt during peephole operation. --- Python/peephole.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/peephole.c b/Python/peephole.c index 7deb02d267..9d06963e2c 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -159,13 +159,16 @@ fold_binops_on_constants(unsigned char *codestr, PyObject *consts) return 0; } if (newconst == NULL) { - PyErr_Clear(); + if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) + PyErr_Clear(); return 0; } size = PyObject_Size(newconst); - if (size == -1) + if (size == -1) { + if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) + return 0; PyErr_Clear(); - else if (size > 20) { + } else if (size > 20) { Py_DECREF(newconst); return 0; } @@ -219,7 +222,8 @@ fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts) return 0; } if (newconst == NULL) { - PyErr_Clear(); + if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) + PyErr_Clear(); return 0; } -- cgit v1.2.1 From f79f35834324009de149fb0f3b0d2b43cce54ea7 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 24 Aug 2010 03:26:23 +0000 Subject: only catch AttributeError in hasattr() #9666 --- Python/bltinmodule.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index e1f2931dbc..3bcb08ee98 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -893,24 +893,21 @@ builtin_hasattr(PyObject *self, PyObject *args) } v = PyObject_GetAttr(v, name); if (v == NULL) { - if (!PyErr_ExceptionMatches(PyExc_Exception)) - return NULL; - else { + if (PyErr_ExceptionMatches(PyExc_AttributeError)) { PyErr_Clear(); - Py_INCREF(Py_False); - return Py_False; + Py_RETURN_FALSE; } + return NULL; } Py_DECREF(v); - Py_INCREF(Py_True); - return Py_True; + Py_RETURN_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.)"); +(This is done by calling getattr(object, name) and catching AttributeError.)"); static PyObject * -- cgit v1.2.1 From dbbf653e5e7d790fce009f7c31b6ebbdc408b938 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Wed, 1 Sep 2010 18:54:56 +0000 Subject: Issue #9549: sys.setdefaultencoding() and PyUnicode_SetDefaultEncoding() are now removed, since their effect was inexistent in 3.x (the default encoding is hardcoded to utf-8 and cannot be changed). --- Python/sysmodule.c | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 013f5f1a9b..90c165a495 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -182,24 +182,6 @@ 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) { @@ -1030,8 +1012,6 @@ static PyMethodDef sys_methods[] = { #ifdef USE_MALLOPT {"mdebug", sys_mdebug, METH_VARARGS}, #endif - {"setdefaultencoding", sys_setdefaultencoding, METH_VARARGS, - setdefaultencoding_doc}, {"setfilesystemencoding", sys_setfilesystemencoding, METH_VARARGS, setfilesystemencoding_doc}, {"setcheckinterval", sys_setcheckinterval, METH_VARARGS, -- cgit v1.2.1 From 14abf7e7923e89d83a7e5dbe495355f7127f1e31 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Fri, 3 Sep 2010 18:30:30 +0000 Subject: PEP 3149 is accepted. http://mail.python.org/pipermail/python-dev/2010-September/103408.html --- Python/dynload_shlib.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'Python') diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c index 87dae27ed4..04542c9cd2 100644 --- a/Python/dynload_shlib.c +++ b/Python/dynload_shlib.c @@ -30,27 +30,34 @@ #define LEAD_UNDERSCORE "" #endif +/* The .so extension module ABI tag, supplied by the Makefile via + Makefile.pre.in and configure. This is used to discriminate between + incompatible .so files so that extensions for different Python builds can + live in the same directory. E.g. foomodule.cpython-32.so +*/ const struct filedescr _PyImport_DynLoadFiletab[] = { #ifdef __CYGWIN__ {".dll", "rb", C_EXTENSION}, {"module.dll", "rb", C_EXTENSION}, -#else +#else /* !__CYGWIN__ */ #if defined(PYOS_OS2) && defined(PYCC_GCC) {".pyd", "rb", C_EXTENSION}, {".dll", "rb", C_EXTENSION}, -#else +#else /* !(defined(PYOS_OS2) && defined(PYCC_GCC)) */ #ifdef __VMS {".exe", "rb", C_EXTENSION}, {".EXE", "rb", C_EXTENSION}, {"module.exe", "rb", C_EXTENSION}, {"MODULE.EXE", "rb", C_EXTENSION}, -#else +#else /* !__VMS */ + {"." SOABI ".so", "rb", C_EXTENSION}, {".so", "rb", C_EXTENSION}, + {"module." SOABI ".so", "rb", C_EXTENSION}, {"module.so", "rb", C_EXTENSION}, -#endif -#endif -#endif +#endif /* __VMS */ +#endif /* defined(PYOS_OS2) && defined(PYCC_GCC) */ +#endif /* __CYGWIN__ */ {0, 0} }; -- cgit v1.2.1 From 23fb3f8d60e6a1fc1d3a4925f6f652539af5ceac Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Sat, 4 Sep 2010 18:24:04 +0000 Subject: _warnings exposed two variables with the name 'default_action' and 'once_registry'. This is bad as the warnings module had variables named 'defaultaction' and 'onceregistry' which are what people should be looking at (technically those variables shouldn't be mucked with as they are undocumented, but we all know better than to believe that isn't happening). So the variables from _warnings have been renamed to come off as private and to avoid confusion over what variable should be used. Closes issue #9766. Thanks to Antoine Pitrou for the discovery. --- Python/_warnings.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/_warnings.c b/Python/_warnings.c index 63bcbffea9..a4e9d48e8e 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -945,13 +945,13 @@ _PyWarnings_Init(void) if (_once_registry == NULL) return NULL; Py_INCREF(_once_registry); - if (PyModule_AddObject(m, "once_registry", _once_registry) < 0) + if (PyModule_AddObject(m, "_onceregistry", _once_registry) < 0) return NULL; _default_action = PyUnicode_FromString("default"); if (_default_action == NULL) return NULL; - if (PyModule_AddObject(m, "default_action", _default_action) < 0) + if (PyModule_AddObject(m, "_defaultaction", _default_action) < 0) return NULL; return m; } -- cgit v1.2.1 From 6b5b7721253d41df7f38576e7874e79e1f8c0ee3 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sat, 4 Sep 2010 18:43:52 +0000 Subject: Issue #9225: Remove the ROT_FOUR and DUP_TOPX opcode, the latter replaced by the new (and simpler) DUP_TOP_TWO. Performance isn't changed, but our bytecode is a bit simplified. Patch by Demur Rumed. --- Python/ceval.c | 47 +++++++++-------------------------------------- Python/compile.c | 8 +++----- Python/import.c | 4 +++- Python/opcode_targets.h | 4 ++-- 4 files changed, 17 insertions(+), 46 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 4d583a57de..1f78f95b49 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1420,50 +1420,21 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) SET_THIRD(v); FAST_DISPATCH(); - TARGET(ROT_FOUR) - u = TOP(); - v = SECOND(); - w = THIRD(); - x = FOURTH(); - SET_TOP(v); - SET_SECOND(w); - SET_THIRD(x); - SET_FOURTH(u); - FAST_DISPATCH(); - TARGET(DUP_TOP) v = TOP(); Py_INCREF(v); PUSH(v); FAST_DISPATCH(); - TARGET(DUP_TOPX) - if (oparg == 2) { - x = TOP(); - Py_INCREF(x); - w = SECOND(); - Py_INCREF(w); - STACKADJ(2); - SET_TOP(x); - SET_SECOND(w); - FAST_DISPATCH(); - } 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); - FAST_DISPATCH(); - } - Py_FatalError("invalid argument to DUP_TOPX" - " (bytecode corruption?)"); - /* Never returns, so don't bother to set why. */ - break; + TARGET(DUP_TOP_TWO) + x = TOP(); + Py_INCREF(x); + w = SECOND(); + Py_INCREF(w); + STACKADJ(2); + SET_TOP(x); + SET_SECOND(w); + FAST_DISPATCH(); TARGET(UNARY_POSITIVE) v = TOP(); diff --git a/Python/compile.c b/Python/compile.c index aae0339c2c..6963a151a7 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -680,8 +680,8 @@ opcode_stack_effect(int opcode, int oparg) return 0; case DUP_TOP: return 1; - case ROT_FOUR: - return 0; + case DUP_TOP_TWO: + return 2; case UNARY_POSITIVE: case UNARY_NEGATIVE: @@ -782,8 +782,6 @@ opcode_stack_effect(int opcode, int oparg) return -1; case DELETE_GLOBAL: return 0; - case DUP_TOPX: - return oparg; case LOAD_CONST: return 1; case LOAD_NAME: @@ -3404,7 +3402,7 @@ compiler_handle_subscr(struct compiler *c, const char *kind, return 0; } if (ctx == AugLoad) { - ADDOP_I(c, DUP_TOPX, 2); + ADDOP(c, DUP_TOP_TWO); } else if (ctx == AugStore) { ADDOP(c, ROT_THREE); diff --git a/Python/import.c b/Python/import.c index a5277af938..d6b19e8f97 100644 --- a/Python/import.c +++ b/Python/import.c @@ -101,12 +101,14 @@ typedef unsigned short mode_t; introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE) Python 3.2a0: 3160 (add SETUP_WITH) tag: cpython-32 + Python 3.2a1: 3170 (add DUP_TOP_TWO, remove DUP_TOPX and ROT_FOUR) + tag: cpython-32 */ /* If you change MAGIC, you must change TAG and you must insert the old value into _PyMagicNumberTags below. */ -#define MAGIC (3160 | ((long)'\r'<<16) | ((long)'\n'<<24)) +#define MAGIC (3170 | ((long)'\r'<<16) | ((long)'\n'<<24)) #define TAG "cpython-32" #define CACHEDIR "__pycache__" /* Current magic word and string tag as globals. */ diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 20c9f258e4..8b59c2db78 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -4,7 +4,7 @@ static void *opcode_targets[256] = { &&TARGET_ROT_TWO, &&TARGET_ROT_THREE, &&TARGET_DUP_TOP, - &&TARGET_ROT_FOUR, + &&TARGET_DUP_TOP_TWO, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, @@ -98,7 +98,7 @@ static void *opcode_targets[256] = { &&TARGET_DELETE_ATTR, &&TARGET_STORE_GLOBAL, &&TARGET_DELETE_GLOBAL, - &&TARGET_DUP_TOPX, + &&_unknown_opcode, &&TARGET_LOAD_CONST, &&TARGET_LOAD_NAME, &&TARGET_BUILD_TUPLE, -- cgit v1.2.1 From 57327a9e22ba35691e056d0b9783ef7b5e8197d3 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Wed, 8 Sep 2010 12:37:10 +0000 Subject: Issue #9797: pystate.c wrongly assumed that zero couldn't be a valid thread-local storage key. --- Python/pystate.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'Python') diff --git a/Python/pystate.c b/Python/pystate.c index f113839ef0..77534fc12f 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -340,7 +340,7 @@ PyThreadState_Delete(PyThreadState *tstate) Py_FatalError("PyThreadState_Delete: tstate is still current"); tstate_delete_common(tstate); #ifdef WITH_THREAD - if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate) + if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate) PyThread_delete_key_value(autoTLSkey); #endif /* WITH_THREAD */ } @@ -357,7 +357,7 @@ PyThreadState_DeleteCurrent() "PyThreadState_DeleteCurrent: no current tstate"); _Py_atomic_store_relaxed(&_PyThreadState_Current, NULL); tstate_delete_common(tstate); - if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate) + if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate) PyThread_delete_key_value(autoTLSkey); PyEval_ReleaseLock(); } @@ -580,7 +580,6 @@ void _PyGILState_Fini(void) { PyThread_delete_key(autoTLSkey); - autoTLSkey = 0; autoInterpreterState = NULL; } @@ -592,10 +591,10 @@ _PyGILState_Fini(void) static void _PyGILState_NoteThreadState(PyThreadState* tstate) { - /* If autoTLSkey is 0, this must be the very first threadstate created - in Py_Initialize(). Don't do anything for now (we'll be back here - when _PyGILState_Init is called). */ - if (!autoTLSkey) + /* If autoTLSkey isn't initialized, this must be the very first + threadstate created in Py_Initialize(). Don't do anything for now + (we'll be back here when _PyGILState_Init is called). */ + if (!autoInterpreterState) return; /* Stick the thread state for this thread in thread local storage. @@ -623,7 +622,7 @@ _PyGILState_NoteThreadState(PyThreadState* tstate) PyThreadState * PyGILState_GetThisThreadState(void) { - if (autoInterpreterState == NULL || autoTLSkey == 0) + if (autoInterpreterState == NULL) return NULL; return (PyThreadState *)PyThread_get_key_value(autoTLSkey); } -- cgit v1.2.1 From c12f007578d4ecacd6559bb4982ab6f59c93d033 Mon Sep 17 00:00:00 2001 From: Matthias Klose Date: Wed, 8 Sep 2010 16:22:10 +0000 Subject: PEP 3149: Try to load the extension with the SOABI before trying to load the one without the SOABI in the name. --- Python/dynload_shlib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c index 04542c9cd2..3d0fb5eb01 100644 --- a/Python/dynload_shlib.c +++ b/Python/dynload_shlib.c @@ -52,8 +52,8 @@ const struct filedescr _PyImport_DynLoadFiletab[] = { {"MODULE.EXE", "rb", C_EXTENSION}, #else /* !__VMS */ {"." SOABI ".so", "rb", C_EXTENSION}, - {".so", "rb", C_EXTENSION}, {"module." SOABI ".so", "rb", C_EXTENSION}, + {".so", "rb", C_EXTENSION}, {"module.so", "rb", C_EXTENSION}, #endif /* __VMS */ #endif /* defined(PYOS_OS2) && defined(PYCC_GCC) */ -- cgit v1.2.1 From 8d57968c6536b8c2e2a510a003eae808b2691a8c Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Thu, 9 Sep 2010 20:30:23 +0000 Subject: Issue #9804: ascii() now always represents unicode surrogate pairs as a single `\UXXXXXXXX`, regardless of whether the character is printable or not. Also, the "backslashreplace" error handler now joins surrogate pairs into a single character on UCS-2 builds. --- Python/codecs.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'Python') diff --git a/Python/codecs.c b/Python/codecs.c index 04487a216c..45d99291f1 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -678,6 +678,13 @@ static Py_UNICODE hexdigits[] = { PyObject *PyCodec_BackslashReplaceErrors(PyObject *exc) { +#ifndef Py_UNICODE_WIDE +#define IS_SURROGATE_PAIR(p, end) \ + (*p >= 0xD800 && *p <= 0xDBFF && (p + 1) < end && \ + *(p + 1) >= 0xDC00 && *(p + 1) <= 0xDFFF) +#else +#define IS_SURROGATE_PAIR(p, end) 0 +#endif if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { PyObject *restuple; PyObject *object; @@ -702,7 +709,12 @@ PyObject *PyCodec_BackslashReplaceErrors(PyObject *exc) else #endif if (*p >= 0x100) { - ressize += 1+1+4; + if (IS_SURROGATE_PAIR(p, startp+end)) { + ressize += 1+1+8; + ++p; + } + else + ressize += 1+1+4; } else ressize += 1+1+2; @@ -712,9 +724,12 @@ PyObject *PyCodec_BackslashReplaceErrors(PyObject *exc) return NULL; for (p = startp+start, outp = PyUnicode_AS_UNICODE(res); p < startp+end; ++p) { - Py_UNICODE c = *p; + Py_UCS4 c = (Py_UCS4) *p; *outp++ = '\\'; -#ifdef Py_UNICODE_WIDE + if (IS_SURROGATE_PAIR(p, startp+end)) { + c = ((*p & 0x3FF) << 10) + (*(p + 1) & 0x3FF) + 0x10000; + ++p; + } if (c >= 0x00010000) { *outp++ = 'U'; *outp++ = hexdigits[(c>>28)&0xf]; @@ -724,9 +739,7 @@ PyObject *PyCodec_BackslashReplaceErrors(PyObject *exc) *outp++ = hexdigits[(c>>12)&0xf]; *outp++ = hexdigits[(c>>8)&0xf]; } - else -#endif - if (c >= 0x100) { + else if (c >= 0x100) { *outp++ = 'u'; *outp++ = hexdigits[(c>>12)&0xf]; *outp++ = hexdigits[(c>>8)&0xf]; @@ -746,6 +759,7 @@ PyObject *PyCodec_BackslashReplaceErrors(PyObject *exc) wrong_exception_type(exc); return NULL; } +#undef IS_SURROGATE_PAIR } /* This handler is declared static until someone demonstrates -- cgit v1.2.1 From 7cbaf55a5ff662a340506a5622b8f4362b4bf97b Mon Sep 17 00:00:00 2001 From: Daniel Stutzbach Date: Thu, 9 Sep 2010 21:18:04 +0000 Subject: Fix Issue #9752: MSVC compiler warning due to undefined function (Patch by Jon Anglin) --- Python/import.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index d6b19e8f97..d79fc52261 100644 --- a/Python/import.c +++ b/Python/import.c @@ -25,6 +25,8 @@ extern "C" { #ifdef MS_WINDOWS /* for stat.st_mode */ typedef unsigned short mode_t; +/* for _mkdir */ +#include #endif @@ -1134,9 +1136,6 @@ write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat) time_t mtime = srcstat->st_mtime; #ifdef MS_WINDOWS /* since Windows uses different permissions */ mode_t mode = srcstat->st_mode & ~S_IEXEC; - mode_t dirmode = srcstat->st_mode | S_IEXEC; /* XXX Is this correct - for Windows? - 2010-04-07 BAW */ #else mode_t mode = srcstat->st_mode & ~S_IXUSR & ~S_IXGRP & ~S_IXOTH; mode_t dirmode = (srcstat->st_mode | @@ -1156,8 +1155,12 @@ write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat) } saved = *dirpath; *dirpath = '\0'; - /* XXX call os.mkdir() or maybe CreateDirectoryA() on Windows? */ + +#ifdef MS_WINDOWS + if (_mkdir(cpathname) < 0 && errno != EEXIST) { +#else if (mkdir(cpathname, dirmode) < 0 && errno != EEXIST) { +#endif *dirpath = saved; if (Py_VerboseFlag) PySys_WriteStderr( -- cgit v1.2.1 From f4136c2c8d5c2470640d04074c10b9e576c0e4fb Mon Sep 17 00:00:00 2001 From: Amaury Forgeot d'Arc Date: Fri, 10 Sep 2010 21:39:53 +0000 Subject: #4617: Previously it was illegal to delete a name from the local namespace if it occurs as a free variable in a nested block. This limitation of the compiler has been lifted, and a new opcode introduced (DELETE_DEREF). This sample was valid in 2.6, but fails to compile in 3.x without this change:: >>> def f(): ... def print_error(): ... print(e) ... try: ... something ... except Exception as e: ... print_error() ... # implicit "del e" here This sample has always been invalid in Python, and now works:: >>> def outer(x): ... def inner(): ... return x ... inner() ... del x There is no need to bump the PYC magic number: the new opcode is used for code that did not compile before. --- Python/ceval.c | 50 +++++++++++++++++++++++++++++++++---------------- Python/compile.c | 10 +++------- Python/opcode_targets.h | 2 +- 3 files changed, 38 insertions(+), 24 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 1f78f95b49..f0d278c564 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -135,6 +135,7 @@ static PyObject * cmp_outcome(int, PyObject *, PyObject *); static PyObject * import_from(PyObject *, PyObject *); static int import_all_from(PyObject *, PyObject *); static void format_exc_check_arg(PyObject *, const char *, PyObject *); +static void format_exc_unbound(PyCodeObject *co, int oparg); static PyObject * unicode_concatenate(PyObject *, PyObject *, PyFrameObject *, unsigned char *); static PyObject * special_lookup(PyObject *, char *, PyObject **); @@ -2143,6 +2144,16 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) ); break; + TARGET(DELETE_DEREF) + x = freevars[oparg]; + if (PyCell_GET(x) != NULL) { + PyCell_Set(x, NULL); + continue; + } + err = -1; + format_exc_unbound(co, oparg); + break; + TARGET(LOAD_CLOSURE) x = freevars[oparg]; Py_INCREF(x); @@ -2158,22 +2169,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) DISPATCH(); } 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); - } + format_exc_unbound(co, oparg); break; TARGET(STORE_DEREF) @@ -4352,6 +4348,28 @@ format_exc_check_arg(PyObject *exc, const char *format_str, PyObject *obj) PyErr_Format(exc, format_str, obj_str); } +static void +format_exc_unbound(PyCodeObject *co, int oparg) +{ + PyObject *name; + /* Don't stomp existing exception */ + if (PyErr_Occurred()) + return; + if (oparg < PyTuple_GET_SIZE(co->co_cellvars)) { + name = PyTuple_GET_ITEM(co->co_cellvars, + oparg); + format_exc_check_arg( + PyExc_UnboundLocalError, + UNBOUNDLOCAL_ERROR_MSG, + name); + } else { + name = PyTuple_GET_ITEM(co->co_freevars, oparg - + PyTuple_GET_SIZE(co->co_cellvars)); + format_exc_check_arg(PyExc_NameError, + UNBOUNDFREE_ERROR_MSG, name); + } +} + static PyObject * unicode_concatenate(PyObject *v, PyObject *w, PyFrameObject *f, unsigned char *next_instr) diff --git a/Python/compile.c b/Python/compile.c index 6963a151a7..5341e6b535 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -857,6 +857,8 @@ opcode_stack_effect(int opcode, int oparg) return 1; case STORE_DEREF: return -1; + case DELETE_DEREF: + return 0; default: fprintf(stderr, "opcode = %d\n", opcode); Py_FatalError("opcode_stack_effect()"); @@ -2506,13 +2508,7 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) case AugLoad: case AugStore: break; - case Del: - PyErr_Format(PyExc_SyntaxError, - "can not delete variable '%S' referenced " - "in nested scope", - name); - Py_DECREF(mangled); - return 0; + case Del: op = DELETE_DEREF; break; case Param: default: PyErr_SetString(PyExc_SystemError, diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 8b59c2db78..a91da79be6 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -137,7 +137,7 @@ static void *opcode_targets[256] = { &&TARGET_LOAD_CLOSURE, &&TARGET_LOAD_DEREF, &&TARGET_STORE_DEREF, - &&_unknown_opcode, + &&TARGET_DELETE_DEREF, &&_unknown_opcode, &&TARGET_CALL_FUNCTION_VAR, &&TARGET_CALL_FUNCTION_KW, -- cgit v1.2.1 From ba1a29639db0d619e8df52c246365918ee5f0da5 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 10 Sep 2010 21:51:44 +0000 Subject: bump magic number for DELETE_DEREF --- Python/import.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index d79fc52261..f5bc03ddd8 100644 --- a/Python/import.c +++ b/Python/import.c @@ -105,12 +105,13 @@ typedef unsigned short mode_t; tag: cpython-32 Python 3.2a1: 3170 (add DUP_TOP_TWO, remove DUP_TOPX and ROT_FOUR) tag: cpython-32 + Python 3.2a2 3180 (add DELETE_DEREF) */ /* If you change MAGIC, you must change TAG and you must insert the old value into _PyMagicNumberTags below. */ -#define MAGIC (3170 | ((long)'\r'<<16) | ((long)'\n'<<24)) +#define MAGIC (3180 | ((long)'\r'<<16) | ((long)'\n'<<24)) #define TAG "cpython-32" #define CACHEDIR "__pycache__" /* Current magic word and string tag as globals. */ -- cgit v1.2.1 From 1658cfd89d09782b7499d0e4a0daa56d5ed6b5b6 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 10 Sep 2010 21:57:59 +0000 Subject: Issue #9632: Remove sys.setfilesystemencoding() function: use PYTHONFSENCODING environment variable to set the filesystem encoding at Python startup. sys.setfilesystemencoding() creates inconsistencies because it is unable to reencode all filenames in all objects. --- Python/bltinmodule.c | 23 ----------------------- Python/sysmodule.c | 21 --------------------- 2 files changed, 44 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 3bcb08ee98..60bceb7581 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -33,29 +33,6 @@ const char *Py_FileSystemDefaultEncoding = "utf-8"; int Py_HasFileSystemDefaultEncoding = 1; #endif -int -_Py_SetFileSystemEncoding(PyObject *s) -{ - PyObject *defenc, *codec; - if (!PyUnicode_Check(s)) { - PyErr_BadInternalCall(); - return -1; - } - defenc = _PyUnicode_AsDefaultEncodedString(s, NULL); - if (!defenc) - return -1; - codec = _PyCodec_Lookup(PyBytes_AsString(defenc)); - if (codec == NULL) - return -1; - Py_DECREF(codec); - if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) - /* A file system encoding was set at run-time */ - free((char*)Py_FileSystemDefaultEncoding); - Py_FileSystemDefaultEncoding = strdup(PyBytes_AsString(defenc)); - Py_HasFileSystemDefaultEncoding = 0; - return 0; -} - static PyObject * builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) { diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 90c165a495..4e428f0171 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -198,25 +198,6 @@ Return the encoding used to convert Unicode filenames in\n\ operating system filenames." ); -static PyObject * -sys_setfilesystemencoding(PyObject *self, PyObject *args) -{ - PyObject *new_encoding; - if (!PyArg_ParseTuple(args, "U:setfilesystemencoding", &new_encoding)) - return NULL; - if (_Py_SetFileSystemEncoding(new_encoding)) - return NULL; - Py_INCREF(Py_None); - return Py_None; -} - -PyDoc_STRVAR(setfilesystemencoding_doc, -"setfilesystemencoding(string) -> None\n\ -\n\ -Set the encoding used to convert Unicode filenames in\n\ -operating system filenames." -); - static PyObject * sys_intern(PyObject *self, PyObject *args) { @@ -1012,8 +993,6 @@ static PyMethodDef sys_methods[] = { #ifdef USE_MALLOPT {"mdebug", sys_mdebug, METH_VARARGS}, #endif - {"setfilesystemencoding", sys_setfilesystemencoding, METH_VARARGS, - setfilesystemencoding_doc}, {"setcheckinterval", sys_setcheckinterval, METH_VARARGS, setcheckinterval_doc}, {"getcheckinterval", sys_getcheckinterval, METH_NOARGS, -- cgit v1.2.1 From 15ba7bae534ca2e21e39e4b8b0269a55a5e9f7d2 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 10 Sep 2010 22:02:31 +0000 Subject: use DISPATCH() instead of continue --- Python/ceval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index f0d278c564..ff505a5dcd 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2148,7 +2148,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) x = freevars[oparg]; if (PyCell_GET(x) != NULL) { PyCell_Set(x, NULL); - continue; + DISPATCH(); } err = -1; format_exc_unbound(co, oparg); -- cgit v1.2.1 From 0b5243646e6b11fefb6fae56eb57b4665ceca8aa Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 10 Sep 2010 22:47:02 +0000 Subject: remove gil_drop_request in --without-threads --- Python/ceval.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index ff505a5dcd..2c7f57b56a 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -217,16 +217,24 @@ PyEval_GetCallStats(PyObject *self) #endif +#ifdef WITH_THREAD +#define GIL_REQUEST _Py_atomic_load_relaxed(&gil_drop_request) +#else +#define GIL_REQUEST 0 +#endif + /* This can set eval_breaker to 0 even though gil_drop_request became 1. We believe this is all right because the eval loop will release the GIL eventually anyway. */ #define COMPUTE_EVAL_BREAKER() \ _Py_atomic_store_relaxed( \ &eval_breaker, \ - _Py_atomic_load_relaxed(&gil_drop_request) | \ + GIL_REQUEST | \ _Py_atomic_load_relaxed(&pendingcalls_to_do) | \ pending_async_exc) +#ifdef WITH_THREAD + #define SET_GIL_DROP_REQUEST() \ do { \ _Py_atomic_store_relaxed(&gil_drop_request, 1); \ @@ -239,6 +247,8 @@ PyEval_GetCallStats(PyObject *self) COMPUTE_EVAL_BREAKER(); \ } while (0) +#endif + /* Pending calls are only modified under pending_lock */ #define SIGNAL_PENDING_CALLS() \ do { \ @@ -387,7 +397,6 @@ PyEval_ReInitThreads(void) #else static _Py_atomic_int eval_breaker = {0}; -static _Py_atomic_int gil_drop_request = {0}; static int pending_async_exc = 0; #endif /* WITH_THREAD */ @@ -1277,8 +1286,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) goto on_error; } } - if (_Py_atomic_load_relaxed(&gil_drop_request)) { #ifdef WITH_THREAD + if (_Py_atomic_load_relaxed(&gil_drop_request)) { /* Give another thread a chance */ if (PyThreadState_Swap(NULL) != tstate) Py_FatalError("ceval: tstate mix-up"); @@ -1289,8 +1298,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) take_gil(tstate); if (PyThreadState_Swap(tstate) != NULL) Py_FatalError("ceval: orphan tstate"); -#endif } +#endif /* Check for asynchronous exceptions. */ if (tstate->async_exc != NULL) { x = tstate->async_exc; -- cgit v1.2.1 From 668b311c5640db5b9a2e27cdf563f2483b537325 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 10 Sep 2010 23:52:42 +0000 Subject: use Py_REFCNT --- Python/ceval.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 2c7f57b56a..51d9fbfb75 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4394,7 +4394,7 @@ unicode_concatenate(PyObject *v, PyObject *w, return NULL; } - if (v->ob_refcnt == 2) { + if (Py_REFCNF(v) == 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 @@ -4435,7 +4435,7 @@ unicode_concatenate(PyObject *v, PyObject *w, } } - if (v->ob_refcnt == 1 && !PyUnicode_CHECK_INTERNED(v)) { + if (Py_REFCNF(v) == 1 && !PyUnicode_CHECK_INTERNED(v)) { /* Now we own the last reference to 'v', so we can resize it * in-place. */ -- cgit v1.2.1 From 2f6a73caaa8d8282a2c7c8f71f717ae2f0ecb582 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 10 Sep 2010 23:53:14 +0000 Subject: typo --- Python/ceval.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 51d9fbfb75..a181ca83fe 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4394,7 +4394,7 @@ unicode_concatenate(PyObject *v, PyObject *w, return NULL; } - if (Py_REFCNF(v) == 2) { + if (Py_REFCNT(v) == 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 @@ -4435,7 +4435,7 @@ unicode_concatenate(PyObject *v, PyObject *w, } } - if (Py_REFCNF(v) == 1 && !PyUnicode_CHECK_INTERNED(v)) { + if (Py_REFCNT(v) == 1 && !PyUnicode_CHECK_INTERNED(v)) { /* Now we own the last reference to 'v', so we can resize it * in-place. */ -- cgit v1.2.1 From c7339f55eed64cbcf8e24625593653e815d62475 Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Sat, 11 Sep 2010 00:39:25 +0000 Subject: Fix incorrect comment regarding MAGIC and TAG in import.c --- Python/import.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index f5bc03ddd8..b8cfbee610 100644 --- a/Python/import.c +++ b/Python/import.c @@ -108,8 +108,11 @@ typedef unsigned short mode_t; Python 3.2a2 3180 (add DELETE_DEREF) */ -/* If you change MAGIC, you must change TAG and you must insert the old value - into _PyMagicNumberTags below. +/* MAGIC must change whenever the bytecode emitted by the compiler may no + longer be understood by older implementations of the eval loop (usually + due to the addition of new opcodes) + TAG must change for each major Python release. The magic number will take + care of any bytecode changes that occur during development. */ #define MAGIC (3180 | ((long)'\r'<<16) | ((long)'\n'<<24)) #define TAG "cpython-32" -- cgit v1.2.1 From 64b32a2e48eecce58447ae9f0c678464720eb960 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Mon, 13 Sep 2010 14:16:46 +0000 Subject: Issue #9828: Destroy the GIL in Py_Finalize(), so that it gets properly re-created on a subsequent call to Py_Initialize(). The problem (a crash) wouldn't appear in 3.1 or 2.7 where the GIL's structure is more trivial. --- Python/ceval.c | 13 +++++++++---- Python/ceval_gil.h | 21 +++++++++++++++++++++ Python/pythonrun.c | 4 ++++ 3 files changed, 34 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index a181ca83fe..48b5678652 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -312,6 +312,15 @@ PyEval_InitThreads(void) pending_lock = PyThread_allocate_lock(); } +void +_PyEval_FiniThreads(void) +{ + if (!gil_created()) + return; + destroy_gil(); + assert(!gil_created()); +} + void PyEval_AcquireLock(void) { @@ -368,10 +377,6 @@ PyEval_ReInitThreads(void) if (!gil_created()) 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 */ recreate_gil(); pending_lock = PyThread_allocate_lock(); take_gil(tstate); diff --git a/Python/ceval_gil.h b/Python/ceval_gil.h index 7d72016083..40e45f75f2 100644 --- a/Python/ceval_gil.h +++ b/Python/ceval_gil.h @@ -95,6 +95,9 @@ do { \ #define MUTEX_INIT(mut) \ if (pthread_mutex_init(&mut, NULL)) { \ Py_FatalError("pthread_mutex_init(" #mut ") failed"); }; +#define MUTEX_FINI(mut) \ + if (pthread_mutex_destroy(&mut)) { \ + Py_FatalError("pthread_mutex_destroy(" #mut ") failed"); }; #define MUTEX_LOCK(mut) \ if (pthread_mutex_lock(&mut)) { \ Py_FatalError("pthread_mutex_lock(" #mut ") failed"); }; @@ -106,6 +109,9 @@ do { \ #define COND_INIT(cond) \ if (pthread_cond_init(&cond, NULL)) { \ Py_FatalError("pthread_cond_init(" #cond ") failed"); }; +#define COND_FINI(cond) \ + if (pthread_cond_destroy(&cond)) { \ + Py_FatalError("pthread_cond_destroy(" #cond ") failed"); }; #define COND_SIGNAL(cond) \ if (pthread_cond_signal(&cond)) { \ Py_FatalError("pthread_cond_signal(" #cond ") failed"); }; @@ -305,9 +311,24 @@ static void create_gil(void) _Py_atomic_store_explicit(&gil_locked, 0, _Py_memory_order_release); } +static void destroy_gil(void) +{ + MUTEX_FINI(gil_mutex); +#ifdef FORCE_SWITCHING + MUTEX_FINI(switch_mutex); +#endif + COND_FINI(gil_cond); +#ifdef FORCE_SWITCHING + COND_FINI(switch_cond); +#endif + _Py_atomic_store_explicit(&gil_locked, -1, _Py_memory_order_release); + _Py_ANNOTATE_RWLOCK_DESTROY(&gil_locked); +} + static void recreate_gil(void) { _Py_ANNOTATE_RWLOCK_DESTROY(&gil_locked); + /* XXX should we destroy the old OS resources here? */ create_gil(); } diff --git a/Python/pythonrun.c b/Python/pythonrun.c index fd31974cb8..8f4e9f18f7 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -514,6 +514,10 @@ Py_Finalize(void) PyGrammar_RemoveAccelerators(&_PyParser_Grammar); +#ifdef WITH_THREAD + _PyEval_FiniThreads(); +#endif + #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 -- cgit v1.2.1 From e408ad2617086fcfe3c843bfa177bc51cb8c7445 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Sun, 19 Sep 2010 21:39:02 +0000 Subject: PyImport_Import was using the old import hack of sticking a dummy value into fromlist to get __import__ to return the module desired. Now it uses the proper approach of fetching the module from sys.modules. Closes issue #9252. Thanks to Alexander Belopolsky for the bug report. --- Python/import.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index b8cfbee610..3078734d8b 100644 --- a/Python/import.c +++ b/Python/import.c @@ -3044,7 +3044,7 @@ PyImport_ReloadModule(PyObject *m) 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". + environment. A dummy list ["__doc__"] is passed as the 4th argument so that e.g. PyImport_Import(PyUnicode_FromString("win32com.client.gencache")) will return instead of . */ @@ -3058,6 +3058,7 @@ PyImport_Import(PyObject *module_name) PyObject *globals = NULL; PyObject *import = NULL; PyObject *builtins = NULL; + PyObject *modules = NULL; PyObject *r = NULL; /* Initialize constant string objects */ @@ -3068,7 +3069,7 @@ PyImport_Import(PyObject *module_name) builtins_str = PyUnicode_InternFromString("__builtins__"); if (builtins_str == NULL) return NULL; - silly_list = Py_BuildValue("[s]", "__doc__"); + silly_list = PyList_New(0); if (silly_list == NULL) return NULL; } @@ -3104,9 +3105,18 @@ PyImport_Import(PyObject *module_name) goto err; /* Call the __import__ function with the proper argument list - * Always use absolute import here. */ + Always use absolute import here. + Calling for side-effect of import. */ r = PyObject_CallFunction(import, "OOOOi", module_name, globals, globals, silly_list, 0, NULL); + if (r == NULL) + goto err; + Py_DECREF(r); + + modules = PyImport_GetModuleDict(); + r = PyDict_GetItem(modules, module_name); + if (r != NULL) + Py_INCREF(r); err: Py_XDECREF(globals); -- cgit v1.2.1 From 4a6fcda50b929b61836ed82e57937dec5d47961a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Valur=20J=C3=B3nsson?= Date: Mon, 20 Sep 2010 02:11:49 +0000 Subject: issue 9786 Native TLS support for pthreads PyThread_create_key now has a failure mode that the applicatino can detect. --- Python/pystate.c | 2 ++ Python/thread_nt.h | 5 ++++- Python/thread_pthread.h | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/pystate.c b/Python/pystate.c index 77534fc12f..d5d98b0c6d 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -569,6 +569,8 @@ _PyGILState_Init(PyInterpreterState *i, PyThreadState *t) { assert(i && t); /* must init with valid states */ autoTLSkey = PyThread_create_key(); + if (autoTLSkey == -1) + Py_FatalError("Could not allocate TLS entry"); autoInterpreterState = i; assert(PyThread_get_key_value(autoTLSkey) == NULL); assert(t->gilstate_counter == 0); diff --git a/Python/thread_nt.h b/Python/thread_nt.h index 2fd709817c..9de9e0dfbe 100644 --- a/Python/thread_nt.h +++ b/Python/thread_nt.h @@ -315,7 +315,10 @@ _pythread_nt_set_stacksize(size_t size) int PyThread_create_key(void) { - return (int) TlsAlloc(); + DWORD result= TlsAlloc(); + if (result == TLS_OUT_OF_INDEXES) + return -1; + return (int)result; } void diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index 5e52b3977e..a529b7a7eb 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -558,3 +558,46 @@ _pythread_pthread_set_stacksize(size_t size) } #define THREAD_SET_STACKSIZE(x) _pythread_pthread_set_stacksize(x) + +#define Py_HAVE_NATIVE_TLS + +int +PyThread_create_key(void) +{ + pthread_key_t key; + int fail = pthread_key_create(&key, NULL); + return fail ? -1 : key; +} + +void +PyThread_delete_key(int key) +{ + pthread_key_delete(key); +} + +void +PyThread_delete_key_value(int key) +{ + pthread_setspecific(key, NULL); +} + +int +PyThread_set_key_value(int key, void *value) +{ + int fail; + void *oldValue = pthread_getspecific(key); + if (oldValue != NULL) + return 0; + fail = pthread_setspecific(key, value); + return fail ? -1 : 0; +} + +void * +PyThread_get_key_value(int key) +{ + return pthread_getspecific(key); +} + +void +PyThread_ReInitTLS(void) +{} -- cgit v1.2.1 From a6001dfe413068f5a425f062d62f2038a72b013d Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Mon, 20 Sep 2010 20:13:48 +0000 Subject: Issue #9901: Destroying the GIL in Py_Finalize() can fail if some other threads are still running. Instead, reinitialize the GIL on a second call to Py_Initialize(). --- Python/pythonrun.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 8f4e9f18f7..a3f5d2b667 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -217,8 +217,15 @@ Py_InitializeEx(int install_sigs) Py_FatalError("Py_Initialize: can't make first thread"); (void) PyThreadState_Swap(tstate); - /* auto-thread-state API, if available */ #ifdef WITH_THREAD + /* We can't call _PyEval_FiniThreads() in Py_Finalize because + destroying the GIL might fail when it is being referenced from + another running thread (see issue #9901). + Instead we destroy the previously created GIL here, which ensures + that we can call Py_Initialize / Py_Finalize multiple times. */ + _PyEval_FiniThreads(); + + /* Auto-thread-state API */ _PyGILState_Init(interp, tstate); #endif /* WITH_THREAD */ @@ -514,10 +521,6 @@ Py_Finalize(void) PyGrammar_RemoveAccelerators(&_PyParser_Grammar); -#ifdef WITH_THREAD - _PyEval_FiniThreads(); -#endif - #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 -- cgit v1.2.1 From 98907bab94e60d8a2b492aa0669b0bf792c6303e Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 20 Sep 2010 22:42:10 +0000 Subject: add PyErr_SyntaxLocationEx, to support adding a column offset --- Python/errors.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/errors.c b/Python/errors.c index 4ae661a16f..a24095dff9 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -780,12 +780,18 @@ PyErr_WriteUnraisable(PyObject *obj) extern PyObject *PyModule_GetWarningsModule(void); +void +PyErr_SyntaxLocation(const char *filename, int lineno) { + PyErr_SyntaxLocationEx(filename, lineno, -1); +} + + /* 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) +PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset) { PyObject *exc, *v, *tb, *tmp; @@ -802,6 +808,16 @@ PyErr_SyntaxLocation(const char *filename, int lineno) PyErr_Clear(); Py_DECREF(tmp); } + if (col_offset >= 0) { + tmp = PyLong_FromLong(col_offset); + if (tmp == NULL) + PyErr_Clear(); + else { + if (PyObject_SetAttrString(v, "offset", tmp)) + PyErr_Clear(); + Py_DECREF(tmp); + } + } if (filename != NULL) { tmp = PyUnicode_FromString(filename); if (tmp == NULL) -- cgit v1.2.1 From c9651975ec1a9b373c4da03a83f5e5abe12b23b9 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 20 Sep 2010 23:02:10 +0000 Subject: add column offset to all syntax errors --- Python/ast.c | 11 +++++++--- Python/compile.c | 10 +++++++-- Python/future.c | 7 +++---- Python/symtable.c | 61 +++++++++++++++++++++++++++++++++---------------------- 4 files changed, 56 insertions(+), 33 deletions(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index 9f6b7eaa8a..38643f6a3b 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -90,7 +90,7 @@ new_identifier(const char* n, PyArena *arena) static int ast_error(const node *n, const char *errstr) { - PyObject *u = Py_BuildValue("zi", errstr, LINENO(n)); + PyObject *u = Py_BuildValue("zii", errstr, LINENO(n), n->n_col_offset); if (!u) return 0; PyErr_SetObject(PyExc_SyntaxError, u); @@ -101,7 +101,7 @@ ast_error(const node *n, const char *errstr) static void ast_error_finish(const char *filename) { - PyObject *type, *value, *tback, *errstr, *loc, *tmp; + PyObject *type, *value, *tback, *errstr, *offset, *loc, *tmp; long lineno; assert(PyErr_Occurred()); @@ -118,6 +118,11 @@ ast_error_finish(const char *filename) Py_DECREF(errstr); return; } + offset = PyTuple_GetItem(value, 2); + if (!offset) { + Py_DECREF(errstr); + return; + } Py_DECREF(value); loc = PyErr_ProgramText(filename, lineno); @@ -125,7 +130,7 @@ ast_error_finish(const char *filename) Py_INCREF(Py_None); loc = Py_None; } - tmp = Py_BuildValue("(zlOO)", filename, lineno, Py_None, loc); + tmp = Py_BuildValue("(zlOO)", filename, lineno, offset, loc); Py_DECREF(loc); if (!tmp) { Py_DECREF(errstr); diff --git a/Python/compile.c b/Python/compile.c index 5341e6b535..d29e48c47a 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -123,6 +123,7 @@ struct compiler_unit { int u_firstlineno; /* the first lineno of the block */ int u_lineno; /* the lineno for the current stmt */ + int u_col_offset; /* the offset of the current stmt */ int u_lineno_set; /* boolean to indicate whether instr has been generated with current lineno */ }; @@ -486,6 +487,7 @@ compiler_enter_scope(struct compiler *c, identifier name, void *key, u->u_nfblocks = 0; u->u_firstlineno = lineno; u->u_lineno = 0; + u->u_col_offset = 0; u->u_lineno_set = 0; u->u_consts = PyDict_New(); if (!u->u_consts) { @@ -1965,6 +1967,7 @@ compiler_try_except(struct compiler *c, stmt_ty s) return compiler_error(c, "default 'except:' must be last"); c->u->u_lineno_set = 0; c->u->u_lineno = handler->lineno; + c->u->u_col_offset = handler->col_offset; except = compiler_new_block(c); if (except == NULL) return 0; @@ -2247,6 +2250,7 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s) /* Always assign a lineno to the next instruction for a stmt. */ c->u->u_lineno = s->lineno; + c->u->u_col_offset = s->col_offset; c->u->u_lineno_set = 0; switch (s->kind) { @@ -3122,6 +3126,8 @@ compiler_visit_expr(struct compiler *c, expr_ty e) c->u->u_lineno = e->lineno; c->u->u_lineno_set = 0; } + /* Updating the column offset is always harmless. */ + c->u->u_col_offset = e->col_offset; switch (e->kind) { case BoolOp_kind: return compiler_boolop(c, e); @@ -3363,8 +3369,8 @@ compiler_error(struct compiler *c, const char *errstr) Py_INCREF(Py_None); loc = Py_None; } - u = Py_BuildValue("(ziOO)", c->c_filename, c->u->u_lineno, - Py_None, loc); + u = Py_BuildValue("(ziiO)", c->c_filename, c->u->u_lineno, + c->u->u_col_offset, loc); if (!u) goto exit; v = Py_BuildValue("(zO)", errstr, u); diff --git a/Python/future.c b/Python/future.c index 515dcd9dc6..551edc6085 100644 --- a/Python/future.c +++ b/Python/future.c @@ -44,12 +44,12 @@ future_check_features(PyFutureFeatures *ff, stmt_ty s, const char *filename) } else if (strcmp(feature, "braces") == 0) { PyErr_SetString(PyExc_SyntaxError, "not a chance"); - PyErr_SyntaxLocation(filename, s->lineno); + PyErr_SyntaxLocationEx(filename, s->lineno, s->col_offset); return 0; } else { PyErr_Format(PyExc_SyntaxError, UNDEFINED_FUTURE_FEATURE, feature); - PyErr_SyntaxLocation(filename, s->lineno); + PyErr_SyntaxLocationEx(filename, s->lineno, s->col_offset); return 0; } } @@ -98,8 +98,7 @@ future_parse(PyFutureFeatures *ff, mod_ty mod, const char *filename) if (done) { PyErr_SetString(PyExc_SyntaxError, ERR_LATE_FUTURE); - PyErr_SyntaxLocation(filename, - s->lineno); + PyErr_SyntaxLocationEx(filename, s->lineno, s->col_offset); return 0; } if (!future_check_features(ff, s, filename)) diff --git a/Python/symtable.c b/Python/symtable.c index 55c9f472fc..f75b9c997f 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -25,7 +25,7 @@ static PySTEntryObject * ste_new(struct symtable *st, identifier name, _Py_block_ty block, - void *key, int lineno) + void *key, int lineno, int col_offset) { PySTEntryObject *ste = NULL; PyObject *k; @@ -65,7 +65,9 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block, ste->ste_varargs = 0; ste->ste_varkeywords = 0; ste->ste_opt_lineno = 0; + ste->ste_opt_col_offset = 0; ste->ste_lineno = lineno; + ste->ste_col_offset = col_offset; if (st->st_cur != NULL && (st->st_cur->ste_nested || @@ -163,7 +165,8 @@ PyTypeObject PySTEntry_Type = { 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); + _Py_block_ty block, void *ast, int lineno, + int col_offset); 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); @@ -230,7 +233,7 @@ PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future) st->st_future = future; /* Make the initial symbol information gathering pass */ if (!GET_IDENTIFIER(top) || - !symtable_enter_block(st, top, ModuleBlock, (void *)mod, 0)) { + !symtable_enter_block(st, top, ModuleBlock, (void *)mod, 0, 0)) { PySymtable_Free(st); return NULL; } @@ -390,8 +393,8 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags, PyErr_Format(PyExc_SyntaxError, "name '%U' is parameter and global", name); - PyErr_SyntaxLocation(ste->ste_table->st_filename, - ste->ste_lineno); + PyErr_SyntaxLocationEx(ste->ste_table->st_filename, + ste->ste_lineno, ste->ste_col_offset); return 0; } @@ -534,8 +537,8 @@ check_unoptimized(const PySTEntryObject* ste) { break; } - PyErr_SyntaxLocation(ste->ste_table->st_filename, - ste->ste_opt_lineno); + PyErr_SyntaxLocationEx(ste->ste_table->st_filename, ste->ste_opt_lineno, + ste->ste_opt_col_offset); return 0; } @@ -873,8 +876,8 @@ symtable_warn(struct symtable *st, char *msg, int lineno) lineno, NULL, NULL) < 0) { if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) { PyErr_SetString(PyExc_SyntaxError, msg); - PyErr_SyntaxLocation(st->st_filename, - st->st_cur->ste_lineno); + PyErr_SyntaxLocationEx(st->st_filename, st->st_cur->ste_lineno, + st->st_cur->ste_col_offset); } return 0; } @@ -907,7 +910,7 @@ symtable_exit_block(struct symtable *st, void *ast) static int symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block, - void *ast, int lineno) + void *ast, int lineno, int col_offset) { PySTEntryObject *prev = NULL; @@ -918,7 +921,7 @@ symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block, } Py_DECREF(st->st_cur); } - st->st_cur = ste_new(st, name, block, ast, lineno); + st->st_cur = ste_new(st, name, block, ast, lineno, col_offset); if (st->st_cur == NULL) return 0; if (name == GET_IDENTIFIER(top)) @@ -963,8 +966,9 @@ symtable_add_def(struct symtable *st, PyObject *name, int flag) if ((flag & DEF_PARAM) && (val & DEF_PARAM)) { /* Is it better to use 'mangled' or 'name' here? */ PyErr_Format(PyExc_SyntaxError, DUPLICATE_ARGUMENT, name); - PyErr_SyntaxLocation(st->st_filename, - st->st_cur->ste_lineno); + PyErr_SyntaxLocationEx(st->st_filename, + st->st_cur->ste_lineno, + st->st_cur->ste_col_offset); goto error; } val |= flag; @@ -1114,7 +1118,8 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) if (s->v.FunctionDef.decorator_list) VISIT_SEQ(st, expr, s->v.FunctionDef.decorator_list); if (!symtable_enter_block(st, s->v.FunctionDef.name, - FunctionBlock, (void *)s, s->lineno)) + FunctionBlock, (void *)s, s->lineno, + s->col_offset)) return 0; VISIT_IN_BLOCK(st, arguments, s->v.FunctionDef.args, s); VISIT_SEQ_IN_BLOCK(st, stmt, s->v.FunctionDef.body, s); @@ -1134,7 +1139,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) if (s->v.ClassDef.decorator_list) VISIT_SEQ(st, expr, s->v.ClassDef.decorator_list); if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock, - (void *)s, s->lineno)) + (void *)s, s->lineno, s->col_offset)) return 0; if (!GET_IDENTIFIER(__class__) || !symtable_add_def(st, __class__, DEF_LOCAL) || @@ -1158,8 +1163,9 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) if (st->st_cur->ste_generator) { PyErr_SetString(PyExc_SyntaxError, RETURN_VAL_IN_GENERATOR); - PyErr_SyntaxLocation(st->st_filename, - s->lineno); + PyErr_SyntaxLocationEx(st->st_filename, + s->lineno, + s->col_offset); return 0; } } @@ -1221,15 +1227,19 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) 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) + if (st->st_cur->ste_unoptimized && !st->st_cur->ste_opt_lineno) { st->st_cur->ste_opt_lineno = s->lineno; + st->st_cur->ste_opt_col_offset = s->col_offset; + } 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) + if (st->st_cur->ste_unoptimized && !st->st_cur->ste_opt_lineno) { st->st_cur->ste_opt_lineno = s->lineno; + st->st_cur->ste_opt_col_offset = s->col_offset; + } break; case Global_kind: { int i; @@ -1324,7 +1334,8 @@ symtable_visit_expr(struct symtable *st, expr_ty e) if (e->v.Lambda.args->defaults) VISIT_SEQ(st, expr, e->v.Lambda.args->defaults); if (!symtable_enter_block(st, lambda, - FunctionBlock, (void *)e, e->lineno)) + FunctionBlock, (void *)e, e->lineno, + e->col_offset)) return 0; VISIT_IN_BLOCK(st, arguments, e->v.Lambda.args, (void*)e); VISIT_IN_BLOCK(st, expr, e->v.Lambda.body, (void*)e); @@ -1367,8 +1378,8 @@ symtable_visit_expr(struct symtable *st, expr_ty e) if (st->st_cur->ste_returns_value) { PyErr_SetString(PyExc_SyntaxError, RETURN_VAL_IN_GENERATOR); - PyErr_SyntaxLocation(st->st_filename, - e->lineno); + PyErr_SyntaxLocationEx(st->st_filename, + e->lineno, e->col_offset); return 0; } break; @@ -1557,8 +1568,9 @@ symtable_visit_alias(struct symtable *st, alias_ty a) else { if (st->st_cur->ste_type != ModuleBlock) { int lineno = st->st_cur->ste_lineno; + int col_offset = st->st_cur->ste_col_offset; PyErr_SetString(PyExc_SyntaxError, IMPORT_STAR_WARNING); - PyErr_SyntaxLocation(st->st_filename, lineno); + PyErr_SyntaxLocationEx(st->st_filename, lineno, col_offset); Py_DECREF(store_name); return 0; } @@ -1622,7 +1634,8 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e, VISIT(st, expr, outermost->iter); /* Create comprehension scope for the rest */ if (!scope_name || - !symtable_enter_block(st, scope_name, FunctionBlock, (void *)e, e->lineno)) { + !symtable_enter_block(st, scope_name, FunctionBlock, (void *)e, + e->lineno, e->col_offset)) { return 0; } st->st_cur->ste_generator = is_generator; -- cgit v1.2.1 From ea5f065cce60d5dc03c4391ca1d408fe0b35af5e Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 25 Sep 2010 03:14:33 +0000 Subject: don't count keyword arguments as positional #9943 --- Python/ceval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 48b5678652..84781be32f 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3104,7 +3104,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, defcount ? "at most" : "exactly", co->co_argcount, co->co_argcount == 1 ? "" : "s", - argcount + kwcount); + argcount); goto fail; } n = co->co_argcount; -- cgit v1.2.1 From 67598f66f1a79c59346ec17185fdbe61156c3636 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 25 Sep 2010 03:25:42 +0000 Subject: revert r85003, poorly considered; breaks tests --- Python/ceval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 84781be32f..48b5678652 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3104,7 +3104,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, defcount ? "at most" : "exactly", co->co_argcount, co->co_argcount == 1 ? "" : "s", - argcount); + argcount + kwcount); goto fail; } n = co->co_argcount; -- cgit v1.2.1 From 064d77f98f02888066c602ff0315ecfb59d586c1 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Mon, 27 Sep 2010 21:08:38 +0000 Subject: Since __import__ is not designed for general use, have its docstring point people towards importlib.import_module(). Closes issue #7397. --- Python/bltinmodule.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 60bceb7581..2e8d6e21b3 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -173,8 +173,12 @@ builtin___import__(PyObject *self, PyObject *args, PyObject *kwds) 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\ +Import a module. Because this function is meant for use by the Python\n\ +interpreter and not for general use it is better to use\n\ +importlib.import_module() to programmatically import a module.\n\ +\n\ +The globals argument is only used to determine the context;\n\ +they are not modified. The locals argument is 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\ -- cgit v1.2.1 From b9d21368d231f338562b8a5b2a0bc392a2ea9f80 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 29 Sep 2010 10:28:51 +0000 Subject: Issue #9979: Use PyUnicode_AsWideCharString() in import.c Don't truncate path if it is too long anymore, and allocate fewer memory (but allocate it on the heap, not on the stack). --- Python/import.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 3078734d8b..b708f27d38 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1961,21 +1961,21 @@ FILE* _Py_fopen(PyObject *unicode, const char *mode) { #ifdef MS_WINDOWS - wchar_t path[MAXPATHLEN+1]; + wchar_t *path; wchar_t wmode[10]; - Py_ssize_t len; int usize; - - len = PyUnicode_AsWideChar((PyUnicodeObject*)unicode, path, MAXPATHLEN); - if (len == -1) - return NULL; - path[len] = L'\0'; + FILE *f; usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode, sizeof(wmode)); if (usize == 0) return NULL; - return _wfopen(path, wmode); + path = PyUnicode_AsWideCharString((PyUnicodeObject*)unicode, NULL); + if (path == NULL) + return NULL; + f = _wfopen(path, wmode); + PyMem_Free(path); + return f; #else FILE *f; PyObject *bytes = PyUnicode_EncodeFSDefault(unicode); @@ -1997,17 +1997,15 @@ int _Py_stat(PyObject *unicode, struct stat *statbuf) { #ifdef MS_WINDOWS - wchar_t path[MAXPATHLEN+1]; - Py_ssize_t len; + wchar_t *path; int err; struct _stat wstatbuf; - len = PyUnicode_AsWideChar((PyUnicodeObject*)unicode, path, MAXPATHLEN); - if (len == -1) + path = PyUnicode_AsWideCharString((PyUnicodeObject*)unicode, NULL); + if (path == NULL) return -1; - path[len] = L'\0'; - err = _wstat(path, &wstatbuf); + PyMem_Free(path); if (!err) statbuf->st_mode = wstatbuf.st_mode; return err; @@ -3724,7 +3722,7 @@ NullImporter_init(NullImporter *self, PyObject *args, PyObject *kwds) #else /* MS_WINDOWS */ PyObject *pathobj; DWORD rv; - wchar_t path[MAXPATHLEN+1]; + wchar_t *path; Py_ssize_t len; if (!_PyArg_NoKeywords("NullImporter()", kwds)) @@ -3739,15 +3737,15 @@ NullImporter_init(NullImporter *self, PyObject *args, PyObject *kwds) return -1; } - len = PyUnicode_AsWideChar((PyUnicodeObject*)pathobj, - path, sizeof(path) / sizeof(path[0])); - if (len == -1) + path = PyUnicode_AsWideCharString((PyUnicodeObject*)pathobj, NULL); + if (path == NULL) return -1; /* see issue1293 and issue3677: * stat() on Windows doesn't recognise paths like * "e:\\shared\\" and "\\\\whiterab-c2znlh\\shared" as dirs. */ rv = GetFileAttributesW(path); + PyMem_Free(path); if (rv != INVALID_FILE_ATTRIBUTES) { /* it exists */ if (rv & FILE_ATTRIBUTE_DIRECTORY) { -- cgit v1.2.1 From 82deba1f06f5dedc64fab78febbed063b4b8f85d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 29 Sep 2010 16:35:47 +0000 Subject: Issue #9630: Redecode filenames when setting the filesystem encoding Redecode the filenames of: - all modules: __file__ and __path__ attributes - all code objects: co_filename attribute - sys.path - sys.meta_path - sys.executable - sys.path_importer_cache (keys) Keep weak references to all code objects until initfsencoding() is called, to be able to redecode co_filename attribute of all code objects. --- Python/pythonrun.c | 258 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 258 insertions(+) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index a3f5d2b667..a888a19f20 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -719,6 +719,259 @@ initmain(void) } } +/* Redecode a filename from the default filesystem encoding (utf-8) to + 'new_encoding' encoding with 'errors' error handler */ +static PyObject* +redecode_filename(PyObject *file, const char *new_encoding, + const char *errors) +{ + PyObject *file_bytes = NULL, *new_file = NULL; + + file_bytes = PyUnicode_EncodeFSDefault(file); + if (file_bytes == NULL) + return NULL; + new_file = PyUnicode_Decode( + PyBytes_AsString(file_bytes), + PyBytes_GET_SIZE(file_bytes), + new_encoding, + errors); + Py_DECREF(file_bytes); + return new_file; +} + +/* Redecode a path list */ +static int +redecode_path_list(PyObject *paths, + const char *new_encoding, const char *errors) +{ + PyObject *filename, *new_filename; + Py_ssize_t i, size; + + size = PyList_Size(paths); + for (i=0; i < size; i++) { + filename = PyList_GetItem(paths, i); + if (filename == NULL) + return -1; + + new_filename = redecode_filename(filename, new_encoding, errors); + if (new_filename == NULL) + return -1; + if (PyList_SetItem(paths, i, new_filename)) { + Py_DECREF(new_filename); + return -1; + } + } + return 0; +} + +/* Redecode __file__ and __path__ attributes of sys.modules */ +static int +redecode_sys_modules(const char *new_encoding, const char *errors) +{ + PyInterpreterState *interp; + PyObject *modules, *values, *file, *new_file, *paths; + PyObject *iter = NULL, *module = NULL; + + interp = PyThreadState_GET()->interp; + modules = interp->modules; + + values = PyObject_CallMethod(modules, "values", ""); + if (values == NULL) + goto error; + + iter = PyObject_GetIter(values); + Py_DECREF(values); + if (iter == NULL) + goto error; + + while (1) + { + module = PyIter_Next(iter); + if (module == NULL) { + if (PyErr_Occurred()) + goto error; + else + break; + } + + file = PyModule_GetFilenameObject(module); + if (file != NULL) { + new_file = redecode_filename(file, new_encoding, errors); + Py_DECREF(file); + if (new_file == NULL) + goto error; + if (PyObject_SetAttrString(module, "__file__", new_file)) { + Py_DECREF(new_file); + goto error; + } + Py_DECREF(new_file); + } + else + PyErr_Clear(); + + paths = PyObject_GetAttrString(module, "__path__"); + if (paths != NULL) { + if (redecode_path_list(paths, new_encoding, errors)) + goto error; + } + else + PyErr_Clear(); + + Py_CLEAR(module); + } + Py_CLEAR(iter); + return 0; + +error: + Py_XDECREF(iter); + Py_XDECREF(module); + return -1; +} + +/* Redecode sys.path_importer_cache keys */ +static int +redecode_sys_path_importer_cache(const char *new_encoding, const char *errors) +{ + PyObject *path_importer_cache, *items, *item, *path, *importer, *new_path; + PyObject *new_cache = NULL, *iter = NULL; + + path_importer_cache = PySys_GetObject("path_importer_cache"); + if (path_importer_cache == NULL) + goto error; + + items = PyObject_CallMethod(path_importer_cache, "items", ""); + if (items == NULL) + goto error; + + iter = PyObject_GetIter(items); + Py_DECREF(items); + if (iter == NULL) + goto error; + + new_cache = PyDict_New(); + if (new_cache == NULL) + goto error; + + while (1) + { + item = PyIter_Next(iter); + if (item == NULL) { + if (PyErr_Occurred()) + goto error; + else + break; + } + path = PyTuple_GET_ITEM(item, 0); + importer = PyTuple_GET_ITEM(item, 1); + + new_path = redecode_filename(path, new_encoding, errors); + if (new_path == NULL) + goto error; + if (PyDict_SetItem(new_cache, new_path, importer)) { + Py_DECREF(new_path); + goto error; + } + Py_DECREF(new_path); + } + Py_CLEAR(iter); + if (PySys_SetObject("path_importer_cache", new_cache)) + goto error; + Py_CLEAR(new_cache); + return 0; + +error: + Py_XDECREF(iter); + Py_XDECREF(new_cache); + return -1; +} + +/* Redecode co_filename attribute of all code objects */ +static int +redecode_code_objects(const char *new_encoding, const char *errors) +{ + Py_ssize_t i, len; + PyCodeObject *co; + PyObject *ref, *new_file; + + len = Py_SIZE(_Py_code_object_list); + for (i=0; i < len; i++) { + ref = PyList_GET_ITEM(_Py_code_object_list, i); + co = (PyCodeObject *)PyWeakref_GetObject(ref); + if ((PyObject*)co == Py_None) + continue; + if (co == NULL) + return -1; + + new_file = redecode_filename(co->co_filename, new_encoding, errors); + if (new_file == NULL) + return -1; + Py_DECREF(co->co_filename); + co->co_filename = new_file; + } + Py_CLEAR(_Py_code_object_list); + return 0; +} + +/* Redecode the filenames of all modules (__file__ and __path__ attributes), + all code objects (co_filename attribute), sys.path, sys.meta_path, + sys.executable and sys.path_importer_cache (keys) when the filesystem + encoding changes from the default encoding (utf-8) to new_encoding */ +static int +redecode_filenames(const char *new_encoding) +{ + char *errors; + PyObject *paths, *executable, *new_executable; + + /* PyUnicode_DecodeFSDefault() and PyUnicode_EncodeFSDefault() do already + use utf-8 if Py_FileSystemDefaultEncoding is NULL */ + if (strcmp(new_encoding, "utf-8") == 0) + return 0; + + if (strcmp(new_encoding, "mbcs") != 0) + errors = "surrogateescape"; + else + errors = NULL; + + /* sys.modules */ + if (redecode_sys_modules(new_encoding, errors)) + return -1; + + /* sys.path and sys.meta_path */ + paths = PySys_GetObject("path"); + if (paths != NULL) { + if (redecode_path_list(paths, new_encoding, errors)) + return -1; + } + paths = PySys_GetObject("meta_path"); + if (paths != NULL) { + if (redecode_path_list(paths, new_encoding, errors)) + return -1; + } + + /* sys.executable */ + executable = PySys_GetObject("executable"); + if (executable == NULL) + return -1; + new_executable = redecode_filename(executable, new_encoding, errors); + if (new_executable == NULL) + return -1; + if (PySys_SetObject("executable", new_executable)) { + Py_DECREF(new_executable); + return -1; + } + Py_DECREF(new_executable); + + /* sys.path_importer_cache */ + if (redecode_sys_path_importer_cache(new_encoding, errors)) + return -1; + + /* code objects */ + if (redecode_code_objects(new_encoding, errors)) + return -1; + + return 0; +} + static void initfsencoding(void) { @@ -744,8 +997,11 @@ initfsencoding(void) codeset = get_codeset(); } if (codeset != NULL) { + if (redecode_filenames(codeset)) + Py_FatalError("Py_Initialize: can't redecode filenames"); Py_FileSystemDefaultEncoding = codeset; Py_HasFileSystemDefaultEncoding = 0; + Py_CLEAR(_Py_code_object_list); return; } else { fprintf(stderr, "Unable to get the locale encoding:\n"); @@ -758,6 +1014,8 @@ initfsencoding(void) } #endif + Py_CLEAR(_Py_code_object_list); + /* the encoding is mbcs, utf-8 or ascii */ codec = _PyCodec_Lookup(Py_FileSystemDefaultEncoding); if (!codec) { -- cgit v1.2.1 From c2227abfa10346d0a7640a7081bf825cfd1515bd Mon Sep 17 00:00:00 2001 From: Brian Curtin Date: Wed, 29 Sep 2010 19:09:33 +0000 Subject: Remove an unreferenced variable. len is no longer needed. --- Python/import.c | 1 - 1 file changed, 1 deletion(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index b708f27d38..43c1494150 100644 --- a/Python/import.c +++ b/Python/import.c @@ -3723,7 +3723,6 @@ NullImporter_init(NullImporter *self, PyObject *args, PyObject *kwds) PyObject *pathobj; DWORD rv; wchar_t *path; - Py_ssize_t len; if (!_PyArg_NoKeywords("NullImporter()", kwds)) return -1; -- cgit v1.2.1 From 4962be22fa662b3a2cbeba588e63dd195d3e27af Mon Sep 17 00:00:00 2001 From: Amaury Forgeot d'Arc Date: Tue, 5 Oct 2010 22:15:37 +0000 Subject: #9060 Let platforms without dup2() compile the replacement fonction without error. --- Python/dup2.c | 1 + 1 file changed, 1 insertion(+) (limited to 'Python') diff --git a/Python/dup2.c b/Python/dup2.c index ba7413a0ca..2579afd443 100644 --- a/Python/dup2.c +++ b/Python/dup2.c @@ -12,6 +12,7 @@ */ #include +#include #define BADEXIT -1 -- cgit v1.2.1 From cb5b45fb8d799d1f1a0cf52325ddc95623534ee5 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 6 Oct 2010 22:44:06 +0000 Subject: Create a subfunction for PySys_SetArgvEx() Create sys_update_path() static function. Do nothing if argc==0. --- Python/sysmodule.c | 172 +++++++++++++++++++++++++++++------------------------ 1 file changed, 94 insertions(+), 78 deletions(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 4e428f0171..97809d27b0 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1685,106 +1685,122 @@ _wrealpath(const wchar_t *path, wchar_t *resolved_path) #define _HAVE_SCRIPT_ARGUMENT(argc, argv) \ (argc > 0 && argv0 != NULL && \ wcscmp(argv0, L"-c") != 0 && wcscmp(argv0, L"-m") != 0) - -void -PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) + +static void +sys_update_path(int argc, wchar_t **argv) { + wchar_t *argv0; + wchar_t *p = NULL; + Py_ssize_t n = 0; + PyObject *a; + PyObject *path; +#ifdef HAVE_READLINK + extern int _Py_wreadlink(const wchar_t *, wchar_t *, size_t); + wchar_t link[MAXPATHLEN+1]; + wchar_t argv0copy[2*MAXPATHLEN+1]; + int nr = 0; +#endif #if defined(HAVE_REALPATH) wchar_t fullpath[MAXPATHLEN]; #elif defined(MS_WINDOWS) && !defined(MS_WINCE) wchar_t 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 (updatepath && path != NULL) { - wchar_t *argv0 = argv[0]; - wchar_t *p = NULL; - Py_ssize_t n = 0; - PyObject *a; - extern int _Py_wreadlink(const wchar_t *, wchar_t *, size_t); + + path = PySys_GetObject("path"); + if (path == NULL) + return; + + if (argc == 0) + return; + argv0 = argv[0]; + #ifdef HAVE_READLINK - wchar_t link[MAXPATHLEN+1]; - wchar_t argv0copy[2*MAXPATHLEN+1]; - int nr = 0; - if (_HAVE_SCRIPT_ARGUMENT(argc, argv)) - nr = _Py_wreadlink(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 (wcschr(link, SEP) == NULL) - ; /* Link without path */ + if (_HAVE_SCRIPT_ARGUMENT(argc, argv)) + nr = _Py_wreadlink(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 (wcschr(link, SEP) == NULL) + ; /* Link without path */ + else { + /* Must join(dirname(argv0), link) */ + wchar_t *q = wcsrchr(argv0, SEP); + if (q == NULL) + argv0 = link; /* argv0 without path */ else { - /* Must join(dirname(argv0), link) */ - wchar_t *q = wcsrchr(argv0, SEP); - if (q == NULL) - argv0 = link; /* argv0 without path */ - else { - /* Must make a copy */ - wcscpy(argv0copy, argv0); - q = wcsrchr(argv0copy, SEP); - wcscpy(q+1, link); - argv0 = argv0copy; - } + /* Must make a copy */ + wcscpy(argv0copy, argv0); + q = wcsrchr(argv0copy, SEP); + wcscpy(q+1, link); + argv0 = argv0copy; } } + } #endif /* HAVE_READLINK */ #if SEP == '\\' /* Special case for MS filename syntax */ - if (_HAVE_SCRIPT_ARGUMENT(argc, argv)) { - wchar_t *q; + if (_HAVE_SCRIPT_ARGUMENT(argc, argv)) { + wchar_t *q; #if defined(MS_WINDOWS) && !defined(MS_WINCE) - /* This code here replaces the first element in argv with the full - path that it represents. Under CE, there are no relative paths so - the argument must be the full path anyway. */ - wchar_t *ptemp; - if (GetFullPathNameW(argv0, - sizeof(fullpath)/sizeof(fullpath[0]), - fullpath, - &ptemp)) { - argv0 = fullpath; - } + /* This code here replaces the first element in argv with the full + path that it represents. Under CE, there are no relative paths so + the argument must be the full path anyway. */ + wchar_t *ptemp; + if (GetFullPathNameW(argv0, + sizeof(fullpath)/sizeof(fullpath[0]), + fullpath, + &ptemp)) { + argv0 = fullpath; + } #endif - p = wcsrchr(argv0, SEP); - /* Test for alternate separator */ - q = wcsrchr(p ? p : argv0, '/'); - if (q != NULL) - p = q; - if (p != NULL) { - n = p + 1 - argv0; - if (n > 1 && p[-1] != ':') - n--; /* Drop trailing separator */ - } + p = wcsrchr(argv0, SEP); + /* Test for alternate separator */ + q = wcsrchr(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 (_HAVE_SCRIPT_ARGUMENT(argc, argv)) { + if (_HAVE_SCRIPT_ARGUMENT(argc, argv)) { #if defined(HAVE_REALPATH) - if (_wrealpath(argv0, fullpath)) { - argv0 = fullpath; - } -#endif - p = wcsrchr(argv0, SEP); + if (_wrealpath(argv0, fullpath)) { + argv0 = fullpath; } - if (p != NULL) { - n = p + 1 - argv0; +#endif + p = wcsrchr(argv0, SEP); + } + if (p != NULL) { + n = p + 1 - argv0; #if SEP == '/' /* Special case for Unix filename syntax */ - if (n > 1) - n--; /* Drop trailing separator */ + if (n > 1) + n--; /* Drop trailing separator */ #endif /* Unix */ - } -#endif /* All others */ - a = PyUnicode_FromWideChar(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); } +#endif /* All others */ + a = PyUnicode_FromWideChar(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); +} + +void +PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) +{ + PyObject *av = makeargvobject(argc, argv); + if (av == NULL) + Py_FatalError("no mem for sys.argv"); + if (PySys_SetObject("argv", av) != 0) + Py_FatalError("can't assign sys.argv"); Py_DECREF(av); + if (updatepath) + sys_update_path(argc, argv); } void -- cgit v1.2.1 From 90fd877049b4be1465843f00506d923e39bd4224 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 7 Oct 2010 01:02:42 +0000 Subject: PyUnicode_AsWideCharString() takes a PyObject*, not a PyUnicodeObject* All unicode functions uses PyObject* except PyUnicode_AsWideChar(). Fix the prototype for the new function PyUnicode_AsWideCharString(). --- Python/import.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 43c1494150..ab1615cd05 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1970,7 +1970,7 @@ _Py_fopen(PyObject *unicode, const char *mode) if (usize == 0) return NULL; - path = PyUnicode_AsWideCharString((PyUnicodeObject*)unicode, NULL); + path = PyUnicode_AsWideCharString(unicode, NULL); if (path == NULL) return NULL; f = _wfopen(path, wmode); @@ -2001,7 +2001,7 @@ _Py_stat(PyObject *unicode, struct stat *statbuf) int err; struct _stat wstatbuf; - path = PyUnicode_AsWideCharString((PyUnicodeObject*)unicode, NULL); + path = PyUnicode_AsWideCharString(unicode, NULL); if (path == NULL) return -1; err = _wstat(path, &wstatbuf); @@ -3736,7 +3736,7 @@ NullImporter_init(NullImporter *self, PyObject *args, PyObject *kwds) return -1; } - path = PyUnicode_AsWideCharString((PyUnicodeObject*)pathobj, NULL); + path = PyUnicode_AsWideCharString(pathobj, NULL); if (path == NULL) return -1; /* see issue1293 and issue3677: -- cgit v1.2.1 From 2ddf7aed96507a54c529355567d663f31aeef92e Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 7 Oct 2010 11:06:49 +0000 Subject: _wrealpath() and _Py_wreadlink() support surrogates (PEP 383) Use _Py_wchar2char() to support surrogate characters in the input path. --- Python/sysmodule.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 97809d27b0..e95a91f042 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1661,16 +1661,17 @@ makeargvobject(int argc, wchar_t **argv) static wchar_t* _wrealpath(const wchar_t *path, wchar_t *resolved_path) { - char cpath[PATH_MAX]; + char *cpath; char cresolved_path[PATH_MAX]; char *res; size_t r; - r = wcstombs(cpath, path, PATH_MAX); - if (r == (size_t)-1 || r >= PATH_MAX) { + cpath = _Py_wchar2char(path); + if (cpath == NULL) { errno = EINVAL; return NULL; } res = realpath(cpath, cresolved_path); + PyMem_Free(cpath); if (res == NULL) return NULL; r = mbstowcs(resolved_path, cresolved_path, PATH_MAX); -- cgit v1.2.1 From b4220c7f86885b91ebc225da4b74a19e1ed747eb Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 7 Oct 2010 21:45:39 +0000 Subject: Create fileutils.c/.h * _Py_fopen() and _Py_stat() come from Python/import.c * (_Py)_wrealpath() comes from Python/sysmodule.c * _Py_char2wchar(), _Py_wchar2char() and _Py_wfopen() come from Modules/main.c * (_Py)_wstat(), (_Py)_wgetcwd(), _Py_wreadlink() come from Modules/getpath.c --- Python/fileutils.c | 758 +++++++++++++++++++++++++++++++++++++++++++++++++++++ Python/import.c | 65 ----- Python/sysmodule.c | 29 +- 3 files changed, 759 insertions(+), 93 deletions(-) create mode 100644 Python/fileutils.c (limited to 'Python') diff --git a/Python/fileutils.c b/Python/fileutils.c new file mode 100644 index 0000000000..ad8b840ef7 --- /dev/null +++ b/Python/fileutils.c @@ -0,0 +1,758 @@ +#include "Python.h" + +#ifdef HAVE_STAT + +/* Decode a byte string from the locale encoding with the + surrogateescape error handler (undecodable bytes are decoded as characters + in range U+DC80..U+DCFF). If a byte sequence can be decoded as a surrogate + character, escape the bytes using the surrogateescape error handler instead + of decoding them. + + Use _Py_wchar2char() to encode the character string back to a byte string. + + Return a pointer to a newly allocated (wide) character string (use + PyMem_Free() to free the memory), or NULL on error (conversion error or + memory error). */ +wchar_t* +_Py_char2wchar(char* arg) +{ + wchar_t *res; +#ifdef HAVE_BROKEN_MBSTOWCS + /* Some platforms have a broken implementation of + * mbstowcs which does not count the characters that + * would result from conversion. Use an upper bound. + */ + size_t argsize = strlen(arg); +#else + size_t argsize = mbstowcs(NULL, arg, 0); +#endif + size_t count; + unsigned char *in; + wchar_t *out; +#ifdef HAVE_MBRTOWC + mbstate_t mbs; +#endif + if (argsize != (size_t)-1) { + res = (wchar_t *)PyMem_Malloc((argsize+1)*sizeof(wchar_t)); + if (!res) + goto oom; + count = mbstowcs(res, arg, argsize+1); + if (count != (size_t)-1) { + wchar_t *tmp; + /* Only use the result if it contains no + surrogate characters. */ + for (tmp = res; *tmp != 0 && + (*tmp < 0xd800 || *tmp > 0xdfff); tmp++) + ; + if (*tmp == 0) + return res; + } + PyMem_Free(res); + } + /* Conversion failed. Fall back to escaping with surrogateescape. */ +#ifdef HAVE_MBRTOWC + /* Try conversion with mbrtwoc (C99), and escape non-decodable bytes. */ + + /* Overallocate; as multi-byte characters are in the argument, the + actual output could use less memory. */ + argsize = strlen(arg) + 1; + res = (wchar_t*)PyMem_Malloc(argsize*sizeof(wchar_t)); + if (!res) goto oom; + in = (unsigned char*)arg; + out = res; + memset(&mbs, 0, sizeof mbs); + while (argsize) { + size_t converted = mbrtowc(out, (char*)in, argsize, &mbs); + if (converted == 0) + /* Reached end of string; null char stored. */ + break; + if (converted == (size_t)-2) { + /* Incomplete character. This should never happen, + since we provide everything that we have - + unless there is a bug in the C library, or I + misunderstood how mbrtowc works. */ + fprintf(stderr, "unexpected mbrtowc result -2\n"); + return NULL; + } + if (converted == (size_t)-1) { + /* Conversion error. Escape as UTF-8b, and start over + in the initial shift state. */ + *out++ = 0xdc00 + *in++; + argsize--; + memset(&mbs, 0, sizeof mbs); + continue; + } + if (*out >= 0xd800 && *out <= 0xdfff) { + /* Surrogate character. Escape the original + byte sequence with surrogateescape. */ + argsize -= converted; + while (converted--) + *out++ = 0xdc00 + *in++; + continue; + } + /* successfully converted some bytes */ + in += converted; + argsize -= converted; + out++; + } +#else + /* Cannot use C locale for escaping; manually escape as if charset + is ASCII (i.e. escape all bytes > 128. This will still roundtrip + correctly in the locale's charset, which must be an ASCII superset. */ + res = PyMem_Malloc((strlen(arg)+1)*sizeof(wchar_t)); + if (!res) goto oom; + in = (unsigned char*)arg; + out = res; + while(*in) + if(*in < 128) + *out++ = *in++; + else + *out++ = 0xdc00 + *in++; + *out = 0; +#endif + return res; +oom: + fprintf(stderr, "out of memory\n"); + return NULL; +} + +/* Encode a (wide) character string to the locale encoding with the + surrogateescape error handler (characters in range U+DC80..U+DCFF are + converted to bytes 0x80..0xFF). + + This function is the reverse of _Py_char2wchar(). + + Return a pointer to a newly allocated byte string (use PyMem_Free() to free + the memory), or NULL on error (conversion error or memory error). */ +char* +_Py_wchar2char(const wchar_t *text) +{ + const size_t len = wcslen(text); + char *result = NULL, *bytes = NULL; + size_t i, size, converted; + wchar_t c, buf[2]; + + /* The function works in two steps: + 1. compute the length of the output buffer in bytes (size) + 2. outputs the bytes */ + size = 0; + buf[1] = 0; + while (1) { + for (i=0; i < len; i++) { + c = text[i]; + if (c >= 0xdc80 && c <= 0xdcff) { + /* UTF-8b surrogate */ + if (bytes != NULL) { + *bytes++ = c - 0xdc00; + size--; + } + else + size++; + continue; + } + else { + buf[0] = c; + if (bytes != NULL) + converted = wcstombs(bytes, buf, size); + else + converted = wcstombs(NULL, buf, 0); + if (converted == (size_t)-1) { + if (result != NULL) + PyMem_Free(result); + return NULL; + } + if (bytes != NULL) { + bytes += converted; + size -= converted; + } + else + size += converted; + } + } + if (result != NULL) { + *bytes = 0; + break; + } + + size += 1; /* nul byte at the end */ + result = PyMem_Malloc(size); + if (result == NULL) + return NULL; + bytes = result; + } + return result; +} + +#if defined(MS_WINDOWS) || defined(HAVE_STAT) +int +_Py_wstat(const wchar_t* path, struct stat *buf) +{ +/* In principle, this should use HAVE__WSTAT, and _wstat + should be detected by autoconf. However, no current + POSIX system provides that function, so testing for + it is pointless. + Not sure whether the MS_WINDOWS guards are necessary: + perhaps for cygwin/mingw builds? +*/ +#ifdef MS_WINDOWS + return _wstat(path, buf); +#else + int err; + char *fname; + fname = _Py_wchar2char(path); + if (fname == NULL) { + errno = EINVAL; + return -1; + } + err = stat(fname, buf); + PyMem_Free(fname); + return err; +#endif +} +#endif + +/* Call _wstat() on Windows, or stat() otherwise. Only fill st_mode + attribute on Windows. Return 0 on success, -1 on stat error or (if + PyErr_Occurred()) unicode error. */ + +int +_Py_stat(PyObject *unicode, struct stat *statbuf) +{ +#ifdef MS_WINDOWS + wchar_t *path; + int err; + struct _stat wstatbuf; + + path = PyUnicode_AsWideCharString(unicode, NULL); + if (path == NULL) + return -1; + err = _wstat(path, &wstatbuf); + PyMem_Free(path); + if (!err) + statbuf->st_mode = wstatbuf.st_mode; + return err; +#else + int ret; + PyObject *bytes = PyUnicode_EncodeFSDefault(unicode); + if (bytes == NULL) + return -1; + ret = stat(PyBytes_AS_STRING(bytes), statbuf); + Py_DECREF(bytes); + return ret; +#endif +} + +FILE * +_Py_wfopen(const wchar_t *path, const wchar_t *mode) +{ +#ifndef MS_WINDOWS + FILE *f; + char *cpath; + char cmode[10]; + size_t r; + r = wcstombs(cmode, mode, 10); + if (r == (size_t)-1 || r >= 10) { + errno = EINVAL; + return NULL; + } + cpath = _Py_wchar2char(path); + if (cpath == NULL) + return NULL; + f = fopen(cpath, cmode); + PyMem_Free(cpath); + return f; +#else + return _wfopen(path, mode); +#endif +} + +/* Call _wfopen() on Windows, or fopen() otherwise. Return the new file + object on success, or NULL if the file cannot be open or (if + PyErr_Occurred()) on unicode error */ + +FILE* +_Py_fopen(PyObject *unicode, const char *mode) +{ +#ifdef MS_WINDOWS + wchar_t *path; + wchar_t wmode[10]; + int usize; + FILE *f; + + usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode, sizeof(wmode)); + if (usize == 0) + return NULL; + + path = PyUnicode_AsWideCharString(unicode, NULL); + if (path == NULL) + return NULL; + f = _wfopen(path, wmode); + PyMem_Free(path); + return f; +#else + FILE *f; + PyObject *bytes = PyUnicode_EncodeFSDefault(unicode); + if (bytes == NULL) + return NULL; + f = fopen(PyBytes_AS_STRING(bytes), mode); + Py_DECREF(bytes); + return f; +#endif +} + +#ifdef HAVE_READLINK +int +_Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz) +{ + char *cpath; + char cbuf[PATH_MAX]; + int res; + size_t r1; + + cpath = _Py_wchar2char(path); + if (cpath == NULL) { + errno = EINVAL; + return -1; + } + res = (int)readlink(cpath, cbuf, PATH_MAX); + PyMem_Free(cpath); + if (res == -1) + return -1; + if (res == PATH_MAX) { + errno = EINVAL; + return -1; + } + cbuf[res] = '\0'; /* buf will be null terminated */ + r1 = mbstowcs(buf, cbuf, bufsiz); + if (r1 == -1) { + errno = EINVAL; + return -1; + } + return (int)r1; +} +#endif + +#ifdef HAVE_REALPATH +wchar_t* +_Py_wrealpath(const wchar_t *path, wchar_t *resolved_path) +{ + char *cpath; + char cresolved_path[PATH_MAX]; + char *res; + size_t r; + cpath = _Py_wchar2char(path); + if (cpath == NULL) { + errno = EINVAL; + return NULL; + } + res = realpath(cpath, cresolved_path); + PyMem_Free(cpath); + if (res == NULL) + return NULL; + r = mbstowcs(resolved_path, cresolved_path, PATH_MAX); + if (r == (size_t)-1 || r >= PATH_MAX) { + errno = EINVAL; + return NULL; + } + return resolved_path; +} +#endif + +wchar_t* +_Py_wgetcwd(wchar_t *buf, size_t size) +{ +#ifdef MS_WINDOWS + return _wgetcwd(buf, size); +#else + char fname[PATH_MAX]; + if (getcwd(fname, PATH_MAX) == NULL) + return NULL; + if (mbstowcs(buf, fname, size) >= size) { + errno = ERANGE; + return NULL; + } + return buf; +#endif +} + +#endif + +#include "Python.h" + +#ifdef HAVE_STAT + +/* Decode a byte string from the locale encoding with the + surrogateescape error handler (undecodable bytes are decoded as characters + in range U+DC80..U+DCFF). If a byte sequence can be decoded as a surrogate + character, escape the bytes using the surrogateescape error handler instead + of decoding them. + + Use _Py_wchar2char() to encode the character string back to a byte string. + + Return a pointer to a newly allocated (wide) character string (use + PyMem_Free() to free the memory), or NULL on error (conversion error or + memory error). */ +wchar_t* +_Py_char2wchar(char* arg) +{ + wchar_t *res; +#ifdef HAVE_BROKEN_MBSTOWCS + /* Some platforms have a broken implementation of + * mbstowcs which does not count the characters that + * would result from conversion. Use an upper bound. + */ + size_t argsize = strlen(arg); +#else + size_t argsize = mbstowcs(NULL, arg, 0); +#endif + size_t count; + unsigned char *in; + wchar_t *out; +#ifdef HAVE_MBRTOWC + mbstate_t mbs; +#endif + if (argsize != (size_t)-1) { + res = (wchar_t *)PyMem_Malloc((argsize+1)*sizeof(wchar_t)); + if (!res) + goto oom; + count = mbstowcs(res, arg, argsize+1); + if (count != (size_t)-1) { + wchar_t *tmp; + /* Only use the result if it contains no + surrogate characters. */ + for (tmp = res; *tmp != 0 && + (*tmp < 0xd800 || *tmp > 0xdfff); tmp++) + ; + if (*tmp == 0) + return res; + } + PyMem_Free(res); + } + /* Conversion failed. Fall back to escaping with surrogateescape. */ +#ifdef HAVE_MBRTOWC + /* Try conversion with mbrtwoc (C99), and escape non-decodable bytes. */ + + /* Overallocate; as multi-byte characters are in the argument, the + actual output could use less memory. */ + argsize = strlen(arg) + 1; + res = (wchar_t*)PyMem_Malloc(argsize*sizeof(wchar_t)); + if (!res) goto oom; + in = (unsigned char*)arg; + out = res; + memset(&mbs, 0, sizeof mbs); + while (argsize) { + size_t converted = mbrtowc(out, (char*)in, argsize, &mbs); + if (converted == 0) + /* Reached end of string; null char stored. */ + break; + if (converted == (size_t)-2) { + /* Incomplete character. This should never happen, + since we provide everything that we have - + unless there is a bug in the C library, or I + misunderstood how mbrtowc works. */ + fprintf(stderr, "unexpected mbrtowc result -2\n"); + return NULL; + } + if (converted == (size_t)-1) { + /* Conversion error. Escape as UTF-8b, and start over + in the initial shift state. */ + *out++ = 0xdc00 + *in++; + argsize--; + memset(&mbs, 0, sizeof mbs); + continue; + } + if (*out >= 0xd800 && *out <= 0xdfff) { + /* Surrogate character. Escape the original + byte sequence with surrogateescape. */ + argsize -= converted; + while (converted--) + *out++ = 0xdc00 + *in++; + continue; + } + /* successfully converted some bytes */ + in += converted; + argsize -= converted; + out++; + } +#else + /* Cannot use C locale for escaping; manually escape as if charset + is ASCII (i.e. escape all bytes > 128. This will still roundtrip + correctly in the locale's charset, which must be an ASCII superset. */ + res = PyMem_Malloc((strlen(arg)+1)*sizeof(wchar_t)); + if (!res) goto oom; + in = (unsigned char*)arg; + out = res; + while(*in) + if(*in < 128) + *out++ = *in++; + else + *out++ = 0xdc00 + *in++; + *out = 0; +#endif + return res; +oom: + fprintf(stderr, "out of memory\n"); + return NULL; +} + +/* Encode a (wide) character string to the locale encoding with the + surrogateescape error handler (characters in range U+DC80..U+DCFF are + converted to bytes 0x80..0xFF). + + This function is the reverse of _Py_char2wchar(). + + Return a pointer to a newly allocated byte string (use PyMem_Free() to free + the memory), or NULL on error (conversion error or memory error). */ +char* +_Py_wchar2char(const wchar_t *text) +{ + const size_t len = wcslen(text); + char *result = NULL, *bytes = NULL; + size_t i, size, converted; + wchar_t c, buf[2]; + + /* The function works in two steps: + 1. compute the length of the output buffer in bytes (size) + 2. outputs the bytes */ + size = 0; + buf[1] = 0; + while (1) { + for (i=0; i < len; i++) { + c = text[i]; + if (c >= 0xdc80 && c <= 0xdcff) { + /* UTF-8b surrogate */ + if (bytes != NULL) { + *bytes++ = c - 0xdc00; + size--; + } + else + size++; + continue; + } + else { + buf[0] = c; + if (bytes != NULL) + converted = wcstombs(bytes, buf, size); + else + converted = wcstombs(NULL, buf, 0); + if (converted == (size_t)-1) { + if (result != NULL) + PyMem_Free(result); + return NULL; + } + if (bytes != NULL) { + bytes += converted; + size -= converted; + } + else + size += converted; + } + } + if (result != NULL) { + *bytes = 0; + break; + } + + size += 1; /* nul byte at the end */ + result = PyMem_Malloc(size); + if (result == NULL) + return NULL; + bytes = result; + } + return result; +} + +#if defined(MS_WINDOWS) || defined(HAVE_STAT) +int +_Py_wstat(const wchar_t* path, struct stat *buf) +{ +/* In principle, this should use HAVE__WSTAT, and _wstat + should be detected by autoconf. However, no current + POSIX system provides that function, so testing for + it is pointless. + Not sure whether the MS_WINDOWS guards are necessary: + perhaps for cygwin/mingw builds? +*/ +#ifdef MS_WINDOWS + return _wstat(path, buf); +#else + int err; + char *fname; + fname = _Py_wchar2char(path); + if (fname == NULL) { + errno = EINVAL; + return -1; + } + err = stat(fname, buf); + PyMem_Free(fname); + return err; +#endif +} +#endif + +/* Call _wstat() on Windows, or stat() otherwise. Only fill st_mode + attribute on Windows. Return 0 on success, -1 on stat error or (if + PyErr_Occurred()) unicode error. */ + +int +_Py_stat(PyObject *unicode, struct stat *statbuf) +{ +#ifdef MS_WINDOWS + wchar_t *path; + int err; + struct _stat wstatbuf; + + path = PyUnicode_AsWideCharString(unicode, NULL); + if (path == NULL) + return -1; + err = _wstat(path, &wstatbuf); + PyMem_Free(path); + if (!err) + statbuf->st_mode = wstatbuf.st_mode; + return err; +#else + int ret; + PyObject *bytes = PyUnicode_EncodeFSDefault(unicode); + if (bytes == NULL) + return -1; + ret = stat(PyBytes_AS_STRING(bytes), statbuf); + Py_DECREF(bytes); + return ret; +#endif +} + +FILE * +_Py_wfopen(const wchar_t *path, const wchar_t *mode) +{ +#ifndef MS_WINDOWS + FILE *f; + char *cpath; + char cmode[10]; + size_t r; + r = wcstombs(cmode, mode, 10); + if (r == (size_t)-1 || r >= 10) { + errno = EINVAL; + return NULL; + } + cpath = _Py_wchar2char(path); + if (cpath == NULL) + return NULL; + f = fopen(cpath, cmode); + PyMem_Free(cpath); + return f; +#else + return _wfopen(path, mode); +#endif +} + +/* Call _wfopen() on Windows, or fopen() otherwise. Return the new file + object on success, or NULL if the file cannot be open or (if + PyErr_Occurred()) on unicode error */ + +FILE* +_Py_fopen(PyObject *unicode, const char *mode) +{ +#ifdef MS_WINDOWS + wchar_t *path; + wchar_t wmode[10]; + int usize; + FILE *f; + + usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode, sizeof(wmode)); + if (usize == 0) + return NULL; + + path = PyUnicode_AsWideCharString(unicode, NULL); + if (path == NULL) + return NULL; + f = _wfopen(path, wmode); + PyMem_Free(path); + return f; +#else + FILE *f; + PyObject *bytes = PyUnicode_EncodeFSDefault(unicode); + if (bytes == NULL) + return NULL; + f = fopen(PyBytes_AS_STRING(bytes), mode); + Py_DECREF(bytes); + return f; +#endif +} + +#ifdef HAVE_READLINK +int +_Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz) +{ + char *cpath; + char cbuf[PATH_MAX]; + int res; + size_t r1; + + cpath = _Py_wchar2char(path); + if (cpath == NULL) { + errno = EINVAL; + return -1; + } + res = (int)readlink(cpath, cbuf, PATH_MAX); + PyMem_Free(cpath); + if (res == -1) + return -1; + if (res == PATH_MAX) { + errno = EINVAL; + return -1; + } + cbuf[res] = '\0'; /* buf will be null terminated */ + r1 = mbstowcs(buf, cbuf, bufsiz); + if (r1 == -1) { + errno = EINVAL; + return -1; + } + return (int)r1; +} +#endif + +#ifdef HAVE_REALPATH +wchar_t* +_Py_wrealpath(const wchar_t *path, wchar_t *resolved_path) +{ + char *cpath; + char cresolved_path[PATH_MAX]; + char *res; + size_t r; + cpath = _Py_wchar2char(path); + if (cpath == NULL) { + errno = EINVAL; + return NULL; + } + res = realpath(cpath, cresolved_path); + PyMem_Free(cpath); + if (res == NULL) + return NULL; + r = mbstowcs(resolved_path, cresolved_path, PATH_MAX); + if (r == (size_t)-1 || r >= PATH_MAX) { + errno = EINVAL; + return NULL; + } + return resolved_path; +} +#endif + +wchar_t* +_Py_wgetcwd(wchar_t *buf, size_t size) +{ +#ifdef MS_WINDOWS + return _wgetcwd(buf, size); +#else + char fname[PATH_MAX]; + if (getcwd(fname, PATH_MAX) == NULL) + return NULL; + if (mbstowcs(buf, fname, size) >= size) { + errno = ERANGE; + return NULL; + } + return buf; +#endif +} + +#endif + diff --git a/Python/import.c b/Python/import.c index ab1615cd05..48fd20594d 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1953,73 +1953,8 @@ case_ok(char *buf, Py_ssize_t len, Py_ssize_t namelen, char *name) #endif } -/* Call _wfopen() on Windows, or fopen() otherwise. Return the new file - object on success, or NULL if the file cannot be open or (if - PyErr_Occurred()) on unicode error */ - -FILE* -_Py_fopen(PyObject *unicode, const char *mode) -{ -#ifdef MS_WINDOWS - wchar_t *path; - wchar_t wmode[10]; - int usize; - FILE *f; - - usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode, sizeof(wmode)); - if (usize == 0) - return NULL; - - path = PyUnicode_AsWideCharString(unicode, NULL); - if (path == NULL) - return NULL; - f = _wfopen(path, wmode); - PyMem_Free(path); - return f; -#else - FILE *f; - PyObject *bytes = PyUnicode_EncodeFSDefault(unicode); - if (bytes == NULL) - return NULL; - f = fopen(PyBytes_AS_STRING(bytes), mode); - Py_DECREF(bytes); - return f; -#endif -} - #ifdef HAVE_STAT -/* Call _wstat() on Windows, or stat() otherwise. Only fill st_mode - attribute on Windows. Return 0 on success, -1 on stat error or (if - PyErr_Occurred()) unicode error. */ - -int -_Py_stat(PyObject *unicode, struct stat *statbuf) -{ -#ifdef MS_WINDOWS - wchar_t *path; - int err; - struct _stat wstatbuf; - - path = PyUnicode_AsWideCharString(unicode, NULL); - if (path == NULL) - return -1; - err = _wstat(path, &wstatbuf); - PyMem_Free(path); - if (!err) - statbuf->st_mode = wstatbuf.st_mode; - return err; -#else - int ret; - PyObject *bytes = PyUnicode_EncodeFSDefault(unicode); - if (bytes == NULL) - return -1; - ret = stat(PyBytes_AS_STRING(bytes), statbuf); - Py_DECREF(bytes); - return ret; -#endif -} - /* Helper to look for __init__.py or __init__.py[co] in potential package */ static int find_init_module(char *buf) diff --git a/Python/sysmodule.c b/Python/sysmodule.c index e95a91f042..1eba28edd1 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1657,32 +1657,6 @@ makeargvobject(int argc, wchar_t **argv) return av; } -#ifdef HAVE_REALPATH -static wchar_t* -_wrealpath(const wchar_t *path, wchar_t *resolved_path) -{ - char *cpath; - char cresolved_path[PATH_MAX]; - char *res; - size_t r; - cpath = _Py_wchar2char(path); - if (cpath == NULL) { - errno = EINVAL; - return NULL; - } - res = realpath(cpath, cresolved_path); - PyMem_Free(cpath); - if (res == NULL) - return NULL; - r = mbstowcs(resolved_path, cresolved_path, PATH_MAX); - if (r == (size_t)-1 || r >= PATH_MAX) { - errno = EINVAL; - return NULL; - } - return resolved_path; -} -#endif - #define _HAVE_SCRIPT_ARGUMENT(argc, argv) \ (argc > 0 && argv0 != NULL && \ wcscmp(argv0, L"-c") != 0 && wcscmp(argv0, L"-m") != 0) @@ -1696,7 +1670,6 @@ sys_update_path(int argc, wchar_t **argv) PyObject *a; PyObject *path; #ifdef HAVE_READLINK - extern int _Py_wreadlink(const wchar_t *, wchar_t *, size_t); wchar_t link[MAXPATHLEN+1]; wchar_t argv0copy[2*MAXPATHLEN+1]; int nr = 0; @@ -1769,7 +1742,7 @@ sys_update_path(int argc, wchar_t **argv) #else /* All other filename syntaxes */ if (_HAVE_SCRIPT_ARGUMENT(argc, argv)) { #if defined(HAVE_REALPATH) - if (_wrealpath(argv0, fullpath)) { + if (_Py_wrealpath(argv0, fullpath)) { argv0 = fullpath; } #endif -- cgit v1.2.1 From 65efe8bb1a2e13924553a2b96df40bd8642128a9 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 7 Oct 2010 21:55:44 +0000 Subject: Ooops, fileutils.c contains twice the same code I suppose that I reapplied my local patch creating Python/fileutils.c whereas the file already existed. --- Python/fileutils.c | 380 ----------------------------------------------------- 1 file changed, 380 deletions(-) (limited to 'Python') diff --git a/Python/fileutils.c b/Python/fileutils.c index ad8b840ef7..0e87860e52 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -376,383 +376,3 @@ _Py_wgetcwd(wchar_t *buf, size_t size) } #endif - -#include "Python.h" - -#ifdef HAVE_STAT - -/* Decode a byte string from the locale encoding with the - surrogateescape error handler (undecodable bytes are decoded as characters - in range U+DC80..U+DCFF). If a byte sequence can be decoded as a surrogate - character, escape the bytes using the surrogateescape error handler instead - of decoding them. - - Use _Py_wchar2char() to encode the character string back to a byte string. - - Return a pointer to a newly allocated (wide) character string (use - PyMem_Free() to free the memory), or NULL on error (conversion error or - memory error). */ -wchar_t* -_Py_char2wchar(char* arg) -{ - wchar_t *res; -#ifdef HAVE_BROKEN_MBSTOWCS - /* Some platforms have a broken implementation of - * mbstowcs which does not count the characters that - * would result from conversion. Use an upper bound. - */ - size_t argsize = strlen(arg); -#else - size_t argsize = mbstowcs(NULL, arg, 0); -#endif - size_t count; - unsigned char *in; - wchar_t *out; -#ifdef HAVE_MBRTOWC - mbstate_t mbs; -#endif - if (argsize != (size_t)-1) { - res = (wchar_t *)PyMem_Malloc((argsize+1)*sizeof(wchar_t)); - if (!res) - goto oom; - count = mbstowcs(res, arg, argsize+1); - if (count != (size_t)-1) { - wchar_t *tmp; - /* Only use the result if it contains no - surrogate characters. */ - for (tmp = res; *tmp != 0 && - (*tmp < 0xd800 || *tmp > 0xdfff); tmp++) - ; - if (*tmp == 0) - return res; - } - PyMem_Free(res); - } - /* Conversion failed. Fall back to escaping with surrogateescape. */ -#ifdef HAVE_MBRTOWC - /* Try conversion with mbrtwoc (C99), and escape non-decodable bytes. */ - - /* Overallocate; as multi-byte characters are in the argument, the - actual output could use less memory. */ - argsize = strlen(arg) + 1; - res = (wchar_t*)PyMem_Malloc(argsize*sizeof(wchar_t)); - if (!res) goto oom; - in = (unsigned char*)arg; - out = res; - memset(&mbs, 0, sizeof mbs); - while (argsize) { - size_t converted = mbrtowc(out, (char*)in, argsize, &mbs); - if (converted == 0) - /* Reached end of string; null char stored. */ - break; - if (converted == (size_t)-2) { - /* Incomplete character. This should never happen, - since we provide everything that we have - - unless there is a bug in the C library, or I - misunderstood how mbrtowc works. */ - fprintf(stderr, "unexpected mbrtowc result -2\n"); - return NULL; - } - if (converted == (size_t)-1) { - /* Conversion error. Escape as UTF-8b, and start over - in the initial shift state. */ - *out++ = 0xdc00 + *in++; - argsize--; - memset(&mbs, 0, sizeof mbs); - continue; - } - if (*out >= 0xd800 && *out <= 0xdfff) { - /* Surrogate character. Escape the original - byte sequence with surrogateescape. */ - argsize -= converted; - while (converted--) - *out++ = 0xdc00 + *in++; - continue; - } - /* successfully converted some bytes */ - in += converted; - argsize -= converted; - out++; - } -#else - /* Cannot use C locale for escaping; manually escape as if charset - is ASCII (i.e. escape all bytes > 128. This will still roundtrip - correctly in the locale's charset, which must be an ASCII superset. */ - res = PyMem_Malloc((strlen(arg)+1)*sizeof(wchar_t)); - if (!res) goto oom; - in = (unsigned char*)arg; - out = res; - while(*in) - if(*in < 128) - *out++ = *in++; - else - *out++ = 0xdc00 + *in++; - *out = 0; -#endif - return res; -oom: - fprintf(stderr, "out of memory\n"); - return NULL; -} - -/* Encode a (wide) character string to the locale encoding with the - surrogateescape error handler (characters in range U+DC80..U+DCFF are - converted to bytes 0x80..0xFF). - - This function is the reverse of _Py_char2wchar(). - - Return a pointer to a newly allocated byte string (use PyMem_Free() to free - the memory), or NULL on error (conversion error or memory error). */ -char* -_Py_wchar2char(const wchar_t *text) -{ - const size_t len = wcslen(text); - char *result = NULL, *bytes = NULL; - size_t i, size, converted; - wchar_t c, buf[2]; - - /* The function works in two steps: - 1. compute the length of the output buffer in bytes (size) - 2. outputs the bytes */ - size = 0; - buf[1] = 0; - while (1) { - for (i=0; i < len; i++) { - c = text[i]; - if (c >= 0xdc80 && c <= 0xdcff) { - /* UTF-8b surrogate */ - if (bytes != NULL) { - *bytes++ = c - 0xdc00; - size--; - } - else - size++; - continue; - } - else { - buf[0] = c; - if (bytes != NULL) - converted = wcstombs(bytes, buf, size); - else - converted = wcstombs(NULL, buf, 0); - if (converted == (size_t)-1) { - if (result != NULL) - PyMem_Free(result); - return NULL; - } - if (bytes != NULL) { - bytes += converted; - size -= converted; - } - else - size += converted; - } - } - if (result != NULL) { - *bytes = 0; - break; - } - - size += 1; /* nul byte at the end */ - result = PyMem_Malloc(size); - if (result == NULL) - return NULL; - bytes = result; - } - return result; -} - -#if defined(MS_WINDOWS) || defined(HAVE_STAT) -int -_Py_wstat(const wchar_t* path, struct stat *buf) -{ -/* In principle, this should use HAVE__WSTAT, and _wstat - should be detected by autoconf. However, no current - POSIX system provides that function, so testing for - it is pointless. - Not sure whether the MS_WINDOWS guards are necessary: - perhaps for cygwin/mingw builds? -*/ -#ifdef MS_WINDOWS - return _wstat(path, buf); -#else - int err; - char *fname; - fname = _Py_wchar2char(path); - if (fname == NULL) { - errno = EINVAL; - return -1; - } - err = stat(fname, buf); - PyMem_Free(fname); - return err; -#endif -} -#endif - -/* Call _wstat() on Windows, or stat() otherwise. Only fill st_mode - attribute on Windows. Return 0 on success, -1 on stat error or (if - PyErr_Occurred()) unicode error. */ - -int -_Py_stat(PyObject *unicode, struct stat *statbuf) -{ -#ifdef MS_WINDOWS - wchar_t *path; - int err; - struct _stat wstatbuf; - - path = PyUnicode_AsWideCharString(unicode, NULL); - if (path == NULL) - return -1; - err = _wstat(path, &wstatbuf); - PyMem_Free(path); - if (!err) - statbuf->st_mode = wstatbuf.st_mode; - return err; -#else - int ret; - PyObject *bytes = PyUnicode_EncodeFSDefault(unicode); - if (bytes == NULL) - return -1; - ret = stat(PyBytes_AS_STRING(bytes), statbuf); - Py_DECREF(bytes); - return ret; -#endif -} - -FILE * -_Py_wfopen(const wchar_t *path, const wchar_t *mode) -{ -#ifndef MS_WINDOWS - FILE *f; - char *cpath; - char cmode[10]; - size_t r; - r = wcstombs(cmode, mode, 10); - if (r == (size_t)-1 || r >= 10) { - errno = EINVAL; - return NULL; - } - cpath = _Py_wchar2char(path); - if (cpath == NULL) - return NULL; - f = fopen(cpath, cmode); - PyMem_Free(cpath); - return f; -#else - return _wfopen(path, mode); -#endif -} - -/* Call _wfopen() on Windows, or fopen() otherwise. Return the new file - object on success, or NULL if the file cannot be open or (if - PyErr_Occurred()) on unicode error */ - -FILE* -_Py_fopen(PyObject *unicode, const char *mode) -{ -#ifdef MS_WINDOWS - wchar_t *path; - wchar_t wmode[10]; - int usize; - FILE *f; - - usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode, sizeof(wmode)); - if (usize == 0) - return NULL; - - path = PyUnicode_AsWideCharString(unicode, NULL); - if (path == NULL) - return NULL; - f = _wfopen(path, wmode); - PyMem_Free(path); - return f; -#else - FILE *f; - PyObject *bytes = PyUnicode_EncodeFSDefault(unicode); - if (bytes == NULL) - return NULL; - f = fopen(PyBytes_AS_STRING(bytes), mode); - Py_DECREF(bytes); - return f; -#endif -} - -#ifdef HAVE_READLINK -int -_Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz) -{ - char *cpath; - char cbuf[PATH_MAX]; - int res; - size_t r1; - - cpath = _Py_wchar2char(path); - if (cpath == NULL) { - errno = EINVAL; - return -1; - } - res = (int)readlink(cpath, cbuf, PATH_MAX); - PyMem_Free(cpath); - if (res == -1) - return -1; - if (res == PATH_MAX) { - errno = EINVAL; - return -1; - } - cbuf[res] = '\0'; /* buf will be null terminated */ - r1 = mbstowcs(buf, cbuf, bufsiz); - if (r1 == -1) { - errno = EINVAL; - return -1; - } - return (int)r1; -} -#endif - -#ifdef HAVE_REALPATH -wchar_t* -_Py_wrealpath(const wchar_t *path, wchar_t *resolved_path) -{ - char *cpath; - char cresolved_path[PATH_MAX]; - char *res; - size_t r; - cpath = _Py_wchar2char(path); - if (cpath == NULL) { - errno = EINVAL; - return NULL; - } - res = realpath(cpath, cresolved_path); - PyMem_Free(cpath); - if (res == NULL) - return NULL; - r = mbstowcs(resolved_path, cresolved_path, PATH_MAX); - if (r == (size_t)-1 || r >= PATH_MAX) { - errno = EINVAL; - return NULL; - } - return resolved_path; -} -#endif - -wchar_t* -_Py_wgetcwd(wchar_t *buf, size_t size) -{ -#ifdef MS_WINDOWS - return _wgetcwd(buf, size); -#else - char fname[PATH_MAX]; - if (getcwd(fname, PATH_MAX) == NULL) - return NULL; - if (mbstowcs(buf, fname, size) >= size) { - errno = ERANGE; - return NULL; - } - return buf; -#endif -} - -#endif - -- cgit v1.2.1 From 0f61f3e424c9ed4231b0337c66877f4be24f641d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 7 Oct 2010 22:09:40 +0000 Subject: Fix fileutils for Windows * Don't define _Py_wstat() on Windows, Windows has its own _wstat() function with a different API (the stat buffer has another type) * Include windows.h --- Python/fileutils.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'Python') diff --git a/Python/fileutils.c b/Python/fileutils.c index 0e87860e52..5d018670e5 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -1,4 +1,7 @@ #include "Python.h" +#ifdef MS_WINDOWS +# include +#endif #ifdef HAVE_STAT @@ -183,10 +186,6 @@ _Py_wchar2char(const wchar_t *text) return result; } -#if defined(MS_WINDOWS) || defined(HAVE_STAT) -int -_Py_wstat(const wchar_t* path, struct stat *buf) -{ /* In principle, this should use HAVE__WSTAT, and _wstat should be detected by autoconf. However, no current POSIX system provides that function, so testing for @@ -194,9 +193,10 @@ _Py_wstat(const wchar_t* path, struct stat *buf) Not sure whether the MS_WINDOWS guards are necessary: perhaps for cygwin/mingw builds? */ -#ifdef MS_WINDOWS - return _wstat(path, buf); -#else +#if defined(HAVE_STAT) && !defined(MS_WINDOWS) +int +_Py_wstat(const wchar_t* path, struct stat *buf) +{ int err; char *fname; fname = _Py_wchar2char(path); @@ -207,7 +207,6 @@ _Py_wstat(const wchar_t* path, struct stat *buf) err = stat(fname, buf); PyMem_Free(fname); return err; -#endif } #endif -- cgit v1.2.1 From 857734b7d26fb28bf7268a1a733155836feaab55 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 7 Oct 2010 22:23:10 +0000 Subject: _Py_stat() and _Py_fopen(): avoid PyUnicode_AsWideCharString() on Windows On Windows, Py_UNICODE is wchar_t, so we can avoid the expensive Py_UNICODE* => wchar_t* conversion. --- Python/fileutils.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) (limited to 'Python') diff --git a/Python/fileutils.c b/Python/fileutils.c index 5d018670e5..bd6ab5d303 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -215,24 +215,19 @@ _Py_wstat(const wchar_t* path, struct stat *buf) PyErr_Occurred()) unicode error. */ int -_Py_stat(PyObject *unicode, struct stat *statbuf) +_Py_stat(PyObject *path, struct stat *statbuf) { #ifdef MS_WINDOWS - wchar_t *path; int err; struct _stat wstatbuf; - path = PyUnicode_AsWideCharString(unicode, NULL); - if (path == NULL) - return -1; - err = _wstat(path, &wstatbuf); - PyMem_Free(path); + err = _wstat(PyUnicode_AS_UNICODE(path), &wstatbuf); if (!err) statbuf->st_mode = wstatbuf.st_mode; return err; #else int ret; - PyObject *bytes = PyUnicode_EncodeFSDefault(unicode); + PyObject *bytes = PyUnicode_EncodeFSDefault(path); if (bytes == NULL) return -1; ret = stat(PyBytes_AS_STRING(bytes), statbuf); @@ -270,27 +265,20 @@ _Py_wfopen(const wchar_t *path, const wchar_t *mode) PyErr_Occurred()) on unicode error */ FILE* -_Py_fopen(PyObject *unicode, const char *mode) +_Py_fopen(PyObject *path, const char *mode) { #ifdef MS_WINDOWS - wchar_t *path; wchar_t wmode[10]; int usize; - FILE *f; usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode, sizeof(wmode)); if (usize == 0) return NULL; - path = PyUnicode_AsWideCharString(unicode, NULL); - if (path == NULL) - return NULL; - f = _wfopen(path, wmode); - PyMem_Free(path); - return f; + return _wfopen(PyUnicode_AS_UNICODE(path), wmode); #else FILE *f; - PyObject *bytes = PyUnicode_EncodeFSDefault(unicode); + PyObject *bytes = PyUnicode_EncodeFSDefault(path); if (bytes == NULL) return NULL; f = fopen(PyBytes_AS_STRING(bytes), mode); -- cgit v1.2.1 From f99397e5074b70e10303516e11f73083e1b9dd5d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 7 Oct 2010 22:29:53 +0000 Subject: _Py_wrealpath() requires the size of the output buffer --- Python/fileutils.c | 5 +++-- Python/sysmodule.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/fileutils.c b/Python/fileutils.c index bd6ab5d303..502868f98c 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -321,7 +321,8 @@ _Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz) #ifdef HAVE_REALPATH wchar_t* -_Py_wrealpath(const wchar_t *path, wchar_t *resolved_path) +_Py_wrealpath(const wchar_t *path, + wchar_t *resolved_path, size_t resolved_path_size) { char *cpath; char cresolved_path[PATH_MAX]; @@ -336,7 +337,7 @@ _Py_wrealpath(const wchar_t *path, wchar_t *resolved_path) PyMem_Free(cpath); if (res == NULL) return NULL; - r = mbstowcs(resolved_path, cresolved_path, PATH_MAX); + r = mbstowcs(resolved_path, cresolved_path, resolved_path_size); if (r == (size_t)-1 || r >= PATH_MAX) { errno = EINVAL; return NULL; diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 1eba28edd1..d02ee5b5c0 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1742,7 +1742,7 @@ sys_update_path(int argc, wchar_t **argv) #else /* All other filename syntaxes */ if (_HAVE_SCRIPT_ARGUMENT(argc, argv)) { #if defined(HAVE_REALPATH) - if (_Py_wrealpath(argv0, fullpath)) { + if (_Py_wrealpath(argv0, fullpath, PATH_MAX)) { argv0 = fullpath; } #endif -- cgit v1.2.1 From 8c367daeb71da022f5b85b9029eb0e01cd4b4ced Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 7 Oct 2010 22:53:43 +0000 Subject: fileutils.c: document which encodings are used --- Python/fileutils.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'Python') diff --git a/Python/fileutils.c b/Python/fileutils.c index 502868f98c..9423cb02f1 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -194,6 +194,9 @@ _Py_wchar2char(const wchar_t *text) perhaps for cygwin/mingw builds? */ #if defined(HAVE_STAT) && !defined(MS_WINDOWS) + +/* Get file status. Encode the path to the locale encoding. */ + int _Py_wstat(const wchar_t* path, struct stat *buf) { @@ -210,9 +213,11 @@ _Py_wstat(const wchar_t* path, struct stat *buf) } #endif -/* Call _wstat() on Windows, or stat() otherwise. Only fill st_mode - attribute on Windows. Return 0 on success, -1 on stat error or (if - PyErr_Occurred()) unicode error. */ +/* Call _wstat() on Windows, or encode the path to the filesystem encoding and + call stat() otherwise. Only fill st_mode attribute on Windows. + + Return 0 on success, -1 on _wstat() / stat() error or (if PyErr_Occurred()) + unicode error. */ int _Py_stat(PyObject *path, struct stat *statbuf) @@ -236,6 +241,9 @@ _Py_stat(PyObject *path, struct stat *statbuf) #endif } +/* Open a file. Use _wfopen() on Windows, encode the path to the locale + encoding and use fopen() otherwise. */ + FILE * _Py_wfopen(const wchar_t *path, const wchar_t *mode) { @@ -260,9 +268,11 @@ _Py_wfopen(const wchar_t *path, const wchar_t *mode) #endif } -/* Call _wfopen() on Windows, or fopen() otherwise. Return the new file - object on success, or NULL if the file cannot be open or (if - PyErr_Occurred()) on unicode error */ +/* Call _wfopen() on Windows, or encode the path to the filesystem encoding and + call fopen() otherwise. + + Return the new file object on success, or NULL if the file cannot be open or + (if PyErr_Occurred()) on unicode error */ FILE* _Py_fopen(PyObject *path, const char *mode) @@ -288,6 +298,10 @@ _Py_fopen(PyObject *path, const char *mode) } #ifdef HAVE_READLINK + +/* Read value of symbolic link. Encode the path to the locale encoding, decode + the result from the locale encoding. */ + int _Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz) { @@ -320,6 +334,10 @@ _Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz) #endif #ifdef HAVE_REALPATH + +/* Return the canonicalized absolute pathname. Encode path to the locale + encoding, decode the result from the locale encoding. */ + wchar_t* _Py_wrealpath(const wchar_t *path, wchar_t *resolved_path, size_t resolved_path_size) @@ -346,6 +364,8 @@ _Py_wrealpath(const wchar_t *path, } #endif +/* Get the current directory. Decode the path from the locale encoding. */ + wchar_t* _Py_wgetcwd(wchar_t *buf, size_t size) { -- cgit v1.2.1 From e0d43318123b33c83747fee9593c834171a9faaf Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sun, 10 Oct 2010 08:37:22 +0000 Subject: Issue #10062: Allow building on platforms which do not have sem_timedwait. --- Python/thread_pthread.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index a529b7a7eb..c007c8b906 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -64,7 +64,8 @@ /* 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) +#if (defined(_POSIX_SEMAPHORES) && !defined(HAVE_BROKEN_POSIX_SEMAPHORES) && \ + defined(HAVE_SEM_TIMEDWAIT)) # define USE_SEMAPHORES #else # undef USE_SEMAPHORES -- cgit v1.2.1 From d098002473ae36aab58993cb3d41dd71cba39561 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 13 Oct 2010 10:48:55 +0000 Subject: ceval.c: catch recursion error on _PyUnicode_AsString(co->co_filename) --- Python/ceval.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 48b5678652..f85f33ad02 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1232,6 +1232,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) PyObject *error_type, *error_value, *error_traceback; PyErr_Fetch(&error_type, &error_value, &error_traceback); filename = _PyUnicode_AsString(co->co_filename); + if (filename == NULL && tstate->overflowed) { + /* maximum recursion depth exceeded */ + goto exit_eval_frame; + } PyErr_Restore(error_type, error_value, error_traceback); } #endif -- cgit v1.2.1 From e27a5e8d1136800ee4395e2172fc51c1dd44d271 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 13 Oct 2010 22:02:27 +0000 Subject: Issue #9992: Remove PYTHONFSENCODING environment variable. --- Python/pythonrun.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index a888a19f20..012c1b85f2 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -980,22 +980,12 @@ initfsencoding(void) char *codeset = NULL; if (Py_FileSystemDefaultEncoding == NULL) { - const char *env_encoding = Py_GETENV("PYTHONFSENCODING"); - if (env_encoding != NULL) { - codeset = get_codec_name(env_encoding); - if (!codeset) { - fprintf(stderr, "PYTHONFSENCODING is not a valid encoding:\n"); - PyErr_Print(); - } - } - if (!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. */ - codeset = get_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. */ + codeset = get_codeset(); if (codeset != NULL) { if (redecode_filenames(codeset)) Py_FatalError("Py_Initialize: can't redecode filenames"); -- cgit v1.2.1 From f371f4fe2a7e4e204e69502cb23fce7963bb0296 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 14 Oct 2010 12:37:19 +0000 Subject: _Py_wgetcwd() decodes the path using _Py_char2wchar() to support surrogates --- Python/fileutils.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/fileutils.c b/Python/fileutils.c index 9423cb02f1..564e2c085b 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -364,7 +364,8 @@ _Py_wrealpath(const wchar_t *path, } #endif -/* Get the current directory. Decode the path from the locale encoding. */ +/* Get the current directory. size is the buffer size in wide characters + including the null character. Decode the path from the locale encoding. */ wchar_t* _Py_wgetcwd(wchar_t *buf, size_t size) @@ -373,12 +374,19 @@ _Py_wgetcwd(wchar_t *buf, size_t size) return _wgetcwd(buf, size); #else char fname[PATH_MAX]; + wchar_t *wname; + if (getcwd(fname, PATH_MAX) == NULL) return NULL; - if (mbstowcs(buf, fname, size) >= size) { - errno = ERANGE; + wname = _Py_char2wchar(fname); + if (wname == NULL) + return NULL; + if (size <= wcslen(wname)) { + PyMem_Free(wname); return NULL; } + wcsncpy(buf, wname, size); + PyMem_Free(wname); return buf; #endif } -- cgit v1.2.1 From c11682af1490a2dbcba37d5a8e9d20ea32154280 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Thu, 14 Oct 2010 21:15:17 +0000 Subject: Explicitly close some files (from issue #10093) --- Python/traceback.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'Python') diff --git a/Python/traceback.c b/Python/traceback.c index 9c9c357c39..558755d209 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -208,6 +208,7 @@ _Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent) PyObject *binary; PyObject *fob = NULL; PyObject *lineobj = NULL; + PyObject *res; char buf[MAXPATHLEN+1]; Py_UNICODE *u, *p; Py_ssize_t len; @@ -253,6 +254,11 @@ _Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent) break; } } + res = PyObject_CallMethod(fob, "close", ""); + if (res) + Py_DECREF(res); + else + PyErr_Clear(); Py_DECREF(fob); if (!lineobj || !PyUnicode_Check(lineobj)) { Py_XDECREF(lineobj); -- cgit v1.2.1 From a22d3119013a15abc89aa99a47eaa0e168feb857 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 15 Oct 2010 11:15:54 +0000 Subject: Mark _Py_char2wchar() input argument as constant --- Python/fileutils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/fileutils.c b/Python/fileutils.c index 564e2c085b..076f510deb 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -17,7 +17,7 @@ PyMem_Free() to free the memory), or NULL on error (conversion error or memory error). */ wchar_t* -_Py_char2wchar(char* arg) +_Py_char2wchar(const char* arg) { wchar_t *res; #ifdef HAVE_BROKEN_MBSTOWCS -- cgit v1.2.1 From 9add3cda9de8882b78ac036ab30a3ed068ec1a73 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 15 Oct 2010 11:16:59 +0000 Subject: redecode_filename(): don't need to initialize variables --- Python/pythonrun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 012c1b85f2..026fcfa8ce 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -725,7 +725,7 @@ static PyObject* redecode_filename(PyObject *file, const char *new_encoding, const char *errors) { - PyObject *file_bytes = NULL, *new_file = NULL; + PyObject *file_bytes, *new_file; file_bytes = PyUnicode_EncodeFSDefault(file); if (file_bytes == NULL) -- cgit v1.2.1 From a47a00d4de1dba7e27eb086e9843d0e1592663ef Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 15 Oct 2010 12:04:23 +0000 Subject: Use locale encoding if Py_FileSystemDefaultEncoding is not set * PyUnicode_EncodeFSDefault(), PyUnicode_DecodeFSDefaultAndSize() and PyUnicode_DecodeFSDefault() use the locale encoding instead of UTF-8 if Py_FileSystemDefaultEncoding is NULL * redecode_filenames() functions and _Py_code_object_list (issue #9630) are no more needed: remove them --- Python/pythonrun.c | 258 ----------------------------------------------------- 1 file changed, 258 deletions(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 026fcfa8ce..73fef75602 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -719,259 +719,6 @@ initmain(void) } } -/* Redecode a filename from the default filesystem encoding (utf-8) to - 'new_encoding' encoding with 'errors' error handler */ -static PyObject* -redecode_filename(PyObject *file, const char *new_encoding, - const char *errors) -{ - PyObject *file_bytes, *new_file; - - file_bytes = PyUnicode_EncodeFSDefault(file); - if (file_bytes == NULL) - return NULL; - new_file = PyUnicode_Decode( - PyBytes_AsString(file_bytes), - PyBytes_GET_SIZE(file_bytes), - new_encoding, - errors); - Py_DECREF(file_bytes); - return new_file; -} - -/* Redecode a path list */ -static int -redecode_path_list(PyObject *paths, - const char *new_encoding, const char *errors) -{ - PyObject *filename, *new_filename; - Py_ssize_t i, size; - - size = PyList_Size(paths); - for (i=0; i < size; i++) { - filename = PyList_GetItem(paths, i); - if (filename == NULL) - return -1; - - new_filename = redecode_filename(filename, new_encoding, errors); - if (new_filename == NULL) - return -1; - if (PyList_SetItem(paths, i, new_filename)) { - Py_DECREF(new_filename); - return -1; - } - } - return 0; -} - -/* Redecode __file__ and __path__ attributes of sys.modules */ -static int -redecode_sys_modules(const char *new_encoding, const char *errors) -{ - PyInterpreterState *interp; - PyObject *modules, *values, *file, *new_file, *paths; - PyObject *iter = NULL, *module = NULL; - - interp = PyThreadState_GET()->interp; - modules = interp->modules; - - values = PyObject_CallMethod(modules, "values", ""); - if (values == NULL) - goto error; - - iter = PyObject_GetIter(values); - Py_DECREF(values); - if (iter == NULL) - goto error; - - while (1) - { - module = PyIter_Next(iter); - if (module == NULL) { - if (PyErr_Occurred()) - goto error; - else - break; - } - - file = PyModule_GetFilenameObject(module); - if (file != NULL) { - new_file = redecode_filename(file, new_encoding, errors); - Py_DECREF(file); - if (new_file == NULL) - goto error; - if (PyObject_SetAttrString(module, "__file__", new_file)) { - Py_DECREF(new_file); - goto error; - } - Py_DECREF(new_file); - } - else - PyErr_Clear(); - - paths = PyObject_GetAttrString(module, "__path__"); - if (paths != NULL) { - if (redecode_path_list(paths, new_encoding, errors)) - goto error; - } - else - PyErr_Clear(); - - Py_CLEAR(module); - } - Py_CLEAR(iter); - return 0; - -error: - Py_XDECREF(iter); - Py_XDECREF(module); - return -1; -} - -/* Redecode sys.path_importer_cache keys */ -static int -redecode_sys_path_importer_cache(const char *new_encoding, const char *errors) -{ - PyObject *path_importer_cache, *items, *item, *path, *importer, *new_path; - PyObject *new_cache = NULL, *iter = NULL; - - path_importer_cache = PySys_GetObject("path_importer_cache"); - if (path_importer_cache == NULL) - goto error; - - items = PyObject_CallMethod(path_importer_cache, "items", ""); - if (items == NULL) - goto error; - - iter = PyObject_GetIter(items); - Py_DECREF(items); - if (iter == NULL) - goto error; - - new_cache = PyDict_New(); - if (new_cache == NULL) - goto error; - - while (1) - { - item = PyIter_Next(iter); - if (item == NULL) { - if (PyErr_Occurred()) - goto error; - else - break; - } - path = PyTuple_GET_ITEM(item, 0); - importer = PyTuple_GET_ITEM(item, 1); - - new_path = redecode_filename(path, new_encoding, errors); - if (new_path == NULL) - goto error; - if (PyDict_SetItem(new_cache, new_path, importer)) { - Py_DECREF(new_path); - goto error; - } - Py_DECREF(new_path); - } - Py_CLEAR(iter); - if (PySys_SetObject("path_importer_cache", new_cache)) - goto error; - Py_CLEAR(new_cache); - return 0; - -error: - Py_XDECREF(iter); - Py_XDECREF(new_cache); - return -1; -} - -/* Redecode co_filename attribute of all code objects */ -static int -redecode_code_objects(const char *new_encoding, const char *errors) -{ - Py_ssize_t i, len; - PyCodeObject *co; - PyObject *ref, *new_file; - - len = Py_SIZE(_Py_code_object_list); - for (i=0; i < len; i++) { - ref = PyList_GET_ITEM(_Py_code_object_list, i); - co = (PyCodeObject *)PyWeakref_GetObject(ref); - if ((PyObject*)co == Py_None) - continue; - if (co == NULL) - return -1; - - new_file = redecode_filename(co->co_filename, new_encoding, errors); - if (new_file == NULL) - return -1; - Py_DECREF(co->co_filename); - co->co_filename = new_file; - } - Py_CLEAR(_Py_code_object_list); - return 0; -} - -/* Redecode the filenames of all modules (__file__ and __path__ attributes), - all code objects (co_filename attribute), sys.path, sys.meta_path, - sys.executable and sys.path_importer_cache (keys) when the filesystem - encoding changes from the default encoding (utf-8) to new_encoding */ -static int -redecode_filenames(const char *new_encoding) -{ - char *errors; - PyObject *paths, *executable, *new_executable; - - /* PyUnicode_DecodeFSDefault() and PyUnicode_EncodeFSDefault() do already - use utf-8 if Py_FileSystemDefaultEncoding is NULL */ - if (strcmp(new_encoding, "utf-8") == 0) - return 0; - - if (strcmp(new_encoding, "mbcs") != 0) - errors = "surrogateescape"; - else - errors = NULL; - - /* sys.modules */ - if (redecode_sys_modules(new_encoding, errors)) - return -1; - - /* sys.path and sys.meta_path */ - paths = PySys_GetObject("path"); - if (paths != NULL) { - if (redecode_path_list(paths, new_encoding, errors)) - return -1; - } - paths = PySys_GetObject("meta_path"); - if (paths != NULL) { - if (redecode_path_list(paths, new_encoding, errors)) - return -1; - } - - /* sys.executable */ - executable = PySys_GetObject("executable"); - if (executable == NULL) - return -1; - new_executable = redecode_filename(executable, new_encoding, errors); - if (new_executable == NULL) - return -1; - if (PySys_SetObject("executable", new_executable)) { - Py_DECREF(new_executable); - return -1; - } - Py_DECREF(new_executable); - - /* sys.path_importer_cache */ - if (redecode_sys_path_importer_cache(new_encoding, errors)) - return -1; - - /* code objects */ - if (redecode_code_objects(new_encoding, errors)) - return -1; - - return 0; -} - static void initfsencoding(void) { @@ -987,11 +734,8 @@ initfsencoding(void) stdin and stdout if these are terminals. */ codeset = get_codeset(); if (codeset != NULL) { - if (redecode_filenames(codeset)) - Py_FatalError("Py_Initialize: can't redecode filenames"); Py_FileSystemDefaultEncoding = codeset; Py_HasFileSystemDefaultEncoding = 0; - Py_CLEAR(_Py_code_object_list); return; } else { fprintf(stderr, "Unable to get the locale encoding:\n"); @@ -1004,8 +748,6 @@ initfsencoding(void) } #endif - Py_CLEAR(_Py_code_object_list); - /* the encoding is mbcs, utf-8 or ascii */ codec = _PyCodec_Lookup(Py_FileSystemDefaultEncoding); if (!codec) { -- cgit v1.2.1 From 38c0c00de5a7a13b563955c5d54f5ddee1f2ba64 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 15 Oct 2010 12:48:01 +0000 Subject: imp.load_dynamic() uses PyUnicode_FSConverter() to support surrogates in the library path. --- Python/import.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 48fd20594d..b8bcabda28 100644 --- a/Python/import.c +++ b/Python/import.c @@ -3326,24 +3326,24 @@ static PyObject * imp_load_dynamic(PyObject *self, PyObject *args) { char *name; + PyObject *pathbytes; char *pathname; PyObject *fob = NULL; PyObject *m; FILE *fp = NULL; - if (!PyArg_ParseTuple(args, "ses|O:load_dynamic", - &name, - Py_FileSystemDefaultEncoding, &pathname, - &fob)) + if (!PyArg_ParseTuple(args, "sO&|O:load_dynamic", + &name, PyUnicode_FSConverter, &pathbytes, &fob)) return NULL; + pathname = PyBytes_AS_STRING(pathbytes); if (fob) { fp = get_file(pathname, fob, "r"); if (fp == NULL) { - PyMem_Free(pathname); + Py_DECREF(pathbytes); return NULL; } } m = _PyImport_LoadDynamicModule(name, pathname, fp); - PyMem_Free(pathname); + Py_DECREF(pathbytes); if (fp) fclose(fp); return m; -- cgit v1.2.1 From 793fde8a945945f43b2419a55f64ade63a08ad83 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 15 Oct 2010 20:34:32 +0000 Subject: imp.cache_from_source() uses PyUnicode_FSConverter() to support surrogates in module path --- Python/import.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index b8bcabda28..6a4143955e 100644 --- a/Python/import.c +++ b/Python/import.c @@ -3460,21 +3460,24 @@ imp_cache_from_source(PyObject *self, PyObject *args, PyObject *kws) static char *kwlist[] = {"path", "debug_override", NULL}; char buf[MAXPATHLEN+1]; - char *pathname, *cpathname; + PyObject *pathbytes; + char *cpathname; PyObject *debug_override = Py_None; int debug = !Py_OptimizeFlag; if (!PyArg_ParseTupleAndKeywords( - args, kws, "es|O", kwlist, - Py_FileSystemDefaultEncoding, &pathname, &debug_override)) + args, kws, "O&|O", kwlist, + PyUnicode_FSConverter, &pathbytes, &debug_override)) return NULL; if (debug_override != Py_None) if ((debug = PyObject_IsTrue(debug_override)) < 0) return NULL; - cpathname = make_compiled_pathname(pathname, buf, MAXPATHLEN+1, debug); - PyMem_Free(pathname); + cpathname = make_compiled_pathname( + PyBytes_AS_STRING(pathbytes), + buf, MAXPATHLEN+1, debug); + Py_DECREF(pathbytes); if (cpathname == NULL) { PyErr_Format(PyExc_SystemError, "path buffer too short"); -- cgit v1.2.1 From 945d344cd37199efcb802161c0f813628311195f Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 15 Oct 2010 22:43:10 +0000 Subject: imp_load_module() uses PyUnicode_FSConverter() to support surrogates in module path --- Python/import.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 6a4143955e..857529370f 100644 --- a/Python/import.c +++ b/Python/import.c @@ -3380,16 +3380,16 @@ imp_load_module(PyObject *self, PyObject *args) { char *name; PyObject *fob; - char *pathname; + PyObject *pathname; PyObject * ret; char *suffix; /* Unused */ char *mode; int type; FILE *fp; - if (!PyArg_ParseTuple(args, "sOes(ssi):load_module", + if (!PyArg_ParseTuple(args, "sOO&(ssi):load_module", &name, &fob, - Py_FileSystemDefaultEncoding, &pathname, + PyUnicode_FSConverter, &pathname, &suffix, &mode, &type)) return NULL; if (*mode) { @@ -3400,7 +3400,7 @@ imp_load_module(PyObject *self, PyObject *args) if (!(*mode == 'r' || *mode == 'U') || strchr(mode, '+')) { PyErr_Format(PyExc_ValueError, "invalid file open mode %.200s", mode); - PyMem_Free(pathname); + Py_DECREF(pathname); return NULL; } } @@ -3409,12 +3409,12 @@ imp_load_module(PyObject *self, PyObject *args) else { fp = get_file(NULL, fob, mode); if (fp == NULL) { - PyMem_Free(pathname); + Py_DECREF(pathname); return NULL; } } - ret = load_module(name, fp, pathname, type, NULL); - PyMem_Free(pathname); + ret = load_module(name, fp, PyBytes_AS_STRING(pathname), type, NULL); + Py_DECREF(pathname); if (fp) fclose(fp); return ret; -- cgit v1.2.1 From a60b1fe637f31ae904edfd9a8d6bf0f27876cf19 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 15 Oct 2010 22:46:07 +0000 Subject: Fix imp_cache_from_source(): Decode make_compiled_pathname() result from the filesystem encoding instead of utf-8. imp_cache_from_source() encodes the input path to filesystem encoding and this path is passed to make_compiled_pathname(). --- Python/import.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 857529370f..94363deae0 100644 --- a/Python/import.c +++ b/Python/import.c @@ -3483,7 +3483,7 @@ imp_cache_from_source(PyObject *self, PyObject *args, PyObject *kws) PyErr_Format(PyExc_SystemError, "path buffer too short"); return NULL; } - return PyUnicode_FromString(buf); + return PyUnicode_DecodeFSDefault(buf); } PyDoc_STRVAR(doc_cache_from_source, -- cgit v1.2.1 From 0744ba041925372096a9b79325943fc746782d81 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Sat, 16 Oct 2010 01:04:07 +0000 Subject: First (uncontroversial) part of issue 9807. * Expose the build flags to Python as sys.abiflags * Shared library libpythonX.Y.so * python-config --abiflags * Make two distutils tests that failed with --enable-shared (even before this patch) succeed. * Fix a few small style issues. --- Python/sysmodule.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index d02ee5b5c0..6c563f0d37 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1520,6 +1520,10 @@ _PySys_Init(void) PyLong_FromVoidPtr(PyWin_DLLhModule)); SET_SYS_FROM_STRING("winver", PyUnicode_FromString(PyWin_DLLVersionString)); +#endif +#ifdef ABIFLAGS + SET_SYS_FROM_STRING("abiflags", + PyUnicode_FromString(ABIFLAGS)); #endif if (warnoptions == NULL) { warnoptions = PyList_New(0); -- cgit v1.2.1 From a0097f9441d3b4626a01e5a827a4af80f4e4618b Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 16 Oct 2010 03:12:39 +0000 Subject: fix refleak --- Python/import.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 94363deae0..5a09c9759c 100644 --- a/Python/import.c +++ b/Python/import.c @@ -3462,7 +3462,7 @@ imp_cache_from_source(PyObject *self, PyObject *args, PyObject *kws) char buf[MAXPATHLEN+1]; PyObject *pathbytes; char *cpathname; - PyObject *debug_override = Py_None; + PyObject *debug_override = NULL; int debug = !Py_OptimizeFlag; if (!PyArg_ParseTupleAndKeywords( @@ -3470,9 +3470,11 @@ imp_cache_from_source(PyObject *self, PyObject *args, PyObject *kws) PyUnicode_FSConverter, &pathbytes, &debug_override)) return NULL; - if (debug_override != Py_None) - if ((debug = PyObject_IsTrue(debug_override)) < 0) - return NULL; + if (debug_override != NULL && + (debug = PyObject_IsTrue(debug_override)) < 0) { + Py_DECREF(pathbytes); + return NULL; + } cpathname = make_compiled_pathname( PyBytes_AS_STRING(pathbytes), -- cgit v1.2.1 From 75d40e99d8063ff7b7163e6ccbcf23a44848538b Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 16 Oct 2010 03:45:45 +0000 Subject: don't identify the toplevel namespace by name #9997 --- Python/symtable.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/symtable.c b/Python/symtable.c index f75b9c997f..4a6c52335b 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -924,7 +924,7 @@ symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block, st->st_cur = ste_new(st, name, block, ast, lineno, col_offset); if (st->st_cur == NULL) return 0; - if (name == GET_IDENTIFIER(top)) + if (block == ModuleBlock) st->st_global = st->st_cur->ste_symbols; if (prev) { if (PyList_Append(prev->ste_children, -- cgit v1.2.1 From 24c7fa3b4d2daf8a3b9d1b3c143e6a55b5b2b4d5 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 16 Oct 2010 13:14:10 +0000 Subject: Issue #9713, #10114: Parser functions (eg. PyParser_ASTFromFile) expects filenames encoded to the filesystem encoding with surrogateescape error handler (to support undecodable bytes), instead of UTF-8 in strict mode. --- Python/ast.c | 7 ++++++- Python/bltinmodule.c | 33 ++++++++++++++++++++++----------- Python/compile.c | 2 +- Python/pythonrun.c | 12 +++++++++--- Python/traceback.c | 35 +++++++++++++++++++++++++---------- 5 files changed, 63 insertions(+), 26 deletions(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index 38643f6a3b..b9beef88ef 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -102,6 +102,7 @@ static void ast_error_finish(const char *filename) { PyObject *type, *value, *tback, *errstr, *offset, *loc, *tmp; + PyObject *filename_obj; long lineno; assert(PyErr_Occurred()); @@ -130,7 +131,11 @@ ast_error_finish(const char *filename) Py_INCREF(Py_None); loc = Py_None; } - tmp = Py_BuildValue("(zlOO)", filename, lineno, offset, loc); + filename_obj = PyUnicode_DecodeFSDefault(filename); + if (filename_obj != NULL) + tmp = Py_BuildValue("(NlOO)", filename_obj, lineno, offset, loc); + else + tmp = NULL; Py_DECREF(loc); if (!tmp) { Py_DECREF(errstr); diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 2e8d6e21b3..ece2a3728e 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -524,6 +524,7 @@ static PyObject * builtin_compile(PyObject *self, PyObject *args, PyObject *kwds) { char *str; + PyObject *filename_obj; char *filename; char *startstr; int mode = -1; @@ -535,12 +536,16 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds) static char *kwlist[] = {"source", "filename", "mode", "flags", "dont_inherit", NULL}; int start[] = {Py_file_input, Py_eval_input, Py_single_input}; + PyObject *result; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oss|ii:compile", - kwlist, &cmd, &filename, &startstr, - &supplied_flags, &dont_inherit)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&s|ii:compile", kwlist, + &cmd, + PyUnicode_FSConverter, &filename_obj, + &startstr, &supplied_flags, + &dont_inherit)) return NULL; + filename = PyBytes_AS_STRING(filename_obj); cf.cf_flags = supplied_flags | PyCF_SOURCE_IS_UTF8; if (supplied_flags & @@ -548,7 +553,7 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds) { PyErr_SetString(PyExc_ValueError, "compile(): unrecognised flags"); - return NULL; + goto error; } /* XXX Warn if (supplied_flags & PyCF_MASK_OBSOLETE) != 0? */ @@ -565,14 +570,13 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds) else { PyErr_SetString(PyExc_ValueError, "compile() arg 3 must be 'exec', 'eval' or 'single'"); - return NULL; + goto error; } is_ast = PyAST_Check(cmd); if (is_ast == -1) - return NULL; + goto error; if (is_ast) { - PyObject *result; if (supplied_flags & PyCF_ONLY_AST) { Py_INCREF(cmd); result = cmd; @@ -585,20 +589,27 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds) mod = PyAST_obj2mod(cmd, arena, mode); if (mod == NULL) { PyArena_Free(arena); - return NULL; + goto error; } result = (PyObject*)PyAST_Compile(mod, filename, &cf, arena); PyArena_Free(arena); } - return result; + goto finally; } str = source_as_string(cmd, "compile", "string, bytes, AST or code", &cf); if (str == NULL) - return NULL; + goto error; - return Py_CompileStringFlags(str, filename, start[mode], &cf); + result = Py_CompileStringFlags(str, filename, start[mode], &cf); + goto finally; + +error: + result = NULL; +finally: + Py_DECREF(filename_obj); + return result; } PyDoc_STRVAR(compile_doc, diff --git a/Python/compile.c b/Python/compile.c index d29e48c47a..1ff085909c 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3942,7 +3942,7 @@ makecode(struct compiler *c, struct assembler *a) freevars = dict_keys_inorder(c->u->u_freevars, PyTuple_Size(cellvars)); if (!freevars) goto error; - filename = PyUnicode_FromString(c->c_filename); + filename = PyUnicode_DecodeFSDefault(c->c_filename); if (!filename) goto error; diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 73fef75602..8c535fd8a6 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1213,7 +1213,7 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, d = PyModule_GetDict(m); if (PyDict_GetItemString(d, "__file__") == NULL) { PyObject *f; - f = PyUnicode_FromString(filename); + f = PyUnicode_DecodeFSDefault(filename); if (f == NULL) return -1; if (PyDict_SetItemString(d, "__file__", f) < 0) { @@ -1968,7 +1968,9 @@ err_input(perrdetail *err) { PyObject *v, *w, *errtype, *errtext; PyObject *msg_obj = NULL; + PyObject *filename; char *msg = NULL; + errtype = PyExc_SyntaxError; switch (err->error) { case E_ERROR: @@ -2052,8 +2054,12 @@ err_input(perrdetail *err) errtext = PyUnicode_DecodeUTF8(err->text, strlen(err->text), "replace"); } - v = Py_BuildValue("(ziiN)", err->filename, - err->lineno, err->offset, errtext); + filename = PyUnicode_DecodeFSDefault(err->filename); + if (filename != NULL) + v = Py_BuildValue("(NiiN)", filename, + err->lineno, err->offset, errtext); + else + v = NULL; if (v != NULL) { if (msg_obj) w = Py_BuildValue("(OO)", msg_obj, v); diff --git a/Python/traceback.c b/Python/traceback.c index 558755d209..ab10cfd161 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -142,16 +142,19 @@ _Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject * Py_ssize_t npath; size_t taillen; PyObject *syspath; - const char* path; + PyObject *path; const char* tail; + PyObject *filebytes; const char* filepath; Py_ssize_t len; + PyObject* result; - filepath = _PyUnicode_AsString(filename); - if (filepath == NULL) { + filebytes = PyUnicode_EncodeFSDefault(filename); + if (filebytes == NULL) { PyErr_Clear(); return NULL; } + filepath = PyBytes_AS_STRING(filebytes); /* Search tail of filename in sys.path before giving up */ tail = strrchr(filepath, SEP); @@ -163,7 +166,7 @@ _Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject * syspath = PySys_GetObject("path"); if (syspath == NULL || !PyList_Check(syspath)) - return NULL; + goto error; npath = PyList_Size(syspath); for (i = 0; i < npath; i++) { @@ -174,14 +177,18 @@ _Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject * } if (!PyUnicode_Check(v)) continue; - path = _PyUnicode_AsStringAndSize(v, &len); + path = PyUnicode_EncodeFSDefault(v); if (path == NULL) { PyErr_Clear(); continue; } - if (len + 1 + (Py_ssize_t)taillen >= (Py_ssize_t)namelen - 1) + len = PyBytes_GET_SIZE(path); + if (len + 1 + (Py_ssize_t)taillen >= (Py_ssize_t)namelen - 1) { + Py_DECREF(path); continue; /* Too long */ - strcpy(namebuf, path); + } + strcpy(namebuf, PyBytes_AS_STRING(path)); + Py_DECREF(path); if (strlen(namebuf) != len) continue; /* v contains '\0' */ if (len > 0 && namebuf[len-1] != SEP) @@ -189,11 +196,19 @@ _Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject * strcpy(namebuf+len, tail); binary = PyObject_CallMethod(io, "open", "ss", namebuf, "rb"); - if (binary != NULL) - return binary; + if (binary != NULL) { + result = binary; + goto finally; + } PyErr_Clear(); } - return NULL; + goto error; + +error: + result = NULL; +finally: + Py_DECREF(filebytes); + return result; } int -- cgit v1.2.1 From a92ba0800250ece57c8b4cfa5f8d8fc1558fd024 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 16 Oct 2010 13:42:53 +0000 Subject: Fix ast_error_finish() and err_input(): filename can be NULL Fix my previous commit (r85569). --- Python/ast.c | 7 ++++++- Python/pythonrun.c | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index b9beef88ef..d1aa61640a 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -131,7 +131,12 @@ ast_error_finish(const char *filename) Py_INCREF(Py_None); loc = Py_None; } - filename_obj = PyUnicode_DecodeFSDefault(filename); + if (filename != NULL) + filename_obj = PyUnicode_DecodeFSDefault(filename); + else { + Py_INCREF(Py_None); + filename_obj = Py_None; + } if (filename_obj != NULL) tmp = Py_BuildValue("(NlOO)", filename_obj, lineno, offset, loc); else diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 8c535fd8a6..f72c9d705a 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -2054,7 +2054,12 @@ err_input(perrdetail *err) errtext = PyUnicode_DecodeUTF8(err->text, strlen(err->text), "replace"); } - filename = PyUnicode_DecodeFSDefault(err->filename); + if (err->filename != NULL) + filename = PyUnicode_DecodeFSDefault(err->filename); + else { + Py_INCREF(Py_None); + filename = Py_None; + } if (filename != NULL) v = Py_BuildValue("(NiiN)", filename, err->lineno, err->offset, errtext); -- cgit v1.2.1 From f086369a465ab84e07afcb703c0c130189c0f863 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 16 Oct 2010 22:47:37 +0000 Subject: _Py_wreadlink() uses _Py_char2wchar() to decode the result, to support surrogate characters. --- Python/fileutils.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/fileutils.c b/Python/fileutils.c index 076f510deb..cfafd865c5 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -307,6 +307,7 @@ _Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz) { char *cpath; char cbuf[PATH_MAX]; + wchar_t *wbuf; int res; size_t r1; @@ -324,11 +325,15 @@ _Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz) return -1; } cbuf[res] = '\0'; /* buf will be null terminated */ - r1 = mbstowcs(buf, cbuf, bufsiz); - if (r1 == -1) { + wbuf = _Py_char2wchar(cbuf); + r1 = wcslen(wbuf); + if (bufsiz <= r1) { + PyMem_Free(wbuf); errno = EINVAL; return -1; } + wcsncpy(buf, wbuf, bufsiz); + PyMem_Free(wbuf); return (int)r1; } #endif -- cgit v1.2.1 From 560612a9ad4dc53b764e2e0cc1137c7687f1d2c3 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 16 Oct 2010 22:52:09 +0000 Subject: _Py_wreadlink(): catch _Py_char2wchar() failure --- Python/fileutils.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Python') diff --git a/Python/fileutils.c b/Python/fileutils.c index cfafd865c5..147636f2c7 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -326,6 +326,10 @@ _Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz) } cbuf[res] = '\0'; /* buf will be null terminated */ wbuf = _Py_char2wchar(cbuf); + if (wbuf == NULL) { + errno = EINVAL; + return -1; + } r1 = wcslen(wbuf); if (bufsiz <= r1) { PyMem_Free(wbuf); -- cgit v1.2.1 From 4e7ceabd43ad27956ac0014ce5ff16995fd5c03d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 16 Oct 2010 22:55:47 +0000 Subject: _Py_wrealpath() uses _Py_char2wchar() to decode the result, to support surrogate characters. --- Python/fileutils.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/fileutils.c b/Python/fileutils.c index 147636f2c7..b8910b7be6 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -353,6 +353,7 @@ _Py_wrealpath(const wchar_t *path, { char *cpath; char cresolved_path[PATH_MAX]; + wchar_t *wresolved_path; char *res; size_t r; cpath = _Py_wchar2char(path); @@ -364,11 +365,20 @@ _Py_wrealpath(const wchar_t *path, PyMem_Free(cpath); if (res == NULL) return NULL; - r = mbstowcs(resolved_path, cresolved_path, resolved_path_size); - if (r == (size_t)-1 || r >= PATH_MAX) { + + wresolved_path = _Py_char2wchar(cresolved_path); + if (wresolved_path == NULL) { + errno = EINVAL; + return NULL; + } + r = wcslen(wresolved_path); + if (resolved_path_size <= r) { + PyMem_Free(wresolved_path); errno = EINVAL; return NULL; } + wcsncpy(resolved_path, wresolved_path, resolved_path_size); + PyMem_Free(wresolved_path); return resolved_path; } #endif -- cgit v1.2.1 From bd3b71a7bb5fcf80de1339fe71c85918a44fb7e3 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 16 Oct 2010 23:16:16 +0000 Subject: Add an optional size argument to _Py_char2wchar() _Py_char2wchar() callers usually need the result size in characters. Since it's trivial to compute it in _Py_char2wchar() (O(1) whereas wcslen() is O(n)), add an option to get it. --- Python/fileutils.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'Python') diff --git a/Python/fileutils.c b/Python/fileutils.c index b8910b7be6..03fc0cb79d 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -13,11 +13,12 @@ Use _Py_wchar2char() to encode the character string back to a byte string. - Return a pointer to a newly allocated (wide) character string (use - PyMem_Free() to free the memory), or NULL on error (conversion error or - memory error). */ + Return a pointer to a newly allocated wide character string (use + PyMem_Free() to free the memory) and write the number of written wide + characters excluding the null character into *size if size is not NULL, or + NULL on error (conversion error or memory error). */ wchar_t* -_Py_char2wchar(const char* arg) +_Py_char2wchar(const char* arg, size_t *size) { wchar_t *res; #ifdef HAVE_BROKEN_MBSTOWCS @@ -47,8 +48,11 @@ _Py_char2wchar(const char* arg) for (tmp = res; *tmp != 0 && (*tmp < 0xd800 || *tmp > 0xdfff); tmp++) ; - if (*tmp == 0) + if (*tmp == 0) { + if (size != NULL) + *size = count; return res; + } } PyMem_Free(res); } @@ -113,6 +117,8 @@ _Py_char2wchar(const char* arg) *out++ = 0xdc00 + *in++; *out = 0; #endif + if (size != NULL) + *size = out - res; return res; oom: fprintf(stderr, "out of memory\n"); @@ -325,12 +331,11 @@ _Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz) return -1; } cbuf[res] = '\0'; /* buf will be null terminated */ - wbuf = _Py_char2wchar(cbuf); + wbuf = _Py_char2wchar(cbuf, &r1); if (wbuf == NULL) { errno = EINVAL; return -1; } - r1 = wcslen(wbuf); if (bufsiz <= r1) { PyMem_Free(wbuf); errno = EINVAL; @@ -366,12 +371,11 @@ _Py_wrealpath(const wchar_t *path, if (res == NULL) return NULL; - wresolved_path = _Py_char2wchar(cresolved_path); + wresolved_path = _Py_char2wchar(cresolved_path, &r); if (wresolved_path == NULL) { errno = EINVAL; return NULL; } - r = wcslen(wresolved_path); if (resolved_path_size <= r) { PyMem_Free(wresolved_path); errno = EINVAL; @@ -394,13 +398,14 @@ _Py_wgetcwd(wchar_t *buf, size_t size) #else char fname[PATH_MAX]; wchar_t *wname; + size_t len; if (getcwd(fname, PATH_MAX) == NULL) return NULL; - wname = _Py_char2wchar(fname); + wname = _Py_char2wchar(fname, &len); if (wname == NULL) return NULL; - if (size <= wcslen(wname)) { + if (size <= len) { PyMem_Free(wname); return NULL; } -- cgit v1.2.1 From fd287a210024b8e10ed205fba01ece1fbcabc5ef Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 17 Oct 2010 01:24:53 +0000 Subject: _PyImport_FixupExtension() and _PyImport_FindExtension() uses FS encoding * Rename _PyImport_FindExtension() to _PyImport_FindExtensionUnicode(): the filename becomes a Unicode object instead of byte string * Rename _PyImport_FixupExtension() to _PyImport_FixupExtensionUnicode(): the filename becomes a Unicode object instead of byte string --- Python/import.c | 44 ++++++++++++++++++++++++++++++++++---------- Python/importdl.c | 34 ++++++++++++++++++++++++---------- Python/pythonrun.c | 8 ++++---- 3 files changed, 62 insertions(+), 24 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 5a09c9759c..6715dc929d 100644 --- a/Python/import.c +++ b/Python/import.c @@ -121,7 +121,7 @@ typedef unsigned short mode_t; static long pyc_magic = MAGIC; static const char *pyc_tag = TAG; -/* See _PyImport_FixupExtension() below */ +/* See _PyImport_FixupExtensionUnicode() below */ static PyObject *extensions = NULL; /* This table is defined in config.c: */ @@ -561,10 +561,10 @@ PyImport_GetMagicTag(void) 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() + dictionary is stored by calling _PyImport_FixupExtensionUnicode() immediately after the module initialization function succeeds. A copy can be retrieved from there by calling - _PyImport_FindExtension(). + _PyImport_FindExtensionUnicode(). Modules which do support multiple initialization set their m_size field to a non-negative number (indicating the size of the @@ -573,7 +573,7 @@ PyImport_GetMagicTag(void) */ int -_PyImport_FixupExtension(PyObject *mod, char *name, char *filename) +_PyImport_FixupExtensionUnicode(PyObject *mod, char *name, PyObject *filename) { PyObject *modules, *dict; struct PyModuleDef *def; @@ -613,18 +613,31 @@ _PyImport_FixupExtension(PyObject *mod, char *name, char *filename) if (def->m_base.m_copy == NULL) return -1; } - PyDict_SetItemString(extensions, filename, (PyObject*)def); + PyDict_SetItem(extensions, filename, (PyObject*)def); return 0; } +int +_PyImport_FixupBuiltin(PyObject *mod, char *name) +{ + int res; + PyObject *filename; + filename = PyUnicode_FromString(name); + if (filename == NULL) + return -1; + res = _PyImport_FixupExtensionUnicode(mod, name, filename); + Py_DECREF(filename); + return res; +} + PyObject * -_PyImport_FindExtension(char *name, char *filename) +_PyImport_FindExtensionUnicode(char *name, PyObject *filename) { PyObject *mod, *mdict; PyModuleDef* def; if (extensions == NULL) return NULL; - def = (PyModuleDef*)PyDict_GetItemString(extensions, filename); + def = (PyModuleDef*)PyDict_GetItem(extensions, filename); if (def == NULL) return NULL; if (def->m_size == -1) { @@ -655,12 +668,23 @@ _PyImport_FindExtension(char *name, char *filename) return NULL; } if (Py_VerboseFlag) - PySys_WriteStderr("import %s # previously loaded (%s)\n", + PySys_FormatStderr("import %s # previously loaded (%U)\n", name, filename); return mod; } +PyObject * +_PyImport_FindBuiltin(char *name) +{ + PyObject *res, *filename; + filename = PyUnicode_FromString(name); + if (filename == NULL) + return NULL; + res = _PyImport_FindExtensionUnicode(name, filename); + Py_DECREF(filename); + return res; +} /* Get the module object corresponding to a module name. First check the modules dictionary if there's one there, @@ -2121,7 +2145,7 @@ init_builtin(char *name) { struct _inittab *p; - if (_PyImport_FindExtension(name, name) != NULL) + if (_PyImport_FindBuiltin(name) != NULL) return 1; for (p = PyImport_Inittab; p->name != NULL; p++) { @@ -2138,7 +2162,7 @@ init_builtin(char *name) mod = (*p->initfunc)(); if (mod == 0) return -1; - if (_PyImport_FixupExtension(mod, name, name) < 0) + if (_PyImport_FixupBuiltin(mod, name) < 0) return -1; /* FixupExtension has put the module into sys.modules, so we can release our own reference. */ diff --git a/Python/importdl.c b/Python/importdl.c index 507222b0c2..9caed453aa 100644 --- a/Python/importdl.c +++ b/Python/importdl.c @@ -27,10 +27,16 @@ _PyImport_LoadDynamicModule(char *name, char *pathname, FILE *fp) dl_funcptr p0; PyObject* (*p)(void); struct PyModuleDef *def; + PyObject *result; - if ((m = _PyImport_FindExtension(name, pathname)) != NULL) { + path = PyUnicode_DecodeFSDefault(pathname); + if (path == NULL) + return NULL; + + if ((m = _PyImport_FindExtensionUnicode(name, path)) != NULL) { Py_INCREF(m); - return m; + result = m; + goto finally; } lastdot = strrchr(name, '.'); if (lastdot == NULL) { @@ -45,26 +51,26 @@ _PyImport_LoadDynamicModule(char *name, char *pathname, FILE *fp) p0 = _PyImport_GetDynLoadFunc(name, shortname, pathname, fp); p = (PyObject*(*)(void))p0; if (PyErr_Occurred()) - return NULL; + goto error; if (p == NULL) { PyErr_Format(PyExc_ImportError, "dynamic module does not define init function (PyInit_%.200s)", shortname); - return NULL; + goto error; } oldcontext = _Py_PackageContext; _Py_PackageContext = packagecontext; m = (*p)(); _Py_PackageContext = oldcontext; if (m == NULL) - return NULL; + goto error; if (PyErr_Occurred()) { Py_DECREF(m); PyErr_Format(PyExc_SystemError, "initialization of %s raised unreported exception", shortname); - return NULL; + goto error; } /* Remember pointer to module init function. */ @@ -72,17 +78,25 @@ _PyImport_LoadDynamicModule(char *name, char *pathname, FILE *fp) def->m_base.m_init = p; /* Remember the filename as the __file__ attribute */ - path = PyUnicode_DecodeFSDefault(pathname); if (PyModule_AddObject(m, "__file__", path) < 0) PyErr_Clear(); /* Not important enough to report */ + else + Py_INCREF(path); - if (_PyImport_FixupExtension(m, name, pathname) < 0) - return NULL; + if (_PyImport_FixupExtensionUnicode(m, name, path) < 0) + goto error; if (Py_VerboseFlag) PySys_WriteStderr( "import %s # dynamically loaded from %s\n", name, pathname); - return m; + result = m; + goto finally; + +error: + result = NULL; +finally: + Py_DECREF(path); + return result; } #endif /* HAVE_DYNAMIC_LOADING */ diff --git a/Python/pythonrun.c b/Python/pythonrun.c index f72c9d705a..fe99fd23f4 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -255,7 +255,7 @@ Py_InitializeEx(int install_sigs) bimod = _PyBuiltin_Init(); if (bimod == NULL) Py_FatalError("Py_Initialize: can't initialize builtins modules"); - _PyImport_FixupExtension(bimod, "builtins", "builtins"); + _PyImport_FixupBuiltin(bimod, "builtins"); interp->builtins = PyModule_GetDict(bimod); if (interp->builtins == NULL) Py_FatalError("Py_Initialize: can't initialize builtins dict"); @@ -271,7 +271,7 @@ Py_InitializeEx(int install_sigs) if (interp->sysdict == NULL) Py_FatalError("Py_Initialize: can't initialize sys dict"); Py_INCREF(interp->sysdict); - _PyImport_FixupExtension(sysmod, "sys", "sys"); + _PyImport_FixupBuiltin(sysmod, "sys"); PySys_SetPath(Py_GetPath()); PyDict_SetItemString(interp->sysdict, "modules", interp->modules); @@ -577,7 +577,7 @@ Py_NewInterpreter(void) interp->modules = PyDict_New(); interp->modules_reloading = PyDict_New(); - bimod = _PyImport_FindExtension("builtins", "builtins"); + bimod = _PyImport_FindBuiltin("builtins"); if (bimod != NULL) { interp->builtins = PyModule_GetDict(bimod); if (interp->builtins == NULL) @@ -588,7 +588,7 @@ Py_NewInterpreter(void) /* initialize builtin exceptions */ _PyExc_Init(); - sysmod = _PyImport_FindExtension("sys", "sys"); + sysmod = _PyImport_FindBuiltin("sys"); if (bimod != NULL && sysmod != NULL) { PyObject *pstderr; interp->sysdict = PyModule_GetDict(sysmod); -- cgit v1.2.1 From cb1017f34c8add0e112192e0518797277e218413 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 17 Oct 2010 02:07:09 +0000 Subject: find_module(): use FS encoding to display the missing __init__ warning --- Python/import.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 6715dc929d..523a1c04db 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1736,14 +1736,16 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, return &fd_package; } else { - char warnstr[MAXPATHLEN+80]; - sprintf(warnstr, "Not importing directory " - "'%.*s': missing __init__.py", - MAXPATHLEN, buf); - if (PyErr_WarnEx(PyExc_ImportWarning, - warnstr, 1)) { + int err; + PyObject *unicode = PyUnicode_DecodeFSDefault(buf); + if (unicode == NULL) + return NULL; + err = PyErr_WarnFormat(PyExc_ImportWarning, 1, + "Not importing directory '%U': missing __init__.py", + unicode); + Py_DECREF(unicode); + if (err) return NULL; - } } } #endif -- cgit v1.2.1 From aa76b5753570a74943a52cb4d01153319a4967be Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 17 Oct 2010 19:03:16 +0000 Subject: PyErr_SyntaxLocationEx() uses PyUnicode_DecodeFSDefault(), instead of PyUnicode_FromString(), to decode the filename. --- Python/errors.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/errors.c b/Python/errors.c index a24095dff9..e3486b95c5 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -819,7 +819,7 @@ PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset) } } if (filename != NULL) { - tmp = PyUnicode_FromString(filename); + tmp = PyUnicode_DecodeFSDefault(filename); if (tmp == NULL) PyErr_Clear(); else { -- cgit v1.2.1 From f6b0658c48183a6162922a03e4b843a5d2af1bb7 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 17 Oct 2010 19:16:33 +0000 Subject: compiler_error(): use PyUnicode_DecodeFSDefault() to decode the filename, instead of utf-8 in strict mode. --- Python/compile.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/compile.c b/Python/compile.c index 1ff085909c..fb2759650b 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3361,7 +3361,7 @@ compiler_in_loop(struct compiler *c) { static int compiler_error(struct compiler *c, const char *errstr) { - PyObject *loc; + PyObject *loc, *filename; PyObject *u = NULL, *v = NULL; loc = PyErr_ProgramText(c->c_filename, c->u->u_lineno); @@ -3369,7 +3369,16 @@ compiler_error(struct compiler *c, const char *errstr) Py_INCREF(Py_None); loc = Py_None; } - u = Py_BuildValue("(ziiO)", c->c_filename, c->u->u_lineno, + if (c->c_filename != NULL) { + filename = PyUnicode_DecodeFSDefault(c->c_filename); + if (!filename) + goto exit; + } + else { + Py_INCREF(Py_None); + filename = Py_None; + } + u = Py_BuildValue("(NiiO)", filename, c->u->u_lineno, c->u->u_col_offset, loc); if (!u) goto exit; -- cgit v1.2.1 From 8c3324e313c1adb92a1e38bbcbaa494bf97b754d Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 17 Oct 2010 20:54:53 +0000 Subject: make hashes always the size of pointers; introduce Py_hash_t #9778 --- Python/bltinmodule.c | 4 ++-- Python/ceval.c | 2 +- Python/sysmodule.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index ece2a3728e..46045192cf 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1148,12 +1148,12 @@ Delete a named attribute on an object; delattr(x, 'y') is equivalent to\n\ static PyObject * builtin_hash(PyObject *self, PyObject *v) { - long x; + Py_hash_t x; x = PyObject_Hash(v); if (x == -1) return NULL; - return PyLong_FromLong(x); + return PyLong_FromSsize_t(x); } PyDoc_STRVAR(hash_doc, diff --git a/Python/ceval.c b/Python/ceval.c index f85f33ad02..1eb5f6204b 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2102,7 +2102,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) /* Inline the PyDict_GetItem() calls. WARNING: this is an extreme speed hack. Do not try this at home. */ - long hash = ((PyUnicodeObject *)w)->hash; + Py_hash_t hash = ((PyUnicodeObject *)w)->hash; if (hash != -1) { PyDictObject *d; PyDictEntry *e; diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 6c563f0d37..033c9d5e56 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -567,7 +567,7 @@ get_hash_info(void) if (hash_info == NULL) return NULL; PyStructSequence_SET_ITEM(hash_info, field++, - PyLong_FromLong(8*sizeof(long))); + PyLong_FromLong(8*sizeof(Py_hash_t))); PyStructSequence_SET_ITEM(hash_info, field++, PyLong_FromLong(_PyHASH_MODULUS)); PyStructSequence_SET_ITEM(hash_info, field++, -- cgit v1.2.1 From 69ad491c3243b85456e2b60a4b47fd7a8a15a55c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 19 Oct 2010 00:05:51 +0000 Subject: initfsencoding(): get_codeset() failure is now a fatal error Don't fallback to utf-8 anymore to avoid mojibake. I never got any error from his function. --- Python/pythonrun.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index fe99fd23f4..f755d117ff 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -730,21 +730,14 @@ initfsencoding(void) /* 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. */ + initialized by other means. */ codeset = get_codeset(); - if (codeset != NULL) { - Py_FileSystemDefaultEncoding = codeset; - Py_HasFileSystemDefaultEncoding = 0; - return; - } else { - fprintf(stderr, "Unable to get the locale encoding:\n"); - PyErr_Print(); - } + if (codeset == NULL) + Py_FatalError("Py_Initialize: Unable to get the locale encoding"); - fprintf(stderr, "Unable to get the filesystem encoding: fallback to utf-8\n"); - Py_FileSystemDefaultEncoding = "utf-8"; - Py_HasFileSystemDefaultEncoding = 1; + Py_FileSystemDefaultEncoding = codeset; + Py_HasFileSystemDefaultEncoding = 0; + return; } #endif -- cgit v1.2.1 From 646694798bfdfa78750ed19d124c6e45711dc880 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 20 Oct 2010 21:25:23 +0000 Subject: fix uninitialized struct member #10152 --- Python/symtable.c | 1 + 1 file changed, 1 insertion(+) (limited to 'Python') diff --git a/Python/symtable.c b/Python/symtable.c index 4a6c52335b..15ba6b5e2f 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -66,6 +66,7 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block, ste->ste_varkeywords = 0; ste->ste_opt_lineno = 0; ste->ste_opt_col_offset = 0; + ste->ste_tmpname = 0; ste->ste_lineno = lineno; ste->ste_col_offset = col_offset; -- cgit v1.2.1 From 657e9caeeac2b54250d697b83f10c2f106353538 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Thu, 21 Oct 2010 13:42:28 +0000 Subject: Issue #10089: Add support for arbitrary -X options on the command-line. They can be retrieved through a new attribute `sys._xoptions`. --- Python/getopt.c | 6 ------ Python/sysmodule.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 6 deletions(-) (limited to 'Python') diff --git a/Python/getopt.c b/Python/getopt.c index 5147320af2..064a1874ea 100644 --- a/Python/getopt.c +++ b/Python/getopt.c @@ -89,12 +89,6 @@ int _PyOS_GetOpt(int argc, wchar_t **argv, wchar_t *optstring) return '_'; } - if (option == 'X') { - fprintf(stderr, - "-X is reserved for implementation-specific arguments\n"); - return '_'; - } - if ((ptr = wcschr(optstring, option)) == NULL) { if (_PyOS_opterr) fprintf(stderr, "Unknown option: -%c\n", (char)option); diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 033c9d5e56..2530cc07aa 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1086,6 +1086,61 @@ PySys_HasWarnOptions(void) return (warnoptions != NULL && (PyList_Size(warnoptions) > 0)) ? 1 : 0; } +static PyObject *xoptions = NULL; + +static PyObject * +get_xoptions(void) +{ + if (xoptions == NULL || !PyDict_Check(xoptions)) { + Py_XDECREF(xoptions); + xoptions = PyDict_New(); + } + return xoptions; +} + +void +PySys_AddXOption(const wchar_t *s) +{ + PyObject *opts; + PyObject *name = NULL, *value = NULL; + const wchar_t *name_end; + int r; + + opts = get_xoptions(); + if (opts == NULL) + goto error; + + name_end = wcschr(s, L'='); + if (!name_end) { + name = PyUnicode_FromWideChar(s, -1); + value = Py_True; + Py_INCREF(value); + } + else { + name = PyUnicode_FromWideChar(s, name_end - s); + value = PyUnicode_FromWideChar(name_end + 1, -1); + } + if (name == NULL || value == NULL) + goto error; + r = PyDict_SetItem(opts, name, value); + Py_DECREF(name); + Py_DECREF(value); + return; + +error: + Py_XDECREF(name); + Py_XDECREF(value); + /* No return value, therefore clear error state if possible */ + if (_Py_atomic_load_relaxed(&_PyThreadState_Current)) + PyErr_Clear(); +} + +PyObject * +PySys_GetXOptions(void) +{ + return get_xoptions(); +} + /* 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, @@ -1535,6 +1590,11 @@ _PySys_Init(void) PyDict_SetItemString(sysdict, "warnoptions", warnoptions); } + v = get_xoptions(); + if (v != NULL) { + PyDict_SetItemString(sysdict, "_xoptions", v); + } + /* version_info */ if (VersionInfoType.tp_name == 0) PyStructSequence_InitType(&VersionInfoType, &version_info_desc); -- cgit v1.2.1 From a7dce1241ca5e5f8a6bcca41a1c2bc01314c16c2 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 23 Oct 2010 16:20:50 +0000 Subject: follow up to #9778: define and use an unsigned hash type --- Python/sysmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 2530cc07aa..6be2262c7b 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -569,7 +569,7 @@ get_hash_info(void) PyStructSequence_SET_ITEM(hash_info, field++, PyLong_FromLong(8*sizeof(Py_hash_t))); PyStructSequence_SET_ITEM(hash_info, field++, - PyLong_FromLong(_PyHASH_MODULUS)); + PyLong_FromSsize_t(_PyHASH_MODULUS)); PyStructSequence_SET_ITEM(hash_info, field++, PyLong_FromLong(_PyHASH_INF)); PyStructSequence_SET_ITEM(hash_info, field++, -- cgit v1.2.1 From f26d99263a6433201f1f5b751a3f113f67359961 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 24 Oct 2010 02:52:05 +0000 Subject: remove broken code accounting an offset the size of the line #10186 --- Python/pythonrun.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index f755d117ff..cf8f7bf2a7 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1344,8 +1344,6 @@ 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) -- cgit v1.2.1 From 09e4cb55cdc2cc460b0c3cac7620bdf3bb3d103b Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 24 Oct 2010 03:41:46 +0000 Subject: tighten loop --- Python/pythonrun.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index cf8f7bf2a7..1b0a84bd65 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1363,11 +1363,8 @@ print_error_text(PyObject *f, int offset, const char *text) if (offset == -1) return; PyFile_WriteString(" ", f); - offset--; - while (offset > 0) { + while (--offset) PyFile_WriteString(" ", f); - offset--; - } PyFile_WriteString("^\n", f); } -- cgit v1.2.1 From a799acdd559c24056cc846fa65af9b1a250e2f36 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sun, 24 Oct 2010 15:11:22 +0000 Subject: Add a new warning gategory, ResourceWarning, as discussed on python-dev. It is silent by default, except when configured --with-pydebug. Emit this warning from the GC shutdown procedure, rather than just printing to stderr. --- Python/_warnings.c | 22 +++++++++++++++++++--- Python/errors.c | 6 ++++-- 2 files changed, 23 insertions(+), 5 deletions(-) (limited to 'Python') diff --git a/Python/_warnings.c b/Python/_warnings.c index a4e9d48e8e..87755e1edb 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -835,6 +835,7 @@ create_filter(PyObject *category, const char *action) static PyObject *ignore_str = NULL; static PyObject *error_str = NULL; static PyObject *default_str = NULL; + static PyObject *always_str = NULL; PyObject *action_obj = NULL; PyObject *lineno, *result; @@ -862,6 +863,14 @@ create_filter(PyObject *category, const char *action) } action_obj = default_str; } + else if (!strcmp(action, "always")) { + if (always_str == NULL) { + always_str = PyUnicode_InternFromString("always"); + if (always_str == NULL) + return NULL; + } + action_obj = always_str; + } else { Py_FatalError("unknown action"); } @@ -879,10 +888,10 @@ static PyObject * init_filters(void) { /* Don't silence DeprecationWarning if -3 was used. */ - PyObject *filters = PyList_New(4); + PyObject *filters = PyList_New(5); unsigned int pos = 0; /* Post-incremented in each use. */ unsigned int x; - const char *bytes_action; + const char *bytes_action, *resource_action; if (filters == NULL) return NULL; @@ -901,7 +910,14 @@ init_filters(void) bytes_action = "ignore"; PyList_SET_ITEM(filters, pos++, create_filter(PyExc_BytesWarning, bytes_action)); - + /* resource usage warnings are enabled by default in pydebug mode */ +#ifdef Py_DEBUG + resource_action = "always"; +#else + resource_action = "ignore"; +#endif + PyList_SET_ITEM(filters, pos++, create_filter(PyExc_ResourceWarning, + resource_action)); for (x = 0; x < pos; x += 1) { if (PyList_GET_ITEM(filters, x) == NULL) { Py_DECREF(filters); diff --git a/Python/errors.c b/Python/errors.c index e3486b95c5..04906141d5 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -767,8 +767,10 @@ PyErr_WriteUnraisable(PyObject *obj) } Py_XDECREF(moduleName); } - PyFile_WriteString(" in ", f); - PyFile_WriteObject(obj, f, 0); + if (obj) { + PyFile_WriteString(" in ", f); + PyFile_WriteObject(obj, f, 0); + } PyFile_WriteString(" ignored\n", f); PyErr_Clear(); /* Just in case */ } -- cgit v1.2.1 From e5e2e0ac0400a76572f7f0cb6e14055767006828 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 25 Oct 2010 17:37:23 +0000 Subject: sys_update_path(): update sys.path even if argc==0 --- Python/sysmodule.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 6be2262c7b..876e31e830 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1748,8 +1748,6 @@ sys_update_path(int argc, wchar_t **argv) if (path == NULL) return; - if (argc == 0) - return; argv0 = argv[0]; #ifdef HAVE_READLINK -- cgit v1.2.1 From a0b3b96364f8ee0e88add47f1497bb2111878039 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Thu, 28 Oct 2010 22:56:58 +0000 Subject: Issue #5437: A preallocated MemoryError instance should not hold traceback data (including local variables caught in the stack trace) alive infinitely. --- Python/errors.c | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) (limited to 'Python') diff --git a/Python/errors.c b/Python/errors.c index 04906141d5..d5a6fae0b4 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -333,29 +333,7 @@ PyErr_BadArgument(void) 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) - { - /* Clear the previous traceback, otherwise it will be appended - * to the current one. - * - * The following statement is not likely to raise any error; - * if it does, we simply discard it. - */ - PyException_SetTraceback(PyExc_MemoryErrorInst, Py_None); - - 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); - + PyErr_SetNone(PyExc_MemoryError); return NULL; } -- cgit v1.2.1 From d83461f3fbb6225b8b24dfcbd4c8cba26de8f263 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 29 Oct 2010 03:28:14 +0000 Subject: decrement offset when it points to a newline (#10186 followup) --- Python/pythonrun.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 1b0a84bd65..33dd11bc88 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1344,6 +1344,8 @@ print_error_text(PyObject *f, int offset, const char *text) { char *nl; if (offset >= 0) { + if (offset > 0 && offset == strlen(text) && text[offset - 1] == '\n') + offset--; for (;;) { nl = strchr(text, '\n'); if (nl == NULL || nl-text >= offset) @@ -1363,7 +1365,7 @@ print_error_text(PyObject *f, int offset, const char *text) if (offset == -1) return; PyFile_WriteString(" ", f); - while (--offset) + while (--offset > 0) PyFile_WriteString(" ", f); PyFile_WriteString("^\n", f); } -- cgit v1.2.1 From e0040b2197ac9d233f6c2a359c5968711bec7555 Mon Sep 17 00:00:00 2001 From: Hirokazu Yamamoto Date: Sat, 30 Oct 2010 15:08:15 +0000 Subject: Issue #10157: Fixed refleaks in pythonrun.c. Patch by Stefan Krah. --- Python/pythonrun.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 33dd11bc88..8b1e61a1c9 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -283,6 +283,7 @@ Py_InitializeEx(int install_sigs) Py_FatalError("Py_Initialize: can't set preliminary stderr"); PySys_SetObject("stderr", pstderr); PySys_SetObject("__stderr__", pstderr); + Py_DECREF(pstderr); _PyImport_Init(); @@ -605,6 +606,7 @@ Py_NewInterpreter(void) Py_FatalError("Py_Initialize: can't set preliminary stderr"); PySys_SetObject("stderr", pstderr); PySys_SetObject("__stderr__", pstderr); + Py_DECREF(pstderr); _PyImportHooks_Init(); if (initstdio() < 0) @@ -971,6 +973,7 @@ initstdio(void) if (encoding != NULL) { _PyCodec_Lookup(encoding); } + Py_DECREF(encoding_attr); } PyErr_Clear(); /* Not a fatal error if codec isn't available */ -- cgit v1.2.1 From 004b7b95f3ffafabb761f4d3d6d17b67d11e3119 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 8 Nov 2010 22:43:46 +0000 Subject: PyUnicode_EncodeFS() raises an exception if _Py_wchar2char() fails * Add error_pos optional argument to _Py_wchar2char() * PyUnicode_EncodeFS() raises a UnicodeEncodeError or MemoryError if _Py_wchar2char() fails --- Python/fileutils.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'Python') diff --git a/Python/fileutils.c b/Python/fileutils.c index 03fc0cb79d..18e98e513c 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -132,15 +132,21 @@ oom: This function is the reverse of _Py_char2wchar(). Return a pointer to a newly allocated byte string (use PyMem_Free() to free - the memory), or NULL on error (conversion error or memory error). */ + the memory), or NULL on conversion or memory allocation error. + + If error_pos is not NULL: *error_pos is the index of the invalid character + on conversion error, or (size_t)-1 otherwise. */ char* -_Py_wchar2char(const wchar_t *text) +_Py_wchar2char(const wchar_t *text, size_t *error_pos) { const size_t len = wcslen(text); char *result = NULL, *bytes = NULL; size_t i, size, converted; wchar_t c, buf[2]; + if (error_pos != NULL) + *error_pos = (size_t)-1; + /* The function works in two steps: 1. compute the length of the output buffer in bytes (size) 2. outputs the bytes */ @@ -168,6 +174,8 @@ _Py_wchar2char(const wchar_t *text) if (converted == (size_t)-1) { if (result != NULL) PyMem_Free(result); + if (error_pos != NULL) + *error_pos = i; return NULL; } if (bytes != NULL) { @@ -208,7 +216,7 @@ _Py_wstat(const wchar_t* path, struct stat *buf) { int err; char *fname; - fname = _Py_wchar2char(path); + fname = _Py_wchar2char(path, NULL); if (fname == NULL) { errno = EINVAL; return -1; @@ -263,7 +271,7 @@ _Py_wfopen(const wchar_t *path, const wchar_t *mode) errno = EINVAL; return NULL; } - cpath = _Py_wchar2char(path); + cpath = _Py_wchar2char(path, NULL); if (cpath == NULL) return NULL; f = fopen(cpath, cmode); @@ -317,7 +325,7 @@ _Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz) int res; size_t r1; - cpath = _Py_wchar2char(path); + cpath = _Py_wchar2char(path, NULL); if (cpath == NULL) { errno = EINVAL; return -1; @@ -361,7 +369,7 @@ _Py_wrealpath(const wchar_t *path, wchar_t *wresolved_path; char *res; size_t r; - cpath = _Py_wchar2char(path); + cpath = _Py_wchar2char(path, NULL); if (cpath == NULL) { errno = EINVAL; return NULL; -- cgit v1.2.1 From c1045d4f1ecd8cf5dc79d227214e371f3d6f7903 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 8 Nov 2010 23:30:46 +0000 Subject: _Py_char2wchar() frees the memory on conversion error Explain in the documentation that conversion errors should never happen. --- Python/fileutils.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/fileutils.c b/Python/fileutils.c index 18e98e513c..c563eaa5fb 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -16,7 +16,10 @@ Return a pointer to a newly allocated wide character string (use PyMem_Free() to free the memory) and write the number of written wide characters excluding the null character into *size if size is not NULL, or - NULL on error (conversion error or memory error). */ + NULL on error (conversion or memory allocation error). + + Conversion errors should never happen, unless there is a bug in the C + library. */ wchar_t* _Py_char2wchar(const char* arg, size_t *size) { @@ -64,7 +67,8 @@ _Py_char2wchar(const char* arg, size_t *size) actual output could use less memory. */ argsize = strlen(arg) + 1; res = (wchar_t*)PyMem_Malloc(argsize*sizeof(wchar_t)); - if (!res) goto oom; + if (!res) + goto oom; in = (unsigned char*)arg; out = res; memset(&mbs, 0, sizeof mbs); @@ -79,6 +83,7 @@ _Py_char2wchar(const char* arg, size_t *size) unless there is a bug in the C library, or I misunderstood how mbrtowc works. */ fprintf(stderr, "unexpected mbrtowc result -2\n"); + PyMem_Free(res); return NULL; } if (converted == (size_t)-1) { -- cgit v1.2.1 From f51cc3fcfc4352e6cc8f0e7292594aa5a462c45d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 9 Nov 2010 09:32:19 +0000 Subject: Issue #10359: Remove ";" after function definition, invalid in ISO C --- Python/import.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 523a1c04db..85ead86d1a 100644 --- a/Python/import.c +++ b/Python/import.c @@ -3101,7 +3101,7 @@ imp_make_magic(long magic) buf[3] = (char) ((magic >> 24) & 0xff); return PyBytes_FromStringAndSize(buf, 4); -}; +} static PyObject * imp_get_magic(PyObject *self, PyObject *noargs) -- cgit v1.2.1 From 4461ae12ac9eb6467106e6a9184180066599b8c4 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Wed, 10 Nov 2010 13:55:25 +0000 Subject: Issue #10372: Import the warnings module only after the IO library is initialized, so as to avoid bootstrap issues with the '-W' option. --- Python/pythonrun.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 8b1e61a1c9..784558c119 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -299,19 +299,21 @@ Py_InitializeEx(int install_sigs) if (install_sigs) initsigs(); /* Signal handling stuff, including initintr() */ + initmain(); /* Module __main__ */ + if (initstdio() < 0) + Py_FatalError( + "Py_Initialize: can't initialize sys standard streams"); + /* Initialize warnings. */ if (PySys_HasWarnOptions()) { PyObject *warnings_module = PyImport_ImportModule("warnings"); - if (!warnings_module) - PyErr_Clear(); + if (warnings_module == NULL) { + fprintf(stderr, "'import warnings' failed; traceback:\n"); + PyErr_Print(); + } Py_XDECREF(warnings_module); } - initmain(); /* Module __main__ */ - if (initstdio() < 0) - Py_FatalError( - "Py_Initialize: can't initialize sys standard streams"); - if (!Py_NoSiteFlag) initsite(); /* Module site */ } -- cgit v1.2.1 From c6988922ca2c06a951ebe4ea907421105ee96806 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 17 Nov 2010 22:33:12 +0000 Subject: handle dict subclasses gracefully in PyArg_ValidateKeywordArguments --- Python/getargs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index abf55ce041..cf9869965c 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1394,7 +1394,7 @@ _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *args, int PyArg_ValidateKeywordArguments(PyObject *kwargs) { - if (!PyDict_CheckExact(kwargs)) { + if (!PyDict_Check(kwargs)) { PyErr_BadInternalCall(); return 0; } -- cgit v1.2.1 From 0cfbd11a323bad965dd270499e13b7fa63178a64 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 20 Nov 2010 01:38:49 +0000 Subject: use %R format code; fixes invalid dereferencing #10391 --- Python/Python-ast.c | 75 ++++++++++++++++++----------------------------------- 1 file changed, 25 insertions(+), 50 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index c37dda7f00..7f22f7f5c3 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -3375,6 +3375,7 @@ int obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena) { PyObject* tmp = NULL; + tmp = tmp; int isinstance; @@ -3514,11 +3515,8 @@ obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena) return 0; } - tmp = PyObject_Repr(obj); - if (tmp == NULL) goto failed; - PyErr_Format(PyExc_TypeError, "expected some sort of mod, but got %.400s", PyBytes_AS_STRING(tmp)); -failed: - Py_XDECREF(tmp); + PyErr_Format(PyExc_TypeError, "expected some sort of mod, but got %R", obj); + failed: return 1; } @@ -3526,6 +3524,7 @@ int obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) { PyObject* tmp = NULL; + tmp = tmp; int isinstance; int lineno; @@ -4712,11 +4711,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) return 0; } - tmp = PyObject_Repr(obj); - if (tmp == NULL) goto failed; - PyErr_Format(PyExc_TypeError, "expected some sort of stmt, but got %.400s", PyBytes_AS_STRING(tmp)); -failed: - Py_XDECREF(tmp); + PyErr_Format(PyExc_TypeError, "expected some sort of stmt, but got %R", obj); + failed: return 1; } @@ -4724,6 +4720,7 @@ int obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) { PyObject* tmp = NULL; + tmp = tmp; int isinstance; int lineno; @@ -5830,11 +5827,8 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) return 0; } - tmp = PyObject_Repr(obj); - if (tmp == NULL) goto failed; - PyErr_Format(PyExc_TypeError, "expected some sort of expr, but got %.400s", PyBytes_AS_STRING(tmp)); -failed: - Py_XDECREF(tmp); + PyErr_Format(PyExc_TypeError, "expected some sort of expr, but got %R", obj); + failed: return 1; } @@ -5842,6 +5836,7 @@ int obj2ast_expr_context(PyObject* obj, expr_context_ty* out, PyArena* arena) { PyObject* tmp = NULL; + tmp = tmp; int isinstance; isinstance = PyObject_IsInstance(obj, (PyObject *)Load_type); @@ -5893,11 +5888,7 @@ obj2ast_expr_context(PyObject* obj, expr_context_ty* out, PyArena* arena) return 0; } - tmp = PyObject_Repr(obj); - if (tmp == NULL) goto failed; - PyErr_Format(PyExc_TypeError, "expected some sort of expr_context, but got %.400s", PyBytes_AS_STRING(tmp)); -failed: - Py_XDECREF(tmp); + PyErr_Format(PyExc_TypeError, "expected some sort of expr_context, but got %R", obj); return 1; } @@ -5905,6 +5896,7 @@ int obj2ast_slice(PyObject* obj, slice_ty* out, PyArena* arena) { PyObject* tmp = NULL; + tmp = tmp; int isinstance; @@ -6018,11 +6010,8 @@ obj2ast_slice(PyObject* obj, slice_ty* out, PyArena* arena) return 0; } - tmp = PyObject_Repr(obj); - if (tmp == NULL) goto failed; - PyErr_Format(PyExc_TypeError, "expected some sort of slice, but got %.400s", PyBytes_AS_STRING(tmp)); -failed: - Py_XDECREF(tmp); + PyErr_Format(PyExc_TypeError, "expected some sort of slice, but got %R", obj); + failed: return 1; } @@ -6030,6 +6019,7 @@ int obj2ast_boolop(PyObject* obj, boolop_ty* out, PyArena* arena) { PyObject* tmp = NULL; + tmp = tmp; int isinstance; isinstance = PyObject_IsInstance(obj, (PyObject *)And_type); @@ -6049,11 +6039,7 @@ obj2ast_boolop(PyObject* obj, boolop_ty* out, PyArena* arena) return 0; } - tmp = PyObject_Repr(obj); - if (tmp == NULL) goto failed; - PyErr_Format(PyExc_TypeError, "expected some sort of boolop, but got %.400s", PyBytes_AS_STRING(tmp)); -failed: - Py_XDECREF(tmp); + PyErr_Format(PyExc_TypeError, "expected some sort of boolop, but got %R", obj); return 1; } @@ -6061,6 +6047,7 @@ int obj2ast_operator(PyObject* obj, operator_ty* out, PyArena* arena) { PyObject* tmp = NULL; + tmp = tmp; int isinstance; isinstance = PyObject_IsInstance(obj, (PyObject *)Add_type); @@ -6160,11 +6147,7 @@ obj2ast_operator(PyObject* obj, operator_ty* out, PyArena* arena) return 0; } - tmp = PyObject_Repr(obj); - if (tmp == NULL) goto failed; - PyErr_Format(PyExc_TypeError, "expected some sort of operator, but got %.400s", PyBytes_AS_STRING(tmp)); -failed: - Py_XDECREF(tmp); + PyErr_Format(PyExc_TypeError, "expected some sort of operator, but got %R", obj); return 1; } @@ -6172,6 +6155,7 @@ int obj2ast_unaryop(PyObject* obj, unaryop_ty* out, PyArena* arena) { PyObject* tmp = NULL; + tmp = tmp; int isinstance; isinstance = PyObject_IsInstance(obj, (PyObject *)Invert_type); @@ -6207,11 +6191,7 @@ obj2ast_unaryop(PyObject* obj, unaryop_ty* out, PyArena* arena) return 0; } - tmp = PyObject_Repr(obj); - if (tmp == NULL) goto failed; - PyErr_Format(PyExc_TypeError, "expected some sort of unaryop, but got %.400s", PyBytes_AS_STRING(tmp)); -failed: - Py_XDECREF(tmp); + PyErr_Format(PyExc_TypeError, "expected some sort of unaryop, but got %R", obj); return 1; } @@ -6219,6 +6199,7 @@ int obj2ast_cmpop(PyObject* obj, cmpop_ty* out, PyArena* arena) { PyObject* tmp = NULL; + tmp = tmp; int isinstance; isinstance = PyObject_IsInstance(obj, (PyObject *)Eq_type); @@ -6302,11 +6283,7 @@ obj2ast_cmpop(PyObject* obj, cmpop_ty* out, PyArena* arena) return 0; } - tmp = PyObject_Repr(obj); - if (tmp == NULL) goto failed; - PyErr_Format(PyExc_TypeError, "expected some sort of cmpop, but got %.400s", PyBytes_AS_STRING(tmp)); -failed: - Py_XDECREF(tmp); + PyErr_Format(PyExc_TypeError, "expected some sort of cmpop, but got %R", obj); return 1; } @@ -6378,6 +6355,7 @@ int obj2ast_excepthandler(PyObject* obj, excepthandler_ty* out, PyArena* arena) { PyObject* tmp = NULL; + tmp = tmp; int isinstance; int lineno; @@ -6473,11 +6451,8 @@ obj2ast_excepthandler(PyObject* obj, excepthandler_ty* out, PyArena* arena) return 0; } - tmp = PyObject_Repr(obj); - if (tmp == NULL) goto failed; - PyErr_Format(PyExc_TypeError, "expected some sort of excepthandler, but got %.400s", PyBytes_AS_STRING(tmp)); -failed: - Py_XDECREF(tmp); + PyErr_Format(PyExc_TypeError, "expected some sort of excepthandler, but got %R", obj); + failed: return 1; } -- cgit v1.2.1 From f8f95ac0048b606c4e81d9b1f113dcde62e09d8c Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 20 Nov 2010 02:01:45 +0000 Subject: c89 declarations --- Python/Python-ast.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 7f22f7f5c3..8de5314e2d 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -3375,8 +3375,8 @@ int obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena) { PyObject* tmp = NULL; - tmp = tmp; int isinstance; + tmp = tmp; if (obj == Py_None) { @@ -3524,8 +3524,8 @@ int obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) { PyObject* tmp = NULL; - tmp = tmp; int isinstance; + tmp = tmp; int lineno; int col_offset; @@ -4720,8 +4720,8 @@ int obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) { PyObject* tmp = NULL; - tmp = tmp; int isinstance; + tmp = tmp; int lineno; int col_offset; @@ -5836,8 +5836,8 @@ int obj2ast_expr_context(PyObject* obj, expr_context_ty* out, PyArena* arena) { PyObject* tmp = NULL; - tmp = tmp; int isinstance; + tmp = tmp; isinstance = PyObject_IsInstance(obj, (PyObject *)Load_type); if (isinstance == -1) { @@ -5896,8 +5896,8 @@ int obj2ast_slice(PyObject* obj, slice_ty* out, PyArena* arena) { PyObject* tmp = NULL; - tmp = tmp; int isinstance; + tmp = tmp; if (obj == Py_None) { @@ -6019,8 +6019,8 @@ int obj2ast_boolop(PyObject* obj, boolop_ty* out, PyArena* arena) { PyObject* tmp = NULL; - tmp = tmp; int isinstance; + tmp = tmp; isinstance = PyObject_IsInstance(obj, (PyObject *)And_type); if (isinstance == -1) { @@ -6047,8 +6047,8 @@ int obj2ast_operator(PyObject* obj, operator_ty* out, PyArena* arena) { PyObject* tmp = NULL; - tmp = tmp; int isinstance; + tmp = tmp; isinstance = PyObject_IsInstance(obj, (PyObject *)Add_type); if (isinstance == -1) { @@ -6155,8 +6155,8 @@ int obj2ast_unaryop(PyObject* obj, unaryop_ty* out, PyArena* arena) { PyObject* tmp = NULL; - tmp = tmp; int isinstance; + tmp = tmp; isinstance = PyObject_IsInstance(obj, (PyObject *)Invert_type); if (isinstance == -1) { @@ -6199,8 +6199,8 @@ int obj2ast_cmpop(PyObject* obj, cmpop_ty* out, PyArena* arena) { PyObject* tmp = NULL; - tmp = tmp; int isinstance; + tmp = tmp; isinstance = PyObject_IsInstance(obj, (PyObject *)Eq_type); if (isinstance == -1) { @@ -6355,8 +6355,8 @@ int obj2ast_excepthandler(PyObject* obj, excepthandler_ty* out, PyArena* arena) { PyObject* tmp = NULL; - tmp = tmp; int isinstance; + tmp = tmp; int lineno; int col_offset; -- cgit v1.2.1 From 2a0838ed90391b3fa68188d59dda4bbacbf4c812 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 20 Nov 2010 04:31:07 +0000 Subject: new plan: functions that want 'tmp' can declare it --- Python/Python-ast.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 8de5314e2d..4d26ec8de7 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -3374,10 +3374,9 @@ failed: int obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena) { - PyObject* tmp = NULL; int isinstance; - tmp = tmp; + PyObject *tmp = NULL; if (obj == Py_None) { *out = NULL; @@ -3523,10 +3522,9 @@ obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena) int obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) { - PyObject* tmp = NULL; int isinstance; - tmp = tmp; + PyObject *tmp = NULL; int lineno; int col_offset; @@ -4719,10 +4717,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) int obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) { - PyObject* tmp = NULL; int isinstance; - tmp = tmp; + PyObject *tmp = NULL; int lineno; int col_offset; @@ -5835,9 +5832,7 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) int obj2ast_expr_context(PyObject* obj, expr_context_ty* out, PyArena* arena) { - PyObject* tmp = NULL; int isinstance; - tmp = tmp; isinstance = PyObject_IsInstance(obj, (PyObject *)Load_type); if (isinstance == -1) { @@ -5895,10 +5890,9 @@ obj2ast_expr_context(PyObject* obj, expr_context_ty* out, PyArena* arena) int obj2ast_slice(PyObject* obj, slice_ty* out, PyArena* arena) { - PyObject* tmp = NULL; int isinstance; - tmp = tmp; + PyObject *tmp = NULL; if (obj == Py_None) { *out = NULL; @@ -6018,9 +6012,7 @@ obj2ast_slice(PyObject* obj, slice_ty* out, PyArena* arena) int obj2ast_boolop(PyObject* obj, boolop_ty* out, PyArena* arena) { - PyObject* tmp = NULL; int isinstance; - tmp = tmp; isinstance = PyObject_IsInstance(obj, (PyObject *)And_type); if (isinstance == -1) { @@ -6046,9 +6038,7 @@ obj2ast_boolop(PyObject* obj, boolop_ty* out, PyArena* arena) int obj2ast_operator(PyObject* obj, operator_ty* out, PyArena* arena) { - PyObject* tmp = NULL; int isinstance; - tmp = tmp; isinstance = PyObject_IsInstance(obj, (PyObject *)Add_type); if (isinstance == -1) { @@ -6154,9 +6144,7 @@ obj2ast_operator(PyObject* obj, operator_ty* out, PyArena* arena) int obj2ast_unaryop(PyObject* obj, unaryop_ty* out, PyArena* arena) { - PyObject* tmp = NULL; int isinstance; - tmp = tmp; isinstance = PyObject_IsInstance(obj, (PyObject *)Invert_type); if (isinstance == -1) { @@ -6198,9 +6186,7 @@ obj2ast_unaryop(PyObject* obj, unaryop_ty* out, PyArena* arena) int obj2ast_cmpop(PyObject* obj, cmpop_ty* out, PyArena* arena) { - PyObject* tmp = NULL; int isinstance; - tmp = tmp; isinstance = PyObject_IsInstance(obj, (PyObject *)Eq_type); if (isinstance == -1) { @@ -6354,10 +6340,9 @@ failed: int obj2ast_excepthandler(PyObject* obj, excepthandler_ty* out, PyArena* arena) { - PyObject* tmp = NULL; int isinstance; - tmp = tmp; + PyObject *tmp = NULL; int lineno; int col_offset; -- cgit v1.2.1 From 75596c7d735b7520f34bb96e70effcb6b0d1cb24 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sat, 20 Nov 2010 19:50:57 +0000 Subject: Issue #10255: Fix reference leak in Py_InitializeEx(). Patch by Neil Schemenauer. --- Python/pythonrun.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 784558c119..37c1f1197a 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -893,8 +893,10 @@ initstdio(void) /* Set builtins.open */ if (PyObject_SetAttrString(bimod, "open", wrapper) == -1) { + Py_DECREF(wrapper); goto error; } + Py_DECREF(wrapper); encoding = Py_GETENV("PYTHONIOENCODING"); errors = NULL; -- cgit v1.2.1 From f93d2d0b52f1b7772092895e8a916bac0da07c6c Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 21 Nov 2010 15:12:34 +0000 Subject: fix refleak --- Python/Python-ast.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 4d26ec8de7..2c09f96f0e 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -3516,6 +3516,7 @@ obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena) PyErr_Format(PyExc_TypeError, "expected some sort of mod, but got %R", obj); failed: + Py_XDECREF(tmp); return 1; } @@ -4711,6 +4712,7 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_Format(PyExc_TypeError, "expected some sort of stmt, but got %R", obj); failed: + Py_XDECREF(tmp); return 1; } @@ -5826,6 +5828,7 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_Format(PyExc_TypeError, "expected some sort of expr, but got %R", obj); failed: + Py_XDECREF(tmp); return 1; } @@ -6006,6 +6009,7 @@ obj2ast_slice(PyObject* obj, slice_ty* out, PyArena* arena) PyErr_Format(PyExc_TypeError, "expected some sort of slice, but got %R", obj); failed: + Py_XDECREF(tmp); return 1; } @@ -6438,6 +6442,7 @@ obj2ast_excepthandler(PyObject* obj, excepthandler_ty* out, PyArena* arena) PyErr_Format(PyExc_TypeError, "expected some sort of excepthandler, but got %R", obj); failed: + Py_XDECREF(tmp); return 1; } -- cgit v1.2.1 From 5034909d0b3fcc584611160fbee87e5942c808d5 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sat, 27 Nov 2010 22:00:11 +0000 Subject: Issue #10518: Bring back the callable() builtin. Approved by Guido (BDFL) and Georg (RM). --- Python/bltinmodule.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 46045192cf..f374277f3d 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -311,6 +311,20 @@ PyDoc_STRVAR(bin_doc, Return the binary representation of an integer or long integer."); +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 of classes with a\n\ +__call__() method."); + + typedef struct { PyObject_HEAD PyObject *func; @@ -2242,6 +2256,7 @@ static PyMethodDef builtin_methods[] = { {"any", builtin_any, METH_O, any_doc}, {"ascii", builtin_ascii, METH_O, ascii_doc}, {"bin", builtin_bin, METH_O, bin_doc}, + {"callable", builtin_callable, METH_O, callable_doc}, {"chr", builtin_chr, METH_VARARGS, chr_doc}, {"compile", (PyCFunction)builtin_compile, METH_VARARGS | METH_KEYWORDS, compile_doc}, {"delattr", builtin_delattr, METH_VARARGS, delattr_doc}, -- cgit v1.2.1 From 6171159a9a7c63538f97307fc00e27618b326a1f Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Tue, 30 Nov 2010 09:30:54 +0000 Subject: Include structseq.h in Python.h, and remove now-redundant includes in individual sources. --- Python/sysmodule.c | 1 - 1 file changed, 1 deletion(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 876e31e830..1aa4271d76 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -15,7 +15,6 @@ Data members: */ #include "Python.h" -#include "structseq.h" #include "code.h" #include "frameobject.h" #include "eval.h" -- cgit v1.2.1 From c16ad2eeb23a20667e832e09ad88e012952d8988 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Tue, 30 Nov 2010 09:41:01 +0000 Subject: Remove redundant includes of headers that are already included by Python.h. --- Python/ast.c | 1 - Python/bltinmodule.c | 1 - Python/ceval.c | 1 - Python/compile.c | 2 -- Python/future.c | 1 - Python/import.c | 4 ---- Python/peephole.c | 2 -- Python/pyarena.c | 1 - Python/pythonrun.c | 4 ---- Python/sysmodule.c | 1 - Python/traceback.c | 1 - 11 files changed, 19 deletions(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index d1aa61640a..4edf335c33 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -7,7 +7,6 @@ #include "Python-ast.h" #include "grammar.h" #include "node.h" -#include "pyarena.h" #include "ast.h" #include "token.h" #include "parsetok.h" diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index f374277f3d..f300ab2a7b 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -5,7 +5,6 @@ #include "node.h" #include "code.h" -#include "eval.h" #include diff --git a/Python/ceval.c b/Python/ceval.c index 1eb5f6204b..140112fc13 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -13,7 +13,6 @@ #include "code.h" #include "frameobject.h" -#include "eval.h" #include "opcode.h" #include "structmember.h" diff --git a/Python/compile.c b/Python/compile.c index fb2759650b..dfb2c9bcf7 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -25,10 +25,8 @@ #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" diff --git a/Python/future.c b/Python/future.c index 551edc6085..d6b653f315 100644 --- a/Python/future.c +++ b/Python/future.c @@ -4,7 +4,6 @@ #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" diff --git a/Python/import.c b/Python/import.c index 85ead86d1a..67c4f70adb 100644 --- a/Python/import.c +++ b/Python/import.c @@ -5,13 +5,9 @@ #include "Python-ast.h" #undef Yield /* undefine macro conflicting with winbase.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" diff --git a/Python/peephole.c b/Python/peephole.c index 9d06963e2c..f972e1611e 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -4,10 +4,8 @@ #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" diff --git a/Python/pyarena.c b/Python/pyarena.c index 2d63638856..5a255ae497 100644 --- a/Python/pyarena.c +++ b/Python/pyarena.c @@ -1,5 +1,4 @@ #include "Python.h" -#include "pyarena.h" /* A simple arena block structure. diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 37c1f1197a..de8e9da4b6 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -11,14 +11,10 @@ #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" #include "osdefs.h" -#include "abstract.h" #ifdef HAVE_SIGNAL_H #include diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 1aa4271d76..204c8c8cc9 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -17,7 +17,6 @@ Data members: #include "Python.h" #include "code.h" #include "frameobject.h" -#include "eval.h" #include "osdefs.h" diff --git a/Python/traceback.c b/Python/traceback.c index ab10cfd161..59bb3f0d15 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -7,7 +7,6 @@ #include "frameobject.h" #include "structmember.h" #include "osdefs.h" -#include "traceback.h" #ifdef HAVE_FCNTL_H #include #endif -- cgit v1.2.1 From 4c1927593fc0ab5e1c59702be4b7faa6331f48ef Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Thu, 2 Dec 2010 04:11:46 +0000 Subject: Issue #9573: os.fork now works when triggered as a side effect of import (the wisdom of actually relying on this remains questionable!) --- Python/import.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 67c4f70adb..e582a277d4 100644 --- a/Python/import.c +++ b/Python/import.c @@ -325,8 +325,17 @@ _PyImport_ReInitLock(void) { if (import_lock != NULL) import_lock = PyThread_allocate_lock(); - import_lock_thread = -1; - import_lock_level = 0; + if (import_lock_level > 1) { + /* Forked as a side effect of import */ + long me = PyThread_get_thread_ident(); + PyThread_acquire_lock(import_lock, 0); + /* XXX: can the previous line fail? */ + import_lock_thread = me; + import_lock_level--; + } else { + import_lock_thread = -1; + import_lock_level = 0; + } } #endif -- cgit v1.2.1 From cb6fcb819798876be944e636c7237c1b176e2cc5 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 3 Dec 2010 17:06:43 +0000 Subject: import: use PyUnicode_FSConverter to support bytes path and PEP 383 (instead of PyArg_Parse*() with "es" format and Py_FileSystemDefaultEncoding) --- Python/import.c | 58 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 28 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index e582a277d4..ce7cbc297e 100644 --- a/Python/import.c +++ b/Python/import.c @@ -3206,14 +3206,14 @@ call_find_module(char *name, PyObject *path) static PyObject * imp_find_module(PyObject *self, PyObject *args) { - char *name; + PyObject *name; PyObject *ret, *path = NULL; - if (!PyArg_ParseTuple(args, "es|O:find_module", - Py_FileSystemDefaultEncoding, &name, + if (!PyArg_ParseTuple(args, "O&|O:find_module", + PyUnicode_FSConverter, &name, &path)) return NULL; - ret = call_find_module(name, path); - PyMem_Free(name); + ret = call_find_module(PyBytes_AS_STRING(name), path); + Py_DECREF(name); return ret; } @@ -3331,23 +3331,23 @@ static PyObject * imp_load_compiled(PyObject *self, PyObject *args) { char *name; - char *pathname; + PyObject *pathname; PyObject *fob = NULL; PyObject *m; FILE *fp; - if (!PyArg_ParseTuple(args, "ses|O:load_compiled", + if (!PyArg_ParseTuple(args, "sO&|O:load_compiled", &name, - Py_FileSystemDefaultEncoding, &pathname, + PyUnicode_FSConverter, &pathname, &fob)) return NULL; - fp = get_file(pathname, fob, "rb"); + fp = get_file(PyBytes_AS_STRING(pathname), fob, "rb"); if (fp == NULL) { - PyMem_Free(pathname); + Py_DECREF(pathname); return NULL; } - m = load_compiled_module(name, pathname, fp); + m = load_compiled_module(name, PyBytes_AS_STRING(pathname), fp); fclose(fp); - PyMem_Free(pathname); + Py_DECREF(pathname); return m; } @@ -3386,22 +3386,22 @@ static PyObject * imp_load_source(PyObject *self, PyObject *args) { char *name; - char *pathname; + PyObject *pathname; PyObject *fob = NULL; PyObject *m; FILE *fp; - if (!PyArg_ParseTuple(args, "ses|O:load_source", + if (!PyArg_ParseTuple(args, "sO&|O:load_source", &name, - Py_FileSystemDefaultEncoding, &pathname, + PyUnicode_FSConverter, &pathname, &fob)) return NULL; - fp = get_file(pathname, fob, "r"); + fp = get_file(PyBytes_AS_STRING(pathname), fob, "r"); if (fp == NULL) { - PyMem_Free(pathname); + Py_DECREF(pathname); return NULL; } - m = load_source_module(name, pathname, fp); - PyMem_Free(pathname); + m = load_source_module(name, PyBytes_AS_STRING(pathname), fp); + Py_DECREF(pathname); fclose(fp); return m; } @@ -3455,13 +3455,13 @@ static PyObject * imp_load_package(PyObject *self, PyObject *args) { char *name; - char *pathname; + PyObject *pathname; PyObject * ret; - if (!PyArg_ParseTuple(args, "ses:load_package", - &name, Py_FileSystemDefaultEncoding, &pathname)) + if (!PyArg_ParseTuple(args, "sO&:load_package", + &name, PyUnicode_FSConverter, &pathname)) return NULL; - ret = load_package(name, pathname); - PyMem_Free(pathname); + ret = load_package(name, PyBytes_AS_STRING(pathname)); + Py_DECREF(pathname); return ret; } @@ -3534,21 +3534,23 @@ imp_source_from_cache(PyObject *self, PyObject *args, PyObject *kws) { static char *kwlist[] = {"path", NULL}; + PyObject *pathname_obj; char *pathname; char buf[MAXPATHLEN+1]; if (!PyArg_ParseTupleAndKeywords( - args, kws, "es", kwlist, - Py_FileSystemDefaultEncoding, &pathname)) + args, kws, "O&", kwlist, + PyUnicode_FSConverter, &pathname_obj)) return NULL; + pathname = PyBytes_AS_STRING(pathname_obj); if (make_source_pathname(pathname, buf) == NULL) { PyErr_Format(PyExc_ValueError, "Not a PEP 3147 pyc path: %s", pathname); - PyMem_Free(pathname); + Py_DECREF(pathname_obj); return NULL; } - PyMem_Free(pathname); + Py_DECREF(pathname_obj); return PyUnicode_FromString(buf); } -- cgit v1.2.1 From bbbb00332d45ae20db0b9032efcb3bf397e2df3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Fri, 3 Dec 2010 20:14:31 +0000 Subject: Merge branches/pep-0384. --- Python/bltinmodule.c | 4 ++-- Python/ceval.c | 7 ++++--- Python/dynload_shlib.c | 2 ++ Python/dynload_win.c | 14 +++++++++++++- Python/import.c | 2 +- Python/pythonrun.c | 12 ++++++++++-- 6 files changed, 32 insertions(+), 9 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index f300ab2a7b..765464a73e 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -727,7 +727,7 @@ builtin_eval(PyObject *self, PyObject *args) "code object passed to eval() may not contain free variables"); return NULL; } - return PyEval_EvalCode((PyCodeObject *) cmd, globals, locals); + return PyEval_EvalCode(cmd, globals, locals); } cf.cf_flags = PyCF_SOURCE_IS_UTF8; @@ -803,7 +803,7 @@ builtin_exec(PyObject *self, PyObject *args) "contain free variables"); return NULL; } - v = PyEval_EvalCode((PyCodeObject *) prog, globals, locals); + v = PyEval_EvalCode(prog, globals, locals); } else { char *str; diff --git a/Python/ceval.c b/Python/ceval.c index 140112fc13..684c6c28f3 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -755,7 +755,7 @@ static int _Py_TracingPossible = 0; PyObject * -PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals) +PyEval_EvalCode(PyObject *co, PyObject *globals, PyObject *locals) { return PyEval_EvalCodeEx(co, globals, locals, @@ -3059,10 +3059,11 @@ exit_eval_frame: the test in the if statements in Misc/gdbinit (pystack and pystackv). */ PyObject * -PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, +PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals, PyObject **args, int argcount, PyObject **kws, int kwcount, PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure) { + PyCodeObject* co = (PyCodeObject*)_co; register PyFrameObject *f; register PyObject *retval = NULL; register PyObject **fastlocals, **freevars; @@ -3968,7 +3969,7 @@ fast_function(PyObject *func, PyObject ***pp_stack, int n, int na, int nk) d = &PyTuple_GET_ITEM(argdefs, 0); nd = Py_SIZE(argdefs); } - return PyEval_EvalCodeEx(co, globals, + return PyEval_EvalCodeEx((PyObject*)co, globals, (PyObject *)NULL, (*pp_stack)-n, na, (*pp_stack)-2*nk, nk, d, nd, kwdefs, PyFunction_GET_CLOSURE(func)); diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c index 3d0fb5eb01..7ea510e862 100644 --- a/Python/dynload_shlib.c +++ b/Python/dynload_shlib.c @@ -53,6 +53,8 @@ const struct filedescr _PyImport_DynLoadFiletab[] = { #else /* !__VMS */ {"." SOABI ".so", "rb", C_EXTENSION}, {"module." SOABI ".so", "rb", C_EXTENSION}, + {".abi" PYTHON_ABI_STRING ".so", "rb", C_EXTENSION}, + {"module.abi" PYTHON_ABI_STRING ".so", "rb", C_EXTENSION}, {".so", "rb", C_EXTENSION}, {"module.so", "rb", C_EXTENSION}, #endif /* __VMS */ diff --git a/Python/dynload_win.c b/Python/dynload_win.c index e7d61ce8e0..73a1dcf897 100644 --- a/Python/dynload_win.c +++ b/Python/dynload_win.c @@ -134,6 +134,15 @@ static char *GetPythonImport (HINSTANCE hModule) !strncmp(import_name,"python",6)) { char *pch; +#ifndef _DEBUG + /* In a release version, don't claim that python3.dll is + a Python DLL. */ + if (strcmp(import_name, "python3.dll") == 0) { + import_data += 20; + continue; + } +#endif + /* Ensure python prefix is followed only by numbers to the end of the basename */ pch = import_name + 6; @@ -162,13 +171,16 @@ static char *GetPythonImport (HINSTANCE hModule) 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; +#ifndef _DEBUG + _Py_CheckPython3(); +#endif + PyOS_snprintf(funcname, sizeof(funcname), "PyInit_%.200s", shortname); { diff --git a/Python/import.c b/Python/import.c index ce7cbc297e..23752eeb72 100644 --- a/Python/import.c +++ b/Python/import.c @@ -806,7 +806,7 @@ PyImport_ExecCodeModuleWithPathnames(char *name, PyObject *co, char *pathname, PyErr_Clear(); /* Not important enough to report */ Py_DECREF(v); - v = PyEval_EvalCode((PyCodeObject *)co, d, d); + v = PyEval_EvalCode(co, d, d); if (v == NULL) goto error; Py_DECREF(v); diff --git a/Python/pythonrun.c b/Python/pythonrun.c index de8e9da4b6..3f6385d455 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1755,7 +1755,7 @@ run_mod(mod_ty mod, const char *filename, PyObject *globals, PyObject *locals, co = PyAST_Compile(mod, filename, flags, arena); if (co == NULL) return NULL; - v = PyEval_EvalCode(co, globals, locals); + v = PyEval_EvalCode((PyObject*)co, globals, locals); Py_DECREF(co); return v; } @@ -1785,7 +1785,7 @@ run_pyc_file(FILE *fp, const char *filename, PyObject *globals, return NULL; } co = (PyCodeObject *)v; - v = PyEval_EvalCode(co, globals, locals); + v = PyEval_EvalCode((PyObject*)co, globals, locals); if (v && flags) flags->cf_flags |= (co->co_flags & PyCF_MASK); Py_DECREF(co); @@ -1817,6 +1817,14 @@ Py_CompileStringFlags(const char *str, const char *filename, int start, return (PyObject *)co; } +/* For use in Py_LIMITED_API */ +#undef Py_CompileString +PyObject * +PyCompileString(const char *str, const char *filename, int start) +{ + return Py_CompileStringFlags(str, filename, start, NULL); +} + struct symtable * Py_SymtableString(const char *str, const char *filename, int start) { -- cgit v1.2.1 From e652f1b1b4166521e134d6312eebe9b761ea78e5 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sat, 4 Dec 2010 10:26:46 +0000 Subject: Add an "optimize" parameter to compile() to control the optimization level, and provide an interface to it in py_compile, compileall and PyZipFile. --- Python/bltinmodule.c | 19 +++++++++++++------ Python/compile.c | 32 ++++++++++++++++++++++---------- Python/pythonrun.c | 16 ++++++++++++---- 3 files changed, 47 insertions(+), 20 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 765464a73e..f9b3202d54 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -543,19 +543,20 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds) int mode = -1; int dont_inherit = 0; int supplied_flags = 0; + int optimize = -1; int is_ast; PyCompilerFlags cf; PyObject *cmd; static char *kwlist[] = {"source", "filename", "mode", "flags", - "dont_inherit", NULL}; + "dont_inherit", "optimize", NULL}; int start[] = {Py_file_input, Py_eval_input, Py_single_input}; PyObject *result; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&s|ii:compile", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&s|iii:compile", kwlist, &cmd, PyUnicode_FSConverter, &filename_obj, &startstr, &supplied_flags, - &dont_inherit)) + &dont_inherit, &optimize)) return NULL; filename = PyBytes_AS_STRING(filename_obj); @@ -570,6 +571,12 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds) } /* XXX Warn if (supplied_flags & PyCF_MASK_OBSOLETE) != 0? */ + if (optimize < -1 || optimize > 2) { + PyErr_SetString(PyExc_ValueError, + "compile(): invalid optimize value"); + goto error; + } + if (!dont_inherit) { PyEval_MergeCompilerFlags(&cf); } @@ -604,8 +611,8 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds) PyArena_Free(arena); goto error; } - result = (PyObject*)PyAST_Compile(mod, filename, - &cf, arena); + result = (PyObject*)PyAST_CompileEx(mod, filename, + &cf, optimize, arena); PyArena_Free(arena); } goto finally; @@ -615,7 +622,7 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds) if (str == NULL) goto error; - result = Py_CompileStringFlags(str, filename, start[mode], &cf); + result = Py_CompileStringExFlags(str, filename, start[mode], &cf, optimize); goto finally; error: diff --git a/Python/compile.c b/Python/compile.c index dfb2c9bcf7..1d6e38c22e 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -139,6 +139,7 @@ struct compiler { PyFutureFeatures *c_future; /* pointer to module's __future__ */ PyCompilerFlags *c_flags; + int c_optimize; /* optimization level */ int c_interactive; /* true if in interactive mode */ int c_nestlevel; @@ -175,7 +176,7 @@ static void compiler_pop_fblock(struct compiler *, enum fblocktype, static int compiler_in_loop(struct compiler *); static int inplace_binop(struct compiler *, operator_ty); -static int expr_constant(expr_ty e); +static int expr_constant(struct compiler *, expr_ty); static int compiler_with(struct compiler *, stmt_ty); static int compiler_call_helper(struct compiler *c, int n, @@ -254,8 +255,8 @@ compiler_init(struct compiler *c) } PyCodeObject * -PyAST_Compile(mod_ty mod, const char *filename, PyCompilerFlags *flags, - PyArena *arena) +PyAST_CompileEx(mod_ty mod, const char *filename, PyCompilerFlags *flags, + int optimize, PyArena *arena) { struct compiler c; PyCodeObject *co = NULL; @@ -283,6 +284,7 @@ PyAST_Compile(mod_ty mod, const char *filename, PyCompilerFlags *flags, c.c_future->ff_features = merged; flags->cf_flags = merged; c.c_flags = flags; + c.c_optimize = (optimize == -1) ? Py_OptimizeFlag : optimize; c.c_nestlevel = 0; c.c_st = PySymtable_Build(mod, filename, c.c_future); @@ -1149,7 +1151,7 @@ compiler_body(struct compiler *c, asdl_seq *stmts) if (!asdl_seq_LEN(stmts)) return 1; st = (stmt_ty)asdl_seq_GET(stmts, 0); - if (compiler_isdocstring(st) && Py_OptimizeFlag < 2) { + if (compiler_isdocstring(st) && c->c_optimize < 2) { /* don't generate docstrings if -OO */ i = 1; VISIT(c, expr, st->v.Expr.value); @@ -1463,7 +1465,7 @@ compiler_function(struct compiler *c, stmt_ty s) st = (stmt_ty)asdl_seq_GET(s->v.FunctionDef.body, 0); docstring = compiler_isdocstring(st); - if (docstring && Py_OptimizeFlag < 2) + if (docstring && c->c_optimize < 2) 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); @@ -1697,7 +1699,7 @@ compiler_if(struct compiler *c, stmt_ty s) if (end == NULL) return 0; - constant = expr_constant(s->v.If.test); + constant = expr_constant(c, s->v.If.test); /* constant = 0: "if 0" * constant = 1: "if 1", "if 2", ... * constant = -1: rest */ @@ -1759,7 +1761,7 @@ static int compiler_while(struct compiler *c, stmt_ty s) { basicblock *loop, *orelse, *end, *anchor = NULL; - int constant = expr_constant(s->v.While.test); + int constant = expr_constant(c, s->v.While.test); if (constant == 0) { if (s->v.While.orelse) @@ -2211,7 +2213,7 @@ compiler_assert(struct compiler *c, stmt_ty s) static PyObject *assertion_error = NULL; basicblock *end; - if (Py_OptimizeFlag) + if (c->c_optimize) return 1; if (assertion_error == NULL) { assertion_error = PyUnicode_InternFromString("AssertionError"); @@ -3011,7 +3013,7 @@ compiler_visit_keyword(struct compiler *c, keyword_ty k) */ static int -expr_constant(expr_ty e) +expr_constant(struct compiler *c, expr_ty e) { char *id; switch (e->kind) { @@ -3029,7 +3031,7 @@ expr_constant(expr_ty e) if (strcmp(id, "False") == 0) return 0; if (strcmp(id, "None") == 0) return 0; if (strcmp(id, "__debug__") == 0) - return ! Py_OptimizeFlag; + return ! c->c_optimize; /* fall through */ default: return -1; @@ -4080,3 +4082,13 @@ assemble(struct compiler *c, int addNone) assemble_free(&a); return co; } + +#undef PyAST_Compile +PyAPI_FUNC(PyCodeObject *) +PyAST_Compile(mod_ty mod, const char *filename, PyCompilerFlags *flags, + PyArena *arena) +{ + return PyAST_CompileEx(mod, filename, flags, -1, arena); +} + + diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 3f6385d455..f7335a2b21 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1793,8 +1793,8 @@ run_pyc_file(FILE *fp, const char *filename, PyObject *globals, } PyObject * -Py_CompileStringFlags(const char *str, const char *filename, int start, - PyCompilerFlags *flags) +Py_CompileStringExFlags(const char *str, const char *filename, int start, + PyCompilerFlags *flags, int optimize) { PyCodeObject *co; mod_ty mod; @@ -1812,7 +1812,7 @@ Py_CompileStringFlags(const char *str, const char *filename, int start, PyArena_Free(arena); return result; } - co = PyAST_Compile(mod, filename, flags, arena); + co = PyAST_CompileEx(mod, filename, flags, optimize, arena); PyArena_Free(arena); return (PyObject *)co; } @@ -2450,7 +2450,15 @@ PyRun_SimpleString(const char *s) PyAPI_FUNC(PyObject *) Py_CompileString(const char *str, const char *p, int s) { - return Py_CompileStringFlags(str, p, s, NULL); + return Py_CompileStringExFlags(str, p, s, NULL, -1); +} + +#undef Py_CompileStringFlags +PyAPI_FUNC(PyObject *) +Py_CompileStringFlags(const char *str, const char *p, int s, + PyCompilerFlags *flags) +{ + return Py_CompileStringExFlags(str, p, s, flags, -1); } #undef PyRun_InteractiveOne -- cgit v1.2.1 From 0c9ffbd3962691222d01633e4a4a71b3103dcbb3 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 4 Dec 2010 17:24:33 +0000 Subject: Issue #10601: sys.displayhook uses 'backslashreplace' error handler on UnicodeEncodeError. --- Python/sysmodule.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 204c8c8cc9..0a14f0eb36 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -65,6 +65,68 @@ PySys_SetObject(const char *name, PyObject *v) return PyDict_SetItemString(sd, name, v); } +/* Write repr(o) to sys.stdout using sys.stdout.encoding and 'backslashreplace' + error handler. If sys.stdout has a buffer attribute, use + sys.stdout.buffer.write(encoded), otherwise redecode the string and use + sys.stdout.write(redecoded). + + Helper function for sys_displayhook(). */ +static int +sys_displayhook_unencodable(PyObject *outf, PyObject *o) +{ + PyObject *stdout_encoding = NULL; + PyObject *encoded, *escaped_str, *repr_str, *buffer, *result; + char *stdout_encoding_str; + int ret; + + stdout_encoding = PyObject_GetAttrString(outf, "encoding"); + if (stdout_encoding == NULL) + goto error; + stdout_encoding_str = _PyUnicode_AsString(stdout_encoding); + if (stdout_encoding_str == NULL) + goto error; + + repr_str = PyObject_Repr(o); + if (repr_str == NULL) + goto error; + encoded = PyUnicode_AsEncodedString(repr_str, + stdout_encoding_str, + "backslashreplace"); + Py_DECREF(repr_str); + if (encoded == NULL) + goto error; + + buffer = PyObject_GetAttrString(outf, "buffer"); + if (buffer) { + result = PyObject_CallMethod(buffer, "write", "(O)", encoded); + Py_DECREF(buffer); + Py_DECREF(encoded); + if (result == NULL) + goto error; + Py_DECREF(result); + } + else { + PyErr_Clear(); + escaped_str = PyUnicode_FromEncodedObject(encoded, + stdout_encoding_str, + "strict"); + Py_DECREF(encoded); + if (PyFile_WriteObject(escaped_str, outf, Py_PRINT_RAW) != 0) { + Py_DECREF(escaped_str); + goto error; + } + Py_DECREF(escaped_str); + } + ret = 0; + goto finally; + +error: + ret = -1; +finally: + Py_XDECREF(stdout_encoding); + return ret; +} + static PyObject * sys_displayhook(PyObject *self, PyObject *o) { @@ -72,6 +134,7 @@ sys_displayhook(PyObject *self, PyObject *o) PyInterpreterState *interp = PyThreadState_GET()->interp; PyObject *modules = interp->modules; PyObject *builtins = PyDict_GetItemString(modules, "builtins"); + int err; if (builtins == NULL) { PyErr_SetString(PyExc_RuntimeError, "lost builtins module"); @@ -92,8 +155,19 @@ sys_displayhook(PyObject *self, PyObject *o) PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout"); return NULL; } - if (PyFile_WriteObject(o, outf, 0) != 0) - return NULL; + if (PyFile_WriteObject(o, outf, 0) != 0) { + if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) { + /* repr(o) is not encodable to sys.stdout.encoding with + * sys.stdout.errors error handler (which is probably 'strict') */ + PyErr_Clear(); + err = sys_displayhook_unencodable(outf, o); + if (err) + return NULL; + } + else { + return NULL; + } + } if (PyFile_WriteString("\n", outf) != 0) return NULL; if (PyObject_SetAttrString(builtins, "_", o) != 0) -- cgit v1.2.1 From 6a156f487e0a2b723984dcd54640976b6436ac79 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Wed, 15 Dec 2010 22:59:16 +0000 Subject: Issue #8844: Regular and recursive lock acquisitions can now be interrupted by signals on platforms using pthreads. Patch by Reid Kleckner. --- Python/thread_nt.h | 19 +++++--- Python/thread_pthread.h | 112 +++++++++++++++++++++++++++++------------------- 2 files changed, 81 insertions(+), 50 deletions(-) (limited to 'Python') diff --git a/Python/thread_nt.h b/Python/thread_nt.h index 9de9e0dfbe..684b54598d 100644 --- a/Python/thread_nt.h +++ b/Python/thread_nt.h @@ -238,10 +238,13 @@ PyThread_free_lock(PyThread_type_lock aLock) * 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_timed(PyThread_type_lock aLock, PY_TIMEOUT_T microseconds) +PyLockStatus +PyThread_acquire_lock_timed(PyThread_type_lock aLock, + PY_TIMEOUT_T microseconds, int intr_flag) { - int success ; + /* Fow now, intr_flag does nothing on Windows, and lock acquires are + * uninterruptible. */ + PyLockStatus success; PY_TIMEOUT_T milliseconds; if (microseconds >= 0) { @@ -258,7 +261,13 @@ PyThread_acquire_lock_timed(PyThread_type_lock aLock, PY_TIMEOUT_T microseconds) dprintf(("%ld: PyThread_acquire_lock_timed(%p, %lld) called\n", PyThread_get_thread_ident(), aLock, microseconds)); - success = aLock && EnterNonRecursiveMutex((PNRMUTEX) aLock, (DWORD) milliseconds) == WAIT_OBJECT_0 ; + if (aLock && EnterNonRecursiveMutex((PNRMUTEX)aLock, + (DWORD)milliseconds) == WAIT_OBJECT_0) { + success = PY_LOCK_ACQUIRED; + } + else { + success = PY_LOCK_FAILURE; + } dprintf(("%ld: PyThread_acquire_lock(%p, %lld) -> %d\n", PyThread_get_thread_ident(), aLock, microseconds, success)); @@ -268,7 +277,7 @@ PyThread_acquire_lock_timed(PyThread_type_lock aLock, PY_TIMEOUT_T microseconds) int PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag) { - return PyThread_acquire_lock_timed(aLock, waitflag ? -1 : 0); + return PyThread_acquire_lock_timed(aLock, waitflag ? -1 : 0, 0); } void diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index c007c8b906..ffc791c578 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -316,16 +316,17 @@ fix_status(int status) return (status == -1) ? errno : status; } -int -PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds) +PyLockStatus +PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds, + int intr_flag) { - int success; + PyLockStatus success; sem_t *thelock = (sem_t *)lock; int status, error = 0; struct timespec ts; - dprintf(("PyThread_acquire_lock_timed(%p, %lld) called\n", - lock, microseconds)); + dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) called\n", + lock, microseconds, intr_flag)); if (microseconds > 0) MICROSECONDS_TO_TIMESPEC(microseconds, ts); @@ -336,33 +337,38 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds) status = fix_status(sem_trywait(thelock)); else status = fix_status(sem_wait(thelock)); - } while (status == EINTR); /* Retry if interrupted by a signal */ - - if (microseconds > 0) { - if (status != ETIMEDOUT) - CHECK_STATUS("sem_timedwait"); - } - else if (microseconds == 0) { - if (status != EAGAIN) - CHECK_STATUS("sem_trywait"); - } - else { - CHECK_STATUS("sem_wait"); + /* Retry if interrupted by a signal, unless the caller wants to be + notified. */ + } while (!intr_flag && status == EINTR); + + /* Don't check the status if we're stopping because of an interrupt. */ + if (!(intr_flag && status == EINTR)) { + if (microseconds > 0) { + if (status != ETIMEDOUT) + CHECK_STATUS("sem_timedwait"); + } + else if (microseconds == 0) { + if (status != EAGAIN) + CHECK_STATUS("sem_trywait"); + } + else { + CHECK_STATUS("sem_wait"); + } } - success = (status == 0) ? 1 : 0; + if (status == 0) { + success = PY_LOCK_ACQUIRED; + } else if (intr_flag && status == EINTR) { + success = PY_LOCK_INTR; + } else { + success = PY_LOCK_FAILURE; + } - dprintf(("PyThread_acquire_lock_timed(%p, %lld) -> %d\n", - lock, microseconds, success)); + dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) -> %d\n", + lock, microseconds, intr_flag, success)); return success; } -int -PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) -{ - return PyThread_acquire_lock_timed(lock, waitflag ? -1 : 0); -} - void PyThread_release_lock(PyThread_type_lock lock) { @@ -436,21 +442,25 @@ PyThread_free_lock(PyThread_type_lock lock) free((void *)thelock); } -int -PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds) +PyLockStatus +PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds, + int intr_flag) { - int success; + PyLockStatus success; pthread_lock *thelock = (pthread_lock *)lock; int status, error = 0; - dprintf(("PyThread_acquire_lock_timed(%p, %lld) called\n", - lock, microseconds)); + dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) called\n", + lock, microseconds, intr_flag)); status = pthread_mutex_lock( &thelock->mut ); CHECK_STATUS("pthread_mutex_lock[1]"); - success = thelock->locked == 0; - if (!success && microseconds != 0) { + if (thelock->locked == 0) { + success = PY_LOCK_ACQUIRED; + } else if (microseconds == 0) { + success = PY_LOCK_FAILURE; + } else { struct timespec ts; if (microseconds > 0) MICROSECONDS_TO_TIMESPEC(microseconds, ts); @@ -458,7 +468,8 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds) /* mut must be locked by me -- part of the condition * protocol */ - while (thelock->locked) { + success = PY_LOCK_FAILURE; + while (success == PY_LOCK_FAILURE) { if (microseconds > 0) { status = pthread_cond_timedwait( &thelock->lock_released, @@ -473,25 +484,30 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds) &thelock->mut); CHECK_STATUS("pthread_cond_wait"); } + + if (intr_flag && status == 0 && thelock->locked) { + /* We were woken up, but didn't get the lock. We probably received + * a signal. Return PY_LOCK_INTR to allow the caller to handle + * it and retry. */ + success = PY_LOCK_INTR; + break; + } else if (status == 0 && !thelock->locked) { + success = PY_LOCK_ACQUIRED; + } else { + success = PY_LOCK_FAILURE; + } } - success = (status == 0); } - if (success) thelock->locked = 1; + if (success == PY_LOCK_ACQUIRED) thelock->locked = 1; status = pthread_mutex_unlock( &thelock->mut ); CHECK_STATUS("pthread_mutex_unlock[1]"); - if (error) success = 0; - dprintf(("PyThread_acquire_lock_timed(%p, %lld) -> %d\n", - lock, microseconds, success)); + if (error) success = PY_LOCK_FAILURE; + dprintf(("PyThread_acquire_lock_timed(%p, %lld, %d) -> %d\n", + lock, microseconds, intr_flag, success)); return success; } -int -PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) -{ - return PyThread_acquire_lock_timed(lock, waitflag ? -1 : 0); -} - void PyThread_release_lock(PyThread_type_lock lock) { @@ -515,6 +531,12 @@ PyThread_release_lock(PyThread_type_lock lock) #endif /* USE_SEMAPHORES */ +int +PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) +{ + return PyThread_acquire_lock_timed(lock, waitflag ? -1 : 0, /*intr_flag=*/0); +} + /* set the thread stack size. * Return 0 if size is valid, -1 if size is invalid, * -2 if setting stack size is not supported. -- cgit v1.2.1 From 5c84d094727910799a607dddf3cf8f7008a6a65e Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 27 Dec 2010 20:10:36 +0000 Subject: Issue #10779: PyErr_WarnExplicit() decodes the filename from the filesystem encoding instead of UTF-8. --- Python/_warnings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/_warnings.c b/Python/_warnings.c index 87755e1edb..51c39e48d4 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -783,7 +783,7 @@ PyErr_WarnExplicit(PyObject *category, const char *text, { PyObject *res; PyObject *message = PyUnicode_FromString(text); - PyObject *filename = PyUnicode_FromString(filename_str); + PyObject *filename = PyUnicode_DecodeFSDefault(filename_str); PyObject *module = NULL; int ret = -1; -- cgit v1.2.1 From bc8d3f58c0217b4babbb9ff8d401901d1f15a7f3 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 28 Dec 2010 00:28:21 +0000 Subject: Issue #10780: PyErr_SetFromWindowsErrWithFilename() and PyErr_SetExcFromWindowsErrWithFilename() decode the filename from the filesystem encoding instead of UTF-8. --- Python/errors.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/errors.c b/Python/errors.c index d5a6fae0b4..5a9a624279 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -515,7 +515,7 @@ PyObject *PyErr_SetExcFromWindowsErrWithFilename( int ierr, const char *filename) { - PyObject *name = filename ? PyUnicode_FromString(filename) : NULL; + PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL; PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc, ierr, name); @@ -552,7 +552,7 @@ PyObject *PyErr_SetFromWindowsErrWithFilename( int ierr, const char *filename) { - PyObject *name = filename ? PyUnicode_FromString(filename) : NULL; + PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL; PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject( PyExc_WindowsError, ierr, name); -- cgit v1.2.1 From 37eff4f6fb0628592d5d39b6cec49ccd8ce4a333 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Tue, 28 Dec 2010 18:30:18 +0000 Subject: Add sys.flags.quiet attribute for the new -q option, as noted missing by Eric in #1772833. --- Python/pythonrun.c | 1 + Python/sysmodule.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index f7335a2b21..e3836b8b7c 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -78,6 +78,7 @@ extern void _PyGILState_Fini(void); int Py_DebugFlag; /* Needed by parser.c */ int Py_VerboseFlag; /* Needed by import.c */ +int Py_QuietFlag; /* Needed by sysmodule.c */ int Py_InteractiveFlag; /* Needed by Py_FdIsInteractive() below */ int Py_InspectFlag; /* Needed to determine whether to exit at SystemError */ int Py_NoSiteFlag; /* Suppress 'import site' */ diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 0a14f0eb36..730567eaf7 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1417,7 +1417,8 @@ static PyStructSequence_Field flags_fields[] = { #endif /* {"unbuffered", "-u"}, */ /* {"skip_first", "-x"}, */ - {"bytes_warning", "-b"}, + {"bytes_warning", "-b"}, + {"quiet", "-q"}, {0} }; @@ -1461,6 +1462,7 @@ make_flags(void) /* SetFlag(saw_unbuffered_flag); */ /* SetFlag(skipfirstline); */ SetFlag(Py_BytesWarningFlag); + SetFlag(Py_QuietFlag); #undef SetFlag if (PyErr_Occurred()) { -- cgit v1.2.1 From 38f6f0e372ad7468c69956d143c0dd22fe311b50 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 1 Jan 2011 14:28:31 +0000 Subject: update copyright to 2011 --- Python/getcopyright.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/getcopyright.c b/Python/getcopyright.c index 43a0293885..1388f2c98c 100644 --- a/Python/getcopyright.c +++ b/Python/getcopyright.c @@ -4,7 +4,7 @@ static char cprt[] = "\ -Copyright (c) 2001-2010 Python Software Foundation.\n\ +Copyright (c) 2001-2011 Python Software Foundation.\n\ All Rights Reserved.\n\ \n\ Copyright (c) 2000 BeOpen.com.\n\ -- cgit v1.2.1 From a99a431f5ecdd9c7185eea5ab4bba79575ef92c6 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 4 Jan 2011 02:07:34 +0000 Subject: Issue #8651: PyArg_Parse*() functions raise an OverflowError if the file doesn't have PY_SSIZE_T_CLEAN define and the size doesn't fit in an int (length bigger than 2^31-1). --- Python/getargs.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index cf9869965c..aac1d177a7 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -597,7 +597,17 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, #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 STORE_SIZE(s) \ + if (flags & FLAG_SIZE_T) \ + *q2=s; \ + else { \ + if (INT_MAX < s) { \ + PyErr_SetString(PyExc_OverflowError, \ + "size does not fit in an int"); \ + return converterr("", arg, msgbuf, bufsize); \ + } \ + *q=s; \ + } #define BUFFER_LEN ((flags & FLAG_SIZE_T) ? *q2:*q) const char *format = *p_format; -- cgit v1.2.1 From f4d435f0800e226d7b69b399f1d959e4909182fd Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 4 Jan 2011 11:16:48 +0000 Subject: Issue #8992: Simplify addcleanup() API Don't need to handle unknown destructor anymore. --- Python/getargs.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index aac1d177a7..487f1aa9c0 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -146,10 +146,19 @@ cleanup_buffer(PyObject *self) } static int -addcleanup(void *ptr, PyObject **freelist, PyCapsule_Destructor destr) +addcleanup(void *ptr, PyObject **freelist, int is_buffer) { PyObject *cobj; const char *name; + PyCapsule_Destructor destr; + + if (is_buffer) { + destr = cleanup_buffer; + name = GETARGS_CAPSULE_NAME_CLEANUP_BUFFER; + } else { + destr = cleanup_ptr; + name = GETARGS_CAPSULE_NAME_CLEANUP_PTR; + } if (!*freelist) { *freelist = PyList_New(0); @@ -159,13 +168,6 @@ addcleanup(void *ptr, PyObject **freelist, PyCapsule_Destructor destr) } } - if (destr == cleanup_ptr) { - name = GETARGS_CAPSULE_NAME_CLEANUP_PTR; - } else if (destr == cleanup_buffer) { - name = GETARGS_CAPSULE_NAME_CLEANUP_BUFFER; - } else { - return -1; - } cobj = PyCapsule_New(ptr, name, destr); if (!cobj) { destr(ptr); @@ -855,7 +857,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, if (getbuffer(arg, (Py_buffer*)p, &buf) < 0) return converterr(buf, arg, msgbuf, bufsize); format++; - if (addcleanup(p, freelist, cleanup_buffer)) { + if (addcleanup(p, freelist, 1)) { return converterr( "(cleanup problem)", arg, msgbuf, bufsize); @@ -901,7 +903,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, if (getbuffer(arg, p, &buf) < 0) return converterr(buf, arg, msgbuf, bufsize); } - if (addcleanup(p, freelist, cleanup_buffer)) { + if (addcleanup(p, freelist, 1)) { return converterr( "(cleanup problem)", arg, msgbuf, bufsize); @@ -1109,7 +1111,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, "(memory error)", arg, msgbuf, bufsize); } - if (addcleanup(*buffer, freelist, cleanup_ptr)) { + if (addcleanup(*buffer, freelist, 0)) { Py_DECREF(s); return converterr( "(cleanup problem)", @@ -1152,7 +1154,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, return converterr("(memory error)", arg, msgbuf, bufsize); } - if (addcleanup(*buffer, freelist, cleanup_ptr)) { + if (addcleanup(*buffer, freelist, 0)) { Py_DECREF(s); return converterr("(cleanup problem)", arg, msgbuf, bufsize); @@ -1244,7 +1246,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, PyBuffer_Release((Py_buffer*)p); return converterr("contiguous buffer", arg, msgbuf, bufsize); } - if (addcleanup(p, freelist, cleanup_buffer)) { + if (addcleanup(p, freelist, 1)) { return converterr( "(cleanup problem)", arg, msgbuf, bufsize); -- cgit v1.2.1 From 6509b37bb8032193baa39e2526501b96bc763b75 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 4 Jan 2011 11:16:49 +0000 Subject: Issue #8992: convertsimple() doesn't need to fill msgbuf if an error occurred Return msgbug on error is enough. --- Python/getargs.c | 79 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 38 deletions(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index 487f1aa9c0..600941d9c7 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -611,6 +611,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, *q=s; \ } #define BUFFER_LEN ((flags & FLAG_SIZE_T) ? *q2:*q) +#define RETURN_ERR_OCCURRED return msgbuf const char *format = *p_format; char c = *format++; @@ -622,19 +623,19 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, char *p = va_arg(*p_va, char *); long ival; if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; ival = PyLong_AsLong(arg); if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; else if (ival < 0) { PyErr_SetString(PyExc_OverflowError, - "unsigned byte integer is less than minimum"); - return converterr("integer", arg, msgbuf, bufsize); + "unsigned byte integer is less than minimum"); + RETURN_ERR_OCCURRED; } else if (ival > UCHAR_MAX) { PyErr_SetString(PyExc_OverflowError, - "unsigned byte integer is greater than maximum"); - return converterr("integer", arg, msgbuf, bufsize); + "unsigned byte integer is greater than maximum"); + RETURN_ERR_OCCURRED; } else *p = (unsigned char) ival; @@ -646,10 +647,10 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, char *p = va_arg(*p_va, char *); long ival; if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; ival = PyLong_AsUnsignedLongMask(arg); if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; else *p = (unsigned char) ival; break; @@ -659,19 +660,19 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, short *p = va_arg(*p_va, short *); long ival; if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; ival = PyLong_AsLong(arg); if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; else if (ival < SHRT_MIN) { PyErr_SetString(PyExc_OverflowError, - "signed short integer is less than minimum"); - return converterr("integer", arg, msgbuf, bufsize); + "signed short integer is less than minimum"); + RETURN_ERR_OCCURRED; } else if (ival > SHRT_MAX) { PyErr_SetString(PyExc_OverflowError, - "signed short integer is greater than maximum"); - return converterr("integer", arg, msgbuf, bufsize); + "signed short integer is greater than maximum"); + RETURN_ERR_OCCURRED; } else *p = (short) ival; @@ -683,10 +684,10 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, unsigned short *p = va_arg(*p_va, unsigned short *); long ival; if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; ival = PyLong_AsUnsignedLongMask(arg); if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; else *p = (unsigned short) ival; break; @@ -696,19 +697,19 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, int *p = va_arg(*p_va, int *); long ival; if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; ival = PyLong_AsLong(arg); if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; else if (ival > INT_MAX) { PyErr_SetString(PyExc_OverflowError, - "signed integer is greater than maximum"); - return converterr("integer", arg, msgbuf, bufsize); + "signed integer is greater than maximum"); + RETURN_ERR_OCCURRED; } else if (ival < INT_MIN) { PyErr_SetString(PyExc_OverflowError, - "signed integer is less than minimum"); - return converterr("integer", arg, msgbuf, bufsize); + "signed integer is less than minimum"); + RETURN_ERR_OCCURRED; } else *p = ival; @@ -720,10 +721,10 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, unsigned int *p = va_arg(*p_va, unsigned int *); unsigned int ival; if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; ival = (unsigned int)PyLong_AsUnsignedLongMask(arg); if (ival == (unsigned int)-1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; else *p = ival; break; @@ -735,14 +736,14 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, Py_ssize_t *p = va_arg(*p_va, Py_ssize_t *); Py_ssize_t ival = -1; if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; iobj = PyNumber_Index(arg); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); } if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; *p = ival; break; } @@ -750,10 +751,10 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, long *p = va_arg(*p_va, long *); long ival; if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; ival = PyLong_AsLong(arg); if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; else *p = ival; break; @@ -775,10 +776,10 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, PY_LONG_LONG *p = va_arg( *p_va, PY_LONG_LONG * ); PY_LONG_LONG ival; if (float_argument_error(arg)) - return converterr("long", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; ival = PyLong_AsLongLong(arg); if (ival == (PY_LONG_LONG)-1 && PyErr_Occurred()) - return converterr("long", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; else *p = ival; break; @@ -800,7 +801,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, float *p = va_arg(*p_va, float *); double dval = PyFloat_AsDouble(arg); if (PyErr_Occurred()) - return converterr("float", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; else *p = (float) dval; break; @@ -810,7 +811,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, double *p = va_arg(*p_va, double *); double dval = PyFloat_AsDouble(arg); if (PyErr_Occurred()) - return converterr("float", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; else *p = dval; break; @@ -821,7 +822,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, Py_complex cval; cval = PyComplex_AsCComplex(arg); if (PyErr_Occurred()) - return converterr("complex", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; else *p = cval; break; @@ -1107,9 +1108,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, if (*buffer == NULL) { Py_DECREF(s); PyErr_NoMemory(); - return converterr( - "(memory error)", - arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; } if (addcleanup(*buffer, freelist, 0)) { Py_DECREF(s); @@ -1151,8 +1150,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, if (*buffer == NULL) { Py_DECREF(s); PyErr_NoMemory(); - return converterr("(memory error)", - arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; } if (addcleanup(*buffer, freelist, 0)) { Py_DECREF(s); @@ -1261,6 +1259,11 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, *p_format = format; return NULL; + +#undef FETCH_SIZE +#undef STORE_SIZE +#undef BUFFER_LEN +#undef RETURN_ERR_OCCURRED } static Py_ssize_t -- cgit v1.2.1 From d4a9fa435abe536522fb0343710feac61914ce00 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 4 Jan 2011 12:59:15 +0000 Subject: Issue #9566: use Py_ssize_t instead of int --- Python/pythonrun.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index e3836b8b7c..33f187386a 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1202,7 +1202,8 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, { PyObject *m, *d, *v; const char *ext; - int set_file_name = 0, ret, len; + int set_file_name = 0, ret; + size_t len; m = PyImport_AddModule("__main__"); if (m == NULL) -- cgit v1.2.1 From f303db16856c70e7f64c09259ea7e620beec5755 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Wed, 5 Jan 2011 20:08:25 +0000 Subject: Fix count of flag fields. Being one short caused the 'quiet' option not to print. --- Python/sysmodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 730567eaf7..de51155a49 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1427,9 +1427,9 @@ static PyStructSequence_Desc flags_desc = { flags__doc__, /* doc */ flags_fields, /* fields */ #ifdef RISCOS - 12 + 13 #else - 11 + 12 #endif }; -- cgit v1.2.1 From 9c22d6ae9460085bb73e3594cbcc70afb6a14848 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 6 Jan 2011 17:01:36 +0000 Subject: Issue #10655: Fix the build on PowerPC on Linux with GCC when building with timestamp profiling (--with-tsc): the preprocessor test for the PowerPC support now looks for "__powerpc__" as well as "__ppc__": the latter seems to only be present on OS X; the former is the correct one for Linux with GCC. --- Python/ceval.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 684c6c28f3..f6d4b0b84b 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -26,10 +26,11 @@ 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 :-) */ +/* PowerPC suppport. + "__ppc__" appears to be the preprocessor definition to detect on OS X, whereas + "__powerpc__" appears to be the correct one for Linux with GCC +*/ +#if defined(__ppc__) || defined (__powerpc__) #define READ_TIMESTAMP(var) ppc_getcounter(&var) -- cgit v1.2.1 From 79ee3cd66781264ae87a8a269b686ae9e3b5bc8c Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sat, 15 Jan 2011 11:37:11 +0000 Subject: Fix the GIL with subinterpreters. Hopefully this will allow mod_wsgi to work with 3.2. (we need some tests for this) --- Python/ceval_gil.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/ceval_gil.h b/Python/ceval_gil.h index 40e45f75f2..bf7a350791 100644 --- a/Python/ceval_gil.h +++ b/Python/ceval_gil.h @@ -334,12 +334,15 @@ static void recreate_gil(void) static void drop_gil(PyThreadState *tstate) { - /* NOTE: tstate is allowed to be NULL. */ if (!_Py_atomic_load_relaxed(&gil_locked)) Py_FatalError("drop_gil: GIL is not locked"); - if (tstate != NULL && - tstate != _Py_atomic_load_relaxed(&gil_last_holder)) - Py_FatalError("drop_gil: wrong thread state"); + /* tstate is allowed to be NULL (early interpreter init) */ + if (tstate != NULL) { + /* Sub-interpreter support: threads might have been switched + under our feet using PyThreadState_Swap(). Fix the GIL last + holder variable so that our heuristics work. */ + _Py_atomic_store_relaxed(&gil_last_holder, tstate); + } MUTEX_LOCK(gil_mutex); _Py_ANNOTATE_RWLOCK_RELEASED(&gil_locked, /*is_write=*/1); -- cgit v1.2.1 From b04d999d5e246006478b7d7551ad4927a29abe06 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Tue, 15 Feb 2011 19:48:59 +0000 Subject: #730467: Another small AIX fix. --- Python/dynload_aix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/dynload_aix.c b/Python/dynload_aix.c index 8d56d7d008..149990d799 100644 --- a/Python/dynload_aix.c +++ b/Python/dynload_aix.c @@ -12,7 +12,7 @@ #ifdef AIX_GENUINE_CPLUSPLUS -#include "/usr/lpp/xlC/include/load.h" +#include #define aix_load loadAndInit #else #define aix_load load -- cgit v1.2.1 From a73a92af0473a634b74becf20fd96bd612fc35e0 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 23 Feb 2011 12:10:23 +0000 Subject: Merged revisions 88530 via svnmerge from svn+ssh://pythondev@svn.python.org/python/branches/py3k MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ........ r88530 | victor.stinner | 2011-02-23 13:07:37 +0100 (mer., 23 févr. 2011) | 4 lines Issue #11272: Fix input() and sys.stdin for Windows newline On Windows, input() strips '\r' (and not only '\n'), and sys.stdin uses universal newline (replace '\r\n' by '\n'). ........ --- Python/bltinmodule.c | 13 +++++++++---- Python/pythonrun.c | 11 ++++++++++- 2 files changed, 19 insertions(+), 5 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index f9b3202d54..2aea9f745f 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1621,6 +1621,7 @@ builtin_input(PyObject *self, PyObject *args) PyObject *stdin_encoding; char *stdin_encoding_str; PyObject *result; + size_t len; stdin_encoding = PyObject_GetAttrString(fin, "encoding"); if (!stdin_encoding) @@ -1685,19 +1686,23 @@ builtin_input(PyObject *self, PyObject *args) Py_DECREF(stdin_encoding); return NULL; } - if (*s == '\0') { + + len = strlen(s); + if (len == 0) { PyErr_SetNone(PyExc_EOFError); result = NULL; } - else { /* strip trailing '\n' */ - size_t len = strlen(s); + else { if (len > PY_SSIZE_T_MAX) { PyErr_SetString(PyExc_OverflowError, "input: input too long"); result = NULL; } else { - result = PyUnicode_Decode(s, len-1, stdin_encoding_str, NULL); + len--; /* strip trailing '\n' */ + if (len != 0 && s[len-1] == '\r') + len--; /* strip trailing '\r' */ + result = PyUnicode_Decode(s, len, stdin_encoding_str, NULL); } } Py_DECREF(stdin_encoding); diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 33f187386a..8e97d7fc24 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -778,6 +778,7 @@ create_stdio(PyObject* io, { PyObject *buf = NULL, *stream = NULL, *text = NULL, *raw = NULL, *res; const char* mode; + const char* newline; PyObject *line_buffering; int buffering, isatty; @@ -828,9 +829,17 @@ create_stdio(PyObject* io, Py_CLEAR(raw); Py_CLEAR(text); + newline = "\n"; +#ifdef MS_WINDOWS + if (!write_mode) { + /* translate \r\n to \n for sys.stdin on Windows */ + newline = NULL; + } +#endif + stream = PyObject_CallMethod(io, "TextIOWrapper", "OsssO", buf, encoding, errors, - "\n", line_buffering); + newline, line_buffering); Py_CLEAR(buf); if (stream == NULL) goto error; -- cgit v1.2.1 From 1461e055cc52862f93f225a129b332dbd64f193c Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Tue, 15 Mar 2011 14:50:16 -0700 Subject: Issue 11510: Fix BUILD_SET optimizer bug. --- Python/peephole.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/peephole.c b/Python/peephole.c index f972e1611e..6985043917 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -475,7 +475,8 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, } if (codestr[i+3] != UNPACK_SEQUENCE || !ISBASICBLOCK(blocks,i,6) || - j != GETARG(codestr, i+3)) + j != GETARG(codestr, i+3) || + opcode == BUILD_SET) continue; if (j == 1) { memset(codestr+i, NOP, 6); -- cgit v1.2.1 From 496f14b82b0a34082d0987ceaae21e4e226628dd Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 20 Mar 2011 23:23:22 +0100 Subject: Fix #11586: typo in initfsencoding() Patch written by Ray Allen. --- Python/pythonrun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 8e97d7fc24..38b2ab84fb 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -147,7 +147,7 @@ get_codec_name(const char *encoding) goto error; name_utf8 = _PyUnicode_AsString(name); - if (name == NULL) + if (name_utf8 == NULL) goto error; name_str = strdup(name_utf8); Py_DECREF(name); -- cgit v1.2.1 From 1a0c484d72946ce13c9204c48dd9ee3528cd8070 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Thu, 31 Mar 2011 01:00:32 +0200 Subject: Issue #11618: Fix the timeout logic in threading.Lock.acquire() under Windows. --- Python/thread_nt.h | 67 +++++++----------------------------------------------- 1 file changed, 8 insertions(+), 59 deletions(-) (limited to 'Python') diff --git a/Python/thread_nt.h b/Python/thread_nt.h index 684b54598d..d1bb0e5673 100644 --- a/Python/thread_nt.h +++ b/Python/thread_nt.h @@ -9,82 +9,31 @@ #include #endif -typedef struct NRMUTEX { - LONG owned ; - DWORD thread_id ; - HANDLE hevent ; -} NRMUTEX, *PNRMUTEX ; +#define PNRMUTEX HANDLE - -BOOL -InitializeNonRecursiveMutex(PNRMUTEX mutex) +PNRMUTEX +AllocNonRecursiveMutex() { - 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 */ + return CreateSemaphore(NULL, 1, 1, NULL); } VOID -DeleteNonRecursiveMutex(PNRMUTEX mutex) +FreeNonRecursiveMutex(PNRMUTEX mutex) { /* No in-use check */ - CloseHandle(mutex->hevent) ; - mutex->hevent = NULL ; /* Just in case */ + CloseHandle(mutex); } DWORD EnterNonRecursiveMutex(PNRMUTEX mutex, DWORD milliseconds) { - /* Assume that the thread waits successfully */ - DWORD ret ; - - /* InterlockedIncrement(&mutex->owned) == 0 means that no thread currently owns the mutex */ - if (milliseconds == 0) - { - if (InterlockedCompareExchange(&mutex->owned, 0, -1) != -1) - return WAIT_TIMEOUT ; - ret = WAIT_OBJECT_0 ; - } - else - ret = InterlockedIncrement(&mutex->owned) ? - /* Some thread owns the mutex, let's wait... */ - WaitForSingleObject(mutex->hevent, milliseconds) : WAIT_OBJECT_0 ; - - mutex->thread_id = GetCurrentThreadId() ; /* We own it */ - return ret ; + return WaitForSingleObject(mutex, milliseconds); } 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) ; - } + return ReleaseSemaphore(mutex, 1, NULL); } long PyThread_get_thread_ident(void); -- cgit v1.2.1 From 6b836616e2e69184bce1d534b9b00204779f580d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 31 Mar 2011 13:39:03 +0200 Subject: sys.getfilesystemencoding() raises a RuntimeError if initfsencoding() was not called yet: detect bootstrap (startup) issues earlier. --- Python/sysmodule.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 8d44135be1..5664646381 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -259,8 +259,9 @@ sys_getfilesystemencoding(PyObject *self) { if (Py_FileSystemDefaultEncoding) return PyUnicode_FromString(Py_FileSystemDefaultEncoding); - Py_INCREF(Py_None); - return Py_None; + PyErr_SetString(PyExc_RuntimeError, + "filesystem encoding is not initialized"); + return NULL; } PyDoc_STRVAR(getfilesystemencoding_doc, -- cgit v1.2.1 From a7df45e6fbba4af091785a764055c44f56f57460 Mon Sep 17 00:00:00 2001 From: Alexander Belopolsky Date: Thu, 7 Apr 2011 00:15:33 -0400 Subject: Removed 'or long integer' from bin, oct, and hex docstrings. --- Python/bltinmodule.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 2aea9f745f..6258167b60 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -307,7 +307,7 @@ builtin_bin(PyObject *self, PyObject *v) PyDoc_STRVAR(bin_doc, "bin(number) -> string\n\ \n\ -Return the binary representation of an integer or long integer."); +Return the binary representation of an integer."); static PyObject * @@ -1192,7 +1192,7 @@ builtin_hex(PyObject *self, PyObject *v) PyDoc_STRVAR(hex_doc, "hex(number) -> string\n\ \n\ -Return the hexadecimal representation of an integer or long integer."); +Return the hexadecimal representation of an integer."); static PyObject * @@ -1380,7 +1380,7 @@ builtin_oct(PyObject *self, PyObject *v) PyDoc_STRVAR(oct_doc, "oct(number) -> string\n\ \n\ -Return the octal representation of an integer or long integer."); +Return the octal representation of an integer."); static PyObject * -- cgit v1.2.1 From 33c84dd0d6eb999583f77e916d943235230d6e0d Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Wed, 27 Apr 2011 19:28:05 +0200 Subject: =?UTF-8?q?Issue=20#10517:=20After=20fork(),=20reinitialize=20the?= =?UTF-8?q?=20TLS=20used=20by=20the=20PyGILState=5F*=20APIs,=20to=20avoid?= =?UTF-8?q?=20a=20crash=20with=20the=20pthread=20implementation=20in=20RHE?= =?UTF-8?q?L=205.=20=20Patch=20by=20Charles-Fran=C3=A7ois=20Natali.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Python/pystate.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'Python') diff --git a/Python/pystate.c b/Python/pystate.c index 922e9a3780..586b856603 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -585,6 +585,23 @@ _PyGILState_Fini(void) autoInterpreterState = NULL; } +/* Reset the TLS key - called by PyOS_AfterFork. + * This should not be necessary, but some - buggy - pthread implementations + * don't flush TLS on fork, see issue #10517. + */ +void +_PyGILState_Reinit(void) +{ + PyThreadState *tstate = PyGILState_GetThisThreadState(); + PyThread_delete_key(autoTLSkey); + if ((autoTLSkey = PyThread_create_key()) == -1) + Py_FatalError("Could not allocate TLS entry"); + + /* re-associate the current thread state with the new key */ + if (PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0) + Py_FatalError("Couldn't create autoTLSkey mapping"); +} + /* 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 -- cgit v1.2.1 From 0ed611ee5df5214a93916fed71b8804b966570c5 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 27 Apr 2011 00:20:27 +0200 Subject: Issue #10914: Py_NewInterpreter() uses PyErr_PrintEx(0) ... instead of PyErr_Print() because we don't need to set sys attributes, the sys module is destroyed just after printing the error. --- Python/pythonrun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 38b2ab84fb..6251e30a34 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -622,7 +622,7 @@ Py_NewInterpreter(void) handle_error: /* Oops, it didn't work. Undo it all. */ - PyErr_Print(); + PyErr_PrintEx(0); PyThreadState_Clear(tstate); PyThreadState_Swap(save_tstate); PyThreadState_Delete(tstate); -- cgit v1.2.1 From aa039cee1babca74cc172aae2886c7c2da30ea8d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 27 Apr 2011 00:24:21 +0200 Subject: Issue #10914: Initialize correctly the filesystem codec when creating a new subinterpreter to fix a bootstrap issue with codecs implemented in Python, as the ISO-8859-15 codec. Add fscodec_initialized attribute to the PyInterpreterState structure. --- Python/pystate.c | 1 + Python/pythonrun.c | 23 +++++++++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) (limited to 'Python') diff --git a/Python/pystate.c b/Python/pystate.c index 586b856603..b347c41c54 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -79,6 +79,7 @@ PyInterpreterState_New(void) interp->codec_search_cache = NULL; interp->codec_error_registry = NULL; interp->codecs_initialized = 0; + interp->fscodec_initialized = 0; #ifdef HAVE_DLOPEN #ifdef RTLD_NOW interp->dlopenflags = RTLD_NOW; diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 6251e30a34..faaf54a0a6 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -53,7 +53,7 @@ extern grammar _PyParser_Grammar; /* From graminit.c */ /* Forward */ static void initmain(void); -static void initfsencoding(void); +static int initfsencoding(PyInterpreterState *interp); static void initsite(void); static int initstdio(void); static void flush_io(void); @@ -291,7 +291,8 @@ Py_InitializeEx(int install_sigs) _PyTime_Init(); - initfsencoding(); + if (initfsencoding(interp) < 0) + Py_FatalError("Py_Initialize: unable to load the file system codec"); if (install_sigs) initsigs(); /* Signal handling stuff, including initintr() */ @@ -608,6 +609,10 @@ Py_NewInterpreter(void) Py_DECREF(pstderr); _PyImportHooks_Init(); + + if (initfsencoding(interp) < 0) + goto handle_error; + if (initstdio() < 0) Py_FatalError( "Py_Initialize: can't initialize sys standard streams"); @@ -720,8 +725,8 @@ initmain(void) } } -static void -initfsencoding(void) +static int +initfsencoding(PyInterpreterState *interp) { PyObject *codec; #if defined(HAVE_LANGINFO_H) && defined(CODESET) @@ -738,7 +743,8 @@ initfsencoding(void) Py_FileSystemDefaultEncoding = codeset; Py_HasFileSystemDefaultEncoding = 0; - return; + interp->fscodec_initialized = 1; + return 0; } #endif @@ -748,10 +754,11 @@ initfsencoding(void) /* Such error can only occurs in critical situations: no more * memory, import a module of the standard library failed, * etc. */ - Py_FatalError("Py_Initialize: unable to load the file system codec"); - } else { - Py_DECREF(codec); + return -1; } + Py_DECREF(codec); + interp->fscodec_initialized = 1; + return 0; } /* Import the site module (not into __main__ though) */ -- cgit v1.2.1 From 89ae6ab2a2cfece70bf55c2a314376093e6a1a41 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Wed, 4 May 2011 20:02:30 +0200 Subject: Issue #1856: Avoid crashes and lockups when daemon threads run while the interpreter is shutting down; instead, these threads are now killed when they try to take the GIL. --- Python/ceval.c | 6 ++++++ Python/pythonrun.c | 15 +++++++++++---- Python/thread_pthread.h | 4 ++-- 3 files changed, 19 insertions(+), 6 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 43a5c904d1..705ed415a9 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -440,6 +440,12 @@ PyEval_RestoreThread(PyThreadState *tstate) if (gil_created()) { int err = errno; take_gil(tstate); + /* _Py_Finalizing is protected by the GIL */ + if (_Py_Finalizing && tstate != _Py_Finalizing) { + drop_gil(tstate); + PyThread_exit_thread(); + assert(0); /* unreachable */ + } errno = err; } #endif diff --git a/Python/pythonrun.c b/Python/pythonrun.c index faaf54a0a6..1e2dd586b4 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -90,6 +90,8 @@ int Py_IgnoreEnvironmentFlag; /* e.g. PYTHONPATH, PYTHONHOME */ int Py_NoUserSiteDirectory = 0; /* for -s and site.py */ int Py_UnbufferedStdioFlag = 0; /* Unbuffered binary std{in,out,err} */ +PyThreadState *_Py_Finalizing = NULL; + /* PyModule_GetWarningsModule is no longer necessary as of 2.6 since _warnings is builtin. This API should not be used. */ PyObject * @@ -188,6 +190,7 @@ Py_InitializeEx(int install_sigs) if (initialized) return; initialized = 1; + _Py_Finalizing = NULL; #if defined(HAVE_LANGINFO_H) && defined(HAVE_SETLOCALE) /* Set up the LC_CTYPE locale, so we can obtain @@ -388,15 +391,19 @@ Py_Finalize(void) * the threads created via Threading. */ call_py_exitfuncs(); - initialized = 0; - - /* Flush stdout+stderr */ - flush_std_files(); /* Get current thread state and interpreter pointer */ tstate = PyThreadState_GET(); interp = tstate->interp; + /* Remaining threads (e.g. daemon threads) will automatically exit + after taking the GIL (in PyEval_RestoreThread()). */ + _Py_Finalizing = tstate; + initialized = 0; + + /* Flush stdout+stderr */ + flush_std_files(); + /* Disable signal handling */ PyOS_FiniInterrupts(); diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index ffc791c578..6bc9d55781 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -250,9 +250,9 @@ void PyThread_exit_thread(void) { dprintf(("PyThread_exit_thread called\n")); - if (!initialized) { + if (!initialized) exit(0); - } + pthread_exit(0); } #ifdef USE_SEMAPHORES -- cgit v1.2.1 From afc882a4bd8bf7a779062470bb2c2ee2690ee661 Mon Sep 17 00:00:00 2001 From: Vinay Sajip Date: Sat, 2 Jul 2011 16:42:47 +0100 Subject: Closes #12291: Fixed bug which was found when doing multiple loads from one stream. --- Python/marshal.c | 215 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 155 insertions(+), 60 deletions(-) (limited to 'Python') diff --git a/Python/marshal.c b/Python/marshal.c index 73d4f374cd..396e05c638 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -57,6 +57,7 @@ typedef struct { int error; /* see WFERR_* values */ int depth; /* If fp == NULL, the following are valid: */ + PyObject * readable; /* Stream-like object being read from */ PyObject *str; char *ptr; char *end; @@ -466,27 +467,75 @@ 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; + char * ptr; + int read, left; + + if (!p->readable) { + if (p->fp != NULL) + /* The result fits into int because it must be <=n. */ + read = (int) fread(s, 1, n, p->fp); + else { + left = (int)(p->end - p->ptr); + read = (left < n) ? left : n; + memcpy(s, p->ptr, read); + p->ptr += read; + } + } + else { + PyObject *data = PyObject_CallMethod(p->readable, "read", "i", n); + read = 0; + if (data != NULL) { + if (!PyBytes_Check(data)) { + PyErr_Format(PyExc_TypeError, + "f.read() returned not bytes but %.100s", + data->ob_type->tp_name); + } + else { + read = PyBytes_GET_SIZE(data); + if (read > 0) { + ptr = PyBytes_AS_STRING(data); + memcpy(s, ptr, read); + } + } + Py_DECREF(data); + } + } + if (!PyErr_Occurred() && (read < n)) { + PyErr_SetString(PyExc_EOFError, "EOF read where not expected"); + } + return read; +} + + +static int +r_byte(RFILE *p) +{ + int c = EOF; + unsigned char ch; + int n; + + if (!p->readable) + c = p->fp ? getc(p->fp) : rs_byte(p); + else { + n = r_string((char *) &ch, 1, p); + if (n > 0) + c = ch; + } + return c; } static int r_short(RFILE *p) { register short x; - x = r_byte(p); - x |= r_byte(p) << 8; + unsigned char buffer[2]; + + r_string((char *) buffer, 2, p); + x = buffer[0]; + x |= buffer[1] << 8; /* Sign-extension, in case short greater than 16 bits */ x |= -(x & 0x8000); return x; @@ -496,19 +545,13 @@ 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; - } + unsigned char buffer[4]; + + r_string((char *) buffer, 4, p); + x = buffer[0]; + x |= (long)buffer[1] << 8; + x |= (long)buffer[2] << 16; + x |= (long)buffer[3] << 24; #if SIZEOF_LONG > 4 /* Sign extension for 64-bit machines */ x |= -(x & 0x80000000L); @@ -526,25 +569,30 @@ r_long(RFILE *p) static PyObject * r_long64(RFILE *p) { + PyObject * result = NULL; long lo4 = r_long(p); long hi4 = r_long(p); + + if (!PyErr_Occurred()) { #if SIZEOF_LONG > 4 - long x = (hi4 << 32) | (lo4 & 0xFFFFFFFFL); - return PyLong_FromLong(x); + long x = (hi4 << 32) | (lo4 & 0xFFFFFFFFL); + result = PyLong_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); + 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); + } + result = _PyLong_FromByteArray(buf, 8, is_little_endian, 1); #endif + } + return result; } static PyObject * @@ -556,6 +604,8 @@ r_PyLong(RFILE *p) digit d; n = r_long(p); + if (PyErr_Occurred()) + return NULL; if (n == 0) return (PyObject *)_PyLong_New(0); if (n < -INT_MAX || n > INT_MAX) { @@ -575,6 +625,8 @@ r_PyLong(RFILE *p) d = 0; for (j=0; j < PyLong_MARSHAL_RATIO; j++) { md = r_short(p); + if (PyErr_Occurred()) + break; if (md < 0 || md > PyLong_MARSHAL_BASE) goto bad_digit; d += (digit)md << j*PyLong_MARSHAL_SHIFT; @@ -584,6 +636,8 @@ r_PyLong(RFILE *p) d = 0; for (j=0; j < shorts_in_top_digit; j++) { md = r_short(p); + if (PyErr_Occurred()) + break; if (md < 0 || md > PyLong_MARSHAL_BASE) goto bad_digit; /* topmost marshal digit should be nonzero */ @@ -595,6 +649,10 @@ r_PyLong(RFILE *p) } d += (digit)md << j*PyLong_MARSHAL_SHIFT; } + if (PyErr_Occurred()) { + Py_DECREF(ob); + return NULL; + } /* top digit should be nonzero, else the resulting PyLong won't be normalized */ ob->ob_digit[size-1] = d; @@ -663,7 +721,8 @@ r_object(RFILE *p) break; case TYPE_INT: - retval = PyLong_FromLong(r_long(p)); + n = r_long(p); + retval = PyErr_Occurred() ? NULL : PyLong_FromLong(n); break; case TYPE_INT64: @@ -773,6 +832,10 @@ r_object(RFILE *p) case TYPE_STRING: n = r_long(p); + if (PyErr_Occurred()) { + retval = NULL; + break; + } if (n < 0 || n > INT_MAX) { PyErr_SetString(PyExc_ValueError, "bad marshal data (string size out of range)"); retval = NULL; @@ -798,6 +861,10 @@ r_object(RFILE *p) char *buffer; n = r_long(p); + if (PyErr_Occurred()) { + retval = NULL; + break; + } if (n < 0 || n > INT_MAX) { PyErr_SetString(PyExc_ValueError, "bad marshal data (unicode size out of range)"); retval = NULL; @@ -823,6 +890,10 @@ r_object(RFILE *p) case TYPE_TUPLE: n = r_long(p); + if (PyErr_Occurred()) { + retval = NULL; + break; + } if (n < 0 || n > INT_MAX) { PyErr_SetString(PyExc_ValueError, "bad marshal data (tuple size out of range)"); retval = NULL; @@ -850,6 +921,10 @@ r_object(RFILE *p) case TYPE_LIST: n = r_long(p); + if (PyErr_Occurred()) { + retval = NULL; + break; + } if (n < 0 || n > INT_MAX) { PyErr_SetString(PyExc_ValueError, "bad marshal data (list size out of range)"); retval = NULL; @@ -902,6 +977,10 @@ r_object(RFILE *p) case TYPE_SET: case TYPE_FROZENSET: n = r_long(p); + if (PyErr_Occurred()) { + retval = NULL; + break; + } if (n < 0 || n > INT_MAX) { PyErr_SetString(PyExc_ValueError, "bad marshal data (set size out of range)"); retval = NULL; @@ -955,10 +1034,20 @@ r_object(RFILE *p) /* XXX ignore long->int overflows for now */ argcount = (int)r_long(p); + if (PyErr_Occurred()) + goto code_error; kwonlyargcount = (int)r_long(p); + if (PyErr_Occurred()) + goto code_error; nlocals = (int)r_long(p); + if (PyErr_Occurred()) + goto code_error; stacksize = (int)r_long(p); + if (PyErr_Occurred()) + goto code_error; flags = (int)r_long(p); + if (PyErr_Occurred()) + goto code_error; code = r_object(p); if (code == NULL) goto code_error; @@ -1040,6 +1129,7 @@ PyMarshal_ReadShortFromFile(FILE *fp) { RFILE rf; assert(fp); + rf.readable = NULL; rf.fp = fp; rf.strings = NULL; rf.end = rf.ptr = NULL; @@ -1051,6 +1141,7 @@ PyMarshal_ReadLongFromFile(FILE *fp) { RFILE rf; rf.fp = fp; + rf.readable = NULL; rf.strings = NULL; rf.ptr = rf.end = NULL; return r_long(&rf); @@ -1112,6 +1203,7 @@ PyMarshal_ReadObjectFromFile(FILE *fp) RFILE rf; PyObject *result; rf.fp = fp; + rf.readable = NULL; rf.strings = PyList_New(0); rf.depth = 0; rf.ptr = rf.end = NULL; @@ -1126,6 +1218,7 @@ PyMarshal_ReadObjectFromString(char *str, Py_ssize_t len) RFILE rf; PyObject *result; rf.fp = NULL; + rf.readable = NULL; rf.ptr = str; rf.end = str + len; rf.strings = PyList_New(0); @@ -1142,6 +1235,7 @@ PyMarshal_WriteObjectToString(PyObject *x, int version) PyObject *res = NULL; wf.fp = NULL; + wf.readable = NULL; wf.str = PyBytes_FromStringAndSize((char *)NULL, 50); if (wf.str == NULL) return NULL; @@ -1219,33 +1313,33 @@ The version argument indicates the data format that dump should use."); static PyObject * marshal_load(PyObject *self, PyObject *f) { - /* XXX Quick hack -- need to do this differently */ PyObject *data, *result; RFILE rf; - data = PyObject_CallMethod(f, "read", ""); + char *p; + int n; + + /* + * Make a call to the read method, but read zero bytes. + * This is to ensure that the object passed in at least + * has a read method which returns bytes. + */ + data = PyObject_CallMethod(f, "read", "i", 0); if (data == NULL) return NULL; - rf.fp = NULL; - if (PyBytes_Check(data)) { - rf.ptr = PyBytes_AS_STRING(data); - rf.end = rf.ptr + PyBytes_GET_SIZE(data); - } - else if (PyBytes_Check(data)) { - rf.ptr = PyBytes_AS_STRING(data); - rf.end = rf.ptr + PyBytes_GET_SIZE(data); - } - else { + if (!PyBytes_Check(data)) { PyErr_Format(PyExc_TypeError, - "f.read() returned neither string " - "nor bytes but %.100s", + "f.read() returned not bytes but %.100s", data->ob_type->tp_name); - Py_DECREF(data); - return NULL; + result = NULL; + } + else { + rf.strings = PyList_New(0); + rf.depth = 0; + rf.fp = NULL; + rf.readable = f; + result = read_object(&rf); + Py_DECREF(rf.strings); } - rf.strings = PyList_New(0); - rf.depth = 0; - result = read_object(&rf); - Py_DECREF(rf.strings); Py_DECREF(data); return result; } @@ -1296,6 +1390,7 @@ marshal_loads(PyObject *self, PyObject *args) s = p.buf; n = p.len; rf.fp = NULL; + rf.readable = NULL; rf.ptr = s; rf.end = s + n; rf.strings = PyList_New(0); -- cgit v1.2.1 From bbda62711e0ebdf0c76422eb67c47eea36ca805c Mon Sep 17 00:00:00 2001 From: Vinay Sajip Date: Sat, 2 Jul 2011 17:21:37 +0100 Subject: Removed some unused local variables. --- Python/marshal.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'Python') diff --git a/Python/marshal.c b/Python/marshal.c index 396e05c638..76d5690438 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -1315,8 +1315,6 @@ marshal_load(PyObject *self, PyObject *f) { PyObject *data, *result; RFILE rf; - char *p; - int n; /* * Make a call to the read method, but read zero bytes. -- cgit v1.2.1 From 5bff1f1aa091e22e4b8598f4a4ca95f5296eca39 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 20 Jun 2011 21:40:19 -0500 Subject: fix indentation --- Python/ast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index 2ee2186198..6269c649d0 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -2283,7 +2283,7 @@ alias_for_import_name(struct compiling *c, const node *n, int store) loop: switch (TYPE(n)) { - case import_as_name: { + case import_as_name: { node *name_node = CHILD(n, 0); str = NULL; name = NEW_IDENTIFIER(name_node); -- cgit v1.2.1 From cf1391cc1af779295a0547ab74e4c6925596c3b1 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 20 Jun 2011 22:09:13 -0500 Subject: fix indentation --- Python/symtable.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'Python') diff --git a/Python/symtable.c b/Python/symtable.c index 15ba6b5e2f..5eff364439 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1568,12 +1568,12 @@ symtable_visit_alias(struct symtable *st, alias_ty a) } else { if (st->st_cur->ste_type != ModuleBlock) { - int lineno = st->st_cur->ste_lineno; - int col_offset = st->st_cur->ste_col_offset; - PyErr_SetString(PyExc_SyntaxError, IMPORT_STAR_WARNING); - PyErr_SyntaxLocationEx(st->st_filename, lineno, col_offset); - Py_DECREF(store_name); - return 0; + int lineno = st->st_cur->ste_lineno; + int col_offset = st->st_cur->ste_col_offset; + PyErr_SetString(PyExc_SyntaxError, IMPORT_STAR_WARNING); + PyErr_SyntaxLocationEx(st->st_filename, lineno, col_offset); + Py_DECREF(store_name); + return 0; } st->st_cur->ste_unoptimized |= OPT_IMPORT_STAR; Py_DECREF(store_name); -- cgit v1.2.1 From e960b4e7aaebd483ad420e895eded15c7857597f Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 3 Jul 2011 13:44:00 -0500 Subject: restore a generator's caller's exception state both on yield and (last) return This prevents generator exception state from leaking into the caller. Closes #12475. --- Python/ceval.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 705ed415a9..c0f2874a8f 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1881,10 +1881,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) retval = POP(); f->f_stacktop = stack_pointer; why = WHY_YIELD; - /* Put aside the current exception state and restore - that of the calling frame. This only serves when - "yield" is used inside an except handler. */ - SWAP_EXC_STATE(); goto fast_yield; TARGET(POP_EXCEPT) @@ -3021,6 +3017,11 @@ fast_block_end: retval = NULL; fast_yield: + if (co->co_flags & CO_GENERATOR && (why == WHY_YIELD || why == WHY_RETURN)) + /* Put aside the current exception state and restore that of the + calling frame. */ + SWAP_EXC_STATE(); + if (tstate->use_tracing) { if (tstate->c_tracefunc) { if (why == WHY_RETURN || why == WHY_YIELD) { -- cgit v1.2.1 From 0c48a3fed9e2b969c3d67adb4c4501917ffafa45 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 3 Jul 2011 16:25:11 -0500 Subject: never retain a generator's caller's exception state on the generator after a yield/return This requires some trickery to properly save the exception state if the generator creates its own exception state. --- Python/ceval.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index c0f2874a8f..5c3bb832cd 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1145,6 +1145,23 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) f->f_exc_traceback = tmp; \ } +#define RESTORE_AND_CLEAR_EXC_STATE() \ + { \ + PyObject *type, *value, *tb; \ + type = tstate->exc_type; \ + value = tstate->exc_value; \ + tb = tstate->exc_traceback; \ + tstate->exc_type = f->f_exc_type; \ + tstate->exc_value = f->f_exc_value; \ + tstate->exc_traceback = f->f_exc_traceback; \ + f->f_exc_type = NULL; \ + f->f_exc_value = NULL; \ + f->f_exc_traceback = NULL; \ + Py_XDECREF(type); \ + Py_XDECREF(value); \ + Py_XDECREF(tb); \ + } + /* Start of code */ if (f == NULL) @@ -3017,10 +3034,25 @@ fast_block_end: retval = NULL; fast_yield: - if (co->co_flags & CO_GENERATOR && (why == WHY_YIELD || why == WHY_RETURN)) - /* Put aside the current exception state and restore that of the - calling frame. */ - SWAP_EXC_STATE(); + if (co->co_flags & CO_GENERATOR && (why == WHY_YIELD || why == WHY_RETURN)) { + /* The purpose of this block is to put aside the generator's exception + state and restore that of the calling frame. If the current + exception state is from the caller, we clear the exception values + on the generator frame, so they are not swapped back in latter. The + origin of the current exception state is determined by checking for + except handler blocks, which we must be in iff a new exception + state came into existence in this frame. (An uncaught exception + would have why == WHY_EXCEPTION, and we wouldn't be here). */ + int i; + for (i = 0; i < f->f_iblock; i++) + if (f->f_blockstack[i].b_type == EXCEPT_HANDLER) + break; + if (i == f->f_iblock) + /* We did not create this exception. */ + RESTORE_AND_CLEAR_EXC_STATE() + else + SWAP_EXC_STATE() + } if (tstate->use_tracing) { if (tstate->c_tracefunc) { -- cgit v1.2.1 From 6b6d717c8df56a714f9a5551483316396d99a05e Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 4 Jul 2011 02:43:09 +0200 Subject: Issue #12467: warnings: fix a race condition if a warning is emitted at shutdown, if globals()['__file__'] is None. --- Python/_warnings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/_warnings.c b/Python/_warnings.c index a797887b9c..07fd683e53 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -496,7 +496,7 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, /* Setup filename. */ *filename = PyDict_GetItemString(globals, "__file__"); - if (*filename != NULL) { + if (*filename != NULL && PyUnicode_Check(*filename)) { Py_ssize_t len = PyUnicode_GetSize(*filename); Py_UNICODE *unicode = PyUnicode_AS_UNICODE(*filename); -- cgit v1.2.1 From 3c35d9ef13c5347aea78e1c62da4ad31d8f3c7d7 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 3 Jul 2011 22:18:34 -0500 Subject: plug refleak --- Python/_warnings.c | 1 + 1 file changed, 1 insertion(+) (limited to 'Python') diff --git a/Python/_warnings.c b/Python/_warnings.c index 07fd683e53..99f6071a0c 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -517,6 +517,7 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, } else { const char *module_str = _PyUnicode_AsString(*module); + Py_XDECREF(*filename); if (module_str == NULL) goto handle_error; if (strcmp(module_str, "__main__") == 0) { -- cgit v1.2.1 From ab14a9f18cd58ac72951f120fbe936fe78ffdc96 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 4 Jul 2011 22:27:16 -0500 Subject: start out this branch always with filename NULL --- Python/_warnings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/_warnings.c b/Python/_warnings.c index 99f6071a0c..615a2d3217 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -517,7 +517,7 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, } else { const char *module_str = _PyUnicode_AsString(*module); - Py_XDECREF(*filename); + *filename = NULL; if (module_str == NULL) goto handle_error; if (strcmp(module_str, "__main__") == 0) { -- cgit v1.2.1 From 30f469fa882ebb308927e30c862774a229e19bc9 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 15 Jul 2011 14:09:26 -0500 Subject: catch nasty exception classes with __new__ that doesn't return a exception (closes #11627) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch from Andreas Stührk. --- Python/ceval.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 5c3bb832cd..f0ea7c90dc 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3413,6 +3413,13 @@ do_raise(PyObject *exc, PyObject *cause) value = PyObject_CallObject(exc, NULL); if (value == NULL) goto raise_error; + if (!PyExceptionInstance_Check(value)) { + PyErr_Format(PyExc_TypeError, + "calling %R should have returned an instance of " + "BaseException, not %R", + type, Py_TYPE(value)); + goto raise_error; + } } else if (PyExceptionInstance_Check(exc)) { value = exc; -- cgit v1.2.1 From 7848f2a4be885c95dc41d479377d063547e46fb3 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 22 Jul 2011 10:50:23 -0500 Subject: type check AST strings and identifiers This is related to a21829180423 as well as #12609 and #12610. --- Python/Python-ast.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 2c09f96f0e..43dcf6a508 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -2,7 +2,7 @@ /* - __version__ 82163. + __version__ . This module must be committed separately after each AST grammar change; The __version__ number is set to the revision number of the commit @@ -600,8 +600,25 @@ static int obj2ast_object(PyObject* obj, PyObject** out, PyArena* arena) return 0; } -#define obj2ast_identifier obj2ast_object -#define obj2ast_string obj2ast_object +static int obj2ast_stringlike(PyObject* obj, PyObject** out, PyArena* arena, + const char *name) +{ + if (!PyUnicode_CheckExact(name)) { + PyErr_Format(PyExc_TypeError, "AST %s must be of type str", name); + return 1; + } + return obj2ast_object(obj, out, arena); +} + +static int obj2ast_identifier(PyObject* obj, PyObject** out, PyArena* arena) +{ + return obj2ast_stringlike(obj, out, arena, "identifier"); +} + +static int obj2ast_string(PyObject* obj, PyObject** out, PyArena* arena) +{ + return obj2ast_stringlike(obj, out, arena, "string"); +} static int obj2ast_int(PyObject* obj, int* out, PyArena* arena) { @@ -6739,7 +6756,7 @@ PyInit__ast(void) NULL; if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0) return NULL; - if (PyModule_AddStringConstant(m, "__version__", "82163") < 0) + if (PyModule_AddStringConstant(m, "__version__", "") < 0) return NULL; if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return NULL; -- cgit v1.2.1 From 4fb9e4f2e1910fdbe8932559a9b807ded60e53d1 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 22 Jul 2011 10:39:12 -0500 Subject: hardcode the old svn __version__ --- Python/Python-ast.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 43dcf6a508..ea6a2ecf52 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -2,7 +2,7 @@ /* - __version__ . + __version__ 82163. This module must be committed separately after each AST grammar change; The __version__ number is set to the revision number of the commit @@ -6756,7 +6756,7 @@ PyInit__ast(void) NULL; if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0) return NULL; - if (PyModule_AddStringConstant(m, "__version__", "") < 0) + if (PyModule_AddStringConstant(m, "__version__", "82163") < 0) return NULL; if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return NULL; -- cgit v1.2.1 From f6639c9c8201eee770b6d1a62feb772a9dbbb593 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 22 Jul 2011 11:09:07 -0500 Subject: None is ok for identifiers but not strings --- Python/Python-ast.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index ea6a2ecf52..8ba06ff39a 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -600,24 +600,22 @@ static int obj2ast_object(PyObject* obj, PyObject** out, PyArena* arena) return 0; } -static int obj2ast_stringlike(PyObject* obj, PyObject** out, PyArena* arena, - const char *name) +static int obj2ast_identifier(PyObject* obj, PyObject** out, PyArena* arena) { - if (!PyUnicode_CheckExact(name)) { - PyErr_Format(PyExc_TypeError, "AST %s must be of type str", name); + if (!PyUnicode_CheckExact(obj) && obj != Py_None) { + PyErr_SetString(PyExc_TypeError, "AST identifier must be of type str"); return 1; } return obj2ast_object(obj, out, arena); } -static int obj2ast_identifier(PyObject* obj, PyObject** out, PyArena* arena) -{ - return obj2ast_stringlike(obj, out, arena, "identifier"); -} - static int obj2ast_string(PyObject* obj, PyObject** out, PyArena* arena) { - return obj2ast_stringlike(obj, out, arena, "string"); + if (!PyUnicode_CheckExact(obj)) { + PyErr_SetString(PyExc_TypeError, "AST string must be of type str"); + return 1; + } + return obj2ast_object(obj, out, arena); } static int obj2ast_int(PyObject* obj, int* out, PyArena* arena) -- cgit v1.2.1 From 13cbc8430c90032f5351afd156632336c59e9674 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sun, 24 Jul 2011 02:27:04 +0200 Subject: Issue #1813: Fix codec lookup under Turkish locales. --- Python/codecs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/codecs.c b/Python/codecs.c index 45d99291f1..1a3e45774c 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -69,7 +69,7 @@ PyObject *normalizestring(const char *string) if (ch == ' ') ch = '-'; else - ch = tolower(Py_CHARMASK(ch)); + ch = Py_TOLOWER(Py_CHARMASK(ch)); p[i] = ch; } p[i] = '\0'; -- cgit v1.2.1 From 3fae00c30017be44348adf4a008d2a4fb3975f80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Araujo?= Date: Tue, 26 Jul 2011 17:23:57 +0200 Subject: Fix style in code added by edba722f3b02 --- Python/marshal.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/marshal.c b/Python/marshal.c index 76d5690438..094f732382 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -57,7 +57,7 @@ typedef struct { int error; /* see WFERR_* values */ int depth; /* If fp == NULL, the following are valid: */ - PyObject * readable; /* Stream-like object being read from */ + PyObject *readable; /* Stream-like object being read from */ PyObject *str; char *ptr; char *end; @@ -470,7 +470,7 @@ typedef WFILE RFILE; /* Same struct with different invariants */ static int r_string(char *s, int n, RFILE *p) { - char * ptr; + char *ptr; int read, left; if (!p->readable) { @@ -569,7 +569,7 @@ r_long(RFILE *p) static PyObject * r_long64(RFILE *p) { - PyObject * result = NULL; + PyObject *result = NULL; long lo4 = r_long(p); long hi4 = r_long(p); -- cgit v1.2.1 From 8517c9174252c7e4419fdb11636680a6b90eaf37 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 31 Aug 2011 22:13:03 -0400 Subject: accept bytes for the AST 'string' type This is a temporary kludge and all is well in 3.3. --- Python/Python-ast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 8ba06ff39a..89c07cd602 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -611,7 +611,7 @@ static int obj2ast_identifier(PyObject* obj, PyObject** out, PyArena* arena) static int obj2ast_string(PyObject* obj, PyObject** out, PyArena* arena) { - if (!PyUnicode_CheckExact(obj)) { + if (!PyUnicode_CheckExact(obj) && !PyBytes_CheckExact(obj)) { PyErr_SetString(PyExc_TypeError, "AST string must be of type str"); return 1; } -- cgit v1.2.1 From 1f12608a8ad62d40c2a108be0e6a9b024b4219dd Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 2 Sep 2011 00:11:43 +0200 Subject: Remove unused variable if Python is build without threads --- Python/import.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 23752eeb72..93defeff7f 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2349,7 +2349,9 @@ PyImport_ImportModuleNoBlock(const char *name) { PyObject *result; PyObject *modules; +#ifdef WITH_THREAD long me; +#endif /* Try to get the module from sys.modules[name] */ modules = PyImport_GetModuleDict(); -- cgit v1.2.1 From dee6b0855426e3641a7119a592f2ff1db69baef3 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 15 Sep 2011 19:28:05 +0200 Subject: Fix the import machinery if there is an error on sys.path or sys.meta_path find_module() now raises a RuntimeError, instead of ImportError, on an error on sys.path or sys.meta_path because load_package() and import_submodule() returns None and clear the exception if a ImportError occurred. --- Python/import.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 93defeff7f..ee905eb286 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1591,7 +1591,7 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, meta_path = PySys_GetObject("meta_path"); if (meta_path == NULL || !PyList_Check(meta_path)) { - PyErr_SetString(PyExc_ImportError, + PyErr_SetString(PyExc_RuntimeError, "sys.meta_path must be a list of " "import hooks"); return NULL; @@ -1641,14 +1641,14 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, } if (path == NULL || !PyList_Check(path)) { - PyErr_SetString(PyExc_ImportError, + PyErr_SetString(PyExc_RuntimeError, "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, + PyErr_SetString(PyExc_RuntimeError, "sys.path_hooks must be a list of " "import hooks"); return NULL; @@ -1656,7 +1656,7 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, path_importer_cache = PySys_GetObject("path_importer_cache"); if (path_importer_cache == NULL || !PyDict_Check(path_importer_cache)) { - PyErr_SetString(PyExc_ImportError, + PyErr_SetString(PyExc_RuntimeError, "sys.path_importer_cache must be a dict"); return NULL; } -- cgit v1.2.1 From 98292273d840a24a366ab585f907da593c0726e0 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Tue, 20 Sep 2011 14:45:44 -0400 Subject: - Issue #13021: Missing decref on an error path. Thanks to Suman Saha for finding the bug and providing a patch. --- Python/pythonrun.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 084db12f63..bea7fe1544 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1241,8 +1241,10 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, Py_DECREF(f); return -1; } - if (PyDict_SetItemString(d, "__cached__", Py_None) < 0) + if (PyDict_SetItemString(d, "__cached__", Py_None) < 0) { + Py_DECREF(f); return -1; + } set_file_name = 1; Py_DECREF(f); } -- cgit v1.2.1 From bec278946d5b2e0b0b2ea661cbfdaf86fc996f9c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 23 Sep 2011 18:54:40 +0200 Subject: Issue #7732: Don't open a directory as a file anymore while importing a module. Ignore the direcotry if its name matchs the module name (e.g. "__init__.py") and raise a ImportError instead. --- Python/import.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index ee905eb286..2adcb04674 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1763,6 +1763,7 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, saved_namelen = namelen; #endif /* PYOS_OS2 */ for (fdp = _PyImport_Filetab; fdp->suffix != NULL; fdp++) { + struct stat statbuf; #if defined(PYOS_OS2) && defined(HAVE_DYNAMIC_LOADING) /* OS/2 limits DLLs to 8 character names (w/o extension) @@ -1791,10 +1792,16 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, 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 (stat(buf, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) + /* it's a directory */ + fp = NULL; + else + fp = fopen(buf, filemode); if (fp != NULL) { if (case_ok(buf, len, namelen, name)) break; -- cgit v1.2.1 From 8a6fce2f337b3c623ee3091878fdd06bccc5b3fe Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Sun, 23 Oct 2011 22:04:16 +1000 Subject: Issue 1294232: Fix errors in metaclass calculation affecting some cases of metaclass inheritance. Patch by Daniel Urban. --- Python/bltinmodule.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 6258167b60..9c50b88da8 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -35,9 +35,10 @@ int Py_HasFileSystemDefaultEncoding = 1; static PyObject * builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) { - PyObject *func, *name, *bases, *mkw, *meta, *prep, *ns, *cell; + PyObject *func, *name, *bases, *mkw, *meta, *winner, *prep, *ns, *cell; PyObject *cls = NULL; Py_ssize_t nargs, nbases; + int isclass; assert(args != NULL); if (!PyTuple_Check(args)) { @@ -82,17 +83,42 @@ builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) Py_DECREF(bases); return NULL; } + /* metaclass is explicitly given, check if it's indeed a class */ + isclass = PyType_Check(meta); } } if (meta == NULL) { - if (PyTuple_GET_SIZE(bases) == 0) + /* if there are no bases, use type: */ + if (PyTuple_GET_SIZE(bases) == 0) { meta = (PyObject *) (&PyType_Type); + } + /* else get the type of the first base */ else { PyObject *base0 = PyTuple_GET_ITEM(bases, 0); meta = (PyObject *) (base0->ob_type); } Py_INCREF(meta); + isclass = 1; /* meta is really a class */ + } + if (isclass) { + /* meta is really a class, so check for a more derived + metaclass, or possible metaclass conflicts: */ + winner = (PyObject *)_PyType_CalculateMetaclass((PyTypeObject *)meta, + bases); + if (winner == NULL) { + Py_DECREF(meta); + Py_XDECREF(mkw); + Py_DECREF(bases); + return NULL; + } + if (winner != meta) { + Py_DECREF(meta); + meta = winner; + Py_INCREF(meta); + } } + /* else: meta is not a class, so we cannot do the metaclass + calculation, so we will use the explicitly given object as it is */ prep = PyObject_GetAttrString(meta, "__prepare__"); if (prep == NULL) { if (PyErr_ExceptionMatches(PyExc_AttributeError)) { -- cgit v1.2.1 From 5b390c263f2bd08db8698db5b64fc3b4b9cc6688 Mon Sep 17 00:00:00 2001 From: Florent Xicluna Date: Fri, 28 Oct 2011 15:00:50 +0200 Subject: Remove unused variable. --- Python/bltinmodule.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 9c50b88da8..d05232c34a 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -37,7 +37,7 @@ builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *func, *name, *bases, *mkw, *meta, *winner, *prep, *ns, *cell; PyObject *cls = NULL; - Py_ssize_t nargs, nbases; + Py_ssize_t nargs; int isclass; assert(args != NULL); @@ -62,7 +62,6 @@ builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) bases = PyTuple_GetSlice(args, 2, nargs); if (bases == NULL) return NULL; - nbases = nargs - 2; if (kwds == NULL) { meta = NULL; -- cgit v1.2.1 From b056c79a98400c94f499fdf3ea36f3d7dbe55d8f Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sun, 30 Oct 2011 19:13:55 +0100 Subject: Issue #10363: Deallocate global locks in Py_Finalize(). --- Python/import.c | 25 +++++++++++++++---------- Python/pystate.c | 6 ++++++ 2 files changed, 21 insertions(+), 10 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 2adcb04674..1dbe544e73 100644 --- a/Python/import.c +++ b/Python/import.c @@ -252,16 +252,6 @@ _PyImportHooks_Init(void) 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. */ @@ -374,6 +364,21 @@ imp_release_lock(PyObject *self, PyObject *noargs) return Py_None; } +void +_PyImport_Fini(void) +{ + Py_XDECREF(extensions); + extensions = NULL; + PyMem_DEL(_PyImport_Filetab); + _PyImport_Filetab = NULL; +#ifdef WITH_THREAD + if (import_lock != NULL) { + PyThread_free_lock(import_lock); + import_lock = NULL; + } +#endif +} + static void imp_modules_reloading_clear(void) { diff --git a/Python/pystate.c b/Python/pystate.c index b347c41c54..40699af499 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -150,6 +150,12 @@ PyInterpreterState_Delete(PyInterpreterState *interp) *p = interp->next; HEAD_UNLOCK(); free(interp); +#ifdef WITH_THREAD + if (interp_head == NULL && head_mutex != NULL) { + PyThread_free_lock(head_mutex); + head_mutex = NULL; + } +#endif } -- cgit v1.2.1 From 8187210d58766c4e3981e3f677d690ebc9cefaa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Araujo?= Date: Thu, 3 Nov 2011 03:38:44 +0100 Subject: Add signatures to the docstring of functions added to imp by PEP 3147 --- Python/import.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 1dbe544e73..e721498aaa 100644 --- a/Python/import.c +++ b/Python/import.c @@ -3534,7 +3534,8 @@ imp_cache_from_source(PyObject *self, PyObject *args, PyObject *kws) } PyDoc_STRVAR(doc_cache_from_source, -"Given the path to a .py file, return the path to its .pyc/.pyo file.\n\ +"cache_from_source(path, [debug_override]) -> path\n\ +Given the path to a .py file, return the path to its .pyc/.pyo file.\n\ \n\ The .py file does not need to exist; this simply returns the path to the\n\ .pyc/.pyo file calculated as if the .py file were imported. The extension\n\ @@ -3569,7 +3570,8 @@ imp_source_from_cache(PyObject *self, PyObject *args, PyObject *kws) } PyDoc_STRVAR(doc_source_from_cache, -"Given the path to a .pyc./.pyo file, return the path to its .py file.\n\ +"source_from_cache(path) -> path\n\ +Given the path to a .pyc./.pyo file, return the path to its .py file.\n\ \n\ The .pyc/.pyo file does not need to exist; this simply returns the path to\n\ the .py file calculated to correspond to the .pyc/.pyo file. If path\n\ -- cgit v1.2.1 From f96517e3cf52217f5da99c66a12d610273956090 Mon Sep 17 00:00:00 2001 From: Amaury Forgeot d'Arc Date: Fri, 4 Nov 2011 22:17:45 +0100 Subject: Issue #13343: Fix a SystemError when a lambda expression uses a global variable in the default value of a keyword-only argument: (lambda *, arg=GLOBAL_NAME: None) --- Python/symtable.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Python') diff --git a/Python/symtable.c b/Python/symtable.c index 5eff364439..1ec51f708c 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1334,6 +1334,9 @@ symtable_visit_expr(struct symtable *st, expr_ty e) return 0; if (e->v.Lambda.args->defaults) VISIT_SEQ(st, expr, e->v.Lambda.args->defaults); + if (e->v.Lambda.args->kw_defaults) + VISIT_KWONLYDEFAULTS(st, + e->v.Lambda.args->kw_defaults); if (!symtable_enter_block(st, lambda, FunctionBlock, (void *)e, e->lineno, e->col_offset)) -- cgit v1.2.1 From a9cd7934e455af79a767dc8a67e6ca83a6c5e90f Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sun, 6 Nov 2011 00:34:26 +0100 Subject: Issue #13342: input() used to ignore sys.stdin's and sys.stdout's unicode error handler in interactive mode (when calling into PyOS_Readline()). --- Python/bltinmodule.c | 83 ++++++++++++++++++++++++++-------------------------- 1 file changed, 41 insertions(+), 42 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index d05232c34a..9e37d21b5d 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1640,76 +1640,65 @@ builtin_input(PyObject *self, PyObject *args) /* If we're interactive, use (GNU) readline */ if (tty) { - PyObject *po; + PyObject *po = NULL; char *prompt; - char *s; - PyObject *stdin_encoding; - char *stdin_encoding_str; + char *s = NULL; + PyObject *stdin_encoding = NULL, *stdin_errors = NULL; + PyObject *stdout_encoding = NULL, *stdout_errors = NULL; + char *stdin_encoding_str, *stdin_errors_str; PyObject *result; size_t len; stdin_encoding = PyObject_GetAttrString(fin, "encoding"); - if (!stdin_encoding) + stdin_errors = PyObject_GetAttrString(fin, "errors"); + if (!stdin_encoding || !stdin_errors) /* stdin is a text stream, so it must have an encoding. */ - return NULL; + goto _readline_errors; stdin_encoding_str = _PyUnicode_AsString(stdin_encoding); - if (stdin_encoding_str == NULL) { - Py_DECREF(stdin_encoding); - return NULL; - } + stdin_errors_str = _PyUnicode_AsString(stdin_errors); + if (!stdin_encoding_str || !stdin_errors_str) + goto _readline_errors; tmp = PyObject_CallMethod(fout, "flush", ""); if (tmp == NULL) PyErr_Clear(); else Py_DECREF(tmp); if (promptarg != NULL) { + /* We have a prompt, encode it as stdout would */ + char *stdout_encoding_str, *stdout_errors_str; PyObject *stringpo; - PyObject *stdout_encoding; - char *stdout_encoding_str; stdout_encoding = PyObject_GetAttrString(fout, "encoding"); - if (stdout_encoding == NULL) { - Py_DECREF(stdin_encoding); - return NULL; - } + stdout_errors = PyObject_GetAttrString(fout, "errors"); + if (!stdout_encoding || !stdout_errors) + goto _readline_errors; stdout_encoding_str = _PyUnicode_AsString(stdout_encoding); - if (stdout_encoding_str == NULL) { - Py_DECREF(stdin_encoding); - Py_DECREF(stdout_encoding); - return NULL; - } + stdout_errors_str = _PyUnicode_AsString(stdout_errors); + if (!stdout_encoding_str || !stdout_errors_str) + goto _readline_errors; stringpo = PyObject_Str(promptarg); - if (stringpo == NULL) { - Py_DECREF(stdin_encoding); - Py_DECREF(stdout_encoding); - return NULL; - } + if (stringpo == NULL) + goto _readline_errors; po = PyUnicode_AsEncodedString(stringpo, - stdout_encoding_str, NULL); - Py_DECREF(stdout_encoding); - Py_DECREF(stringpo); - if (po == NULL) { - Py_DECREF(stdin_encoding); - return NULL; - } + stdout_encoding_str, stdout_errors_str); + Py_CLEAR(stdout_encoding); + Py_CLEAR(stdout_errors); + Py_CLEAR(stringpo); + if (po == NULL) + goto _readline_errors; prompt = PyBytes_AsString(po); - if (prompt == NULL) { - Py_DECREF(stdin_encoding); - Py_DECREF(po); - return NULL; - } + if (prompt == NULL) + goto _readline_errors; } else { po = NULL; prompt = ""; } s = PyOS_Readline(stdin, stdout, prompt); - Py_XDECREF(po); if (s == NULL) { if (!PyErr_Occurred()) PyErr_SetNone(PyExc_KeyboardInterrupt); - Py_DECREF(stdin_encoding); - return NULL; + goto _readline_errors; } len = strlen(s); @@ -1727,12 +1716,22 @@ builtin_input(PyObject *self, PyObject *args) len--; /* strip trailing '\n' */ if (len != 0 && s[len-1] == '\r') len--; /* strip trailing '\r' */ - result = PyUnicode_Decode(s, len, stdin_encoding_str, NULL); + result = PyUnicode_Decode(s, len, stdin_encoding_str, + stdin_errors_str); } } Py_DECREF(stdin_encoding); + Py_DECREF(stdin_errors); + Py_XDECREF(po); PyMem_FREE(s); return result; + _readline_errors: + Py_XDECREF(stdin_encoding); + Py_XDECREF(stdout_encoding); + Py_XDECREF(stdin_errors); + Py_XDECREF(stdout_errors); + Py_XDECREF(po); + return NULL; } /* Fallback if we're not interactive */ -- cgit v1.2.1 From 5ce62495bbd169404c52625f3aced451ea4200c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Fran=C3=A7ois=20Natali?= Date: Tue, 22 Nov 2011 19:49:51 +0100 Subject: Issue #13156: _PyGILState_Reinit(): Re-associate the auto thread state with the TLS key only if the thread that called fork() had an associated auto thread state (this might not be the case for example for a thread created outside of Python calling into a subinterpreter). --- Python/pystate.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/pystate.c b/Python/pystate.c index 40699af499..3b4c6a2e65 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -592,9 +592,9 @@ _PyGILState_Fini(void) autoInterpreterState = NULL; } -/* Reset the TLS key - called by PyOS_AfterFork. +/* Reset the TLS key - called by PyOS_AfterFork(). * This should not be necessary, but some - buggy - pthread implementations - * don't flush TLS on fork, see issue #10517. + * don't reset TLS upon fork(), see issue #10517. */ void _PyGILState_Reinit(void) @@ -604,8 +604,9 @@ _PyGILState_Reinit(void) if ((autoTLSkey = PyThread_create_key()) == -1) Py_FatalError("Could not allocate TLS entry"); - /* re-associate the current thread state with the new key */ - if (PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0) + /* If the thread had an associated auto thread state, reassociate it with + * the new key. */ + if (tstate && PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0) Py_FatalError("Couldn't create autoTLSkey mapping"); } -- cgit v1.2.1 From 025a9d35b90a5c26c427462569e336c7c46c8388 Mon Sep 17 00:00:00 2001 From: Amaury Forgeot d'Arc Date: Tue, 22 Nov 2011 21:52:30 +0100 Subject: Issue #13436: commit regenerated Python-ast.c --- Python/Python-ast.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 89c07cd602..a276b6cf21 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -622,11 +622,7 @@ static int obj2ast_int(PyObject* obj, int* out, PyArena* arena) { int i; if (!PyLong_Check(obj)) { - PyObject *s = PyObject_Repr(obj); - if (s == NULL) return 1; - PyErr_Format(PyExc_ValueError, "invalid integer value: %.400s", - PyBytes_AS_STRING(s)); - Py_DECREF(s); + PyErr_Format(PyExc_ValueError, "invalid integer value: %R", obj); return 1; } -- cgit v1.2.1 From 28e55082c3f1c64621bf2a3de150e51a94815d3d Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sat, 26 Nov 2011 21:59:36 +0100 Subject: Issue #13444: When stdout has been closed explicitly, we should not attempt to flush it at shutdown and print an error. This also adds a test for issue #5319, whose resolution introduced the issue. --- Python/pythonrun.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index bea7fe1544..fe92d303c8 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -332,6 +332,22 @@ extern void dump_counts(FILE*); /* Flush stdout and stderr */ +static int +file_is_closed(PyObject *fobj) +{ + int r; + PyObject *tmp = PyObject_GetAttrString(fobj, "closed"); + if (tmp == NULL) { + PyErr_Clear(); + return 0; + } + r = PyObject_IsTrue(tmp); + Py_DECREF(tmp); + if (r < 0) + PyErr_Clear(); + return r > 0; +} + static void flush_std_files(void) { @@ -339,7 +355,7 @@ flush_std_files(void) PyObject *ferr = PySys_GetObject("stderr"); PyObject *tmp; - if (fout != NULL && fout != Py_None) { + if (fout != NULL && fout != Py_None && !file_is_closed(fout)) { tmp = PyObject_CallMethod(fout, "flush", ""); if (tmp == NULL) PyErr_WriteUnraisable(fout); @@ -347,7 +363,7 @@ flush_std_files(void) Py_DECREF(tmp); } - if (ferr != NULL && ferr != Py_None) { + if (ferr != NULL && ferr != Py_None && !file_is_closed(ferr)) { tmp = PyObject_CallMethod(ferr, "flush", ""); if (tmp == NULL) PyErr_Clear(); -- cgit v1.2.1 From 07ee349b41ca8f94aadaf39be3ec9ca5aca692f9 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Mon, 28 Nov 2011 19:08:36 +0100 Subject: Issue #7111: Python can now be run without a stdin, stdout or stderr stream. It was already the case with Python 2. However, the corresponding sys module entries are now set to None (instead of an unusable file object). --- Python/pythonrun.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index fe92d303c8..4b0ac139a2 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -892,6 +892,19 @@ error: return NULL; } +static int +is_valid_fd(int fd) +{ + int dummy_fd; + if (fd < 0 || !_PyVerify_fd(fd)) + return 0; + dummy_fd = dup(fd); + if (dummy_fd < 0) + return 0; + close(dummy_fd); + return 1; +} + /* Initialize sys.stdin, stdout, stderr and builtins.open */ static int initstdio(void) @@ -951,13 +964,9 @@ initstdio(void) * and fileno() may point to an invalid file descriptor. For example * GUI apps don't have valid standard streams by default. */ - if (fd < 0) { -#ifdef MS_WINDOWS + if (!is_valid_fd(fd)) { std = Py_None; Py_INCREF(std); -#else - goto error; -#endif } else { std = create_stdio(iomod, fd, 0, "", encoding, errors); @@ -970,13 +979,9 @@ initstdio(void) /* Set sys.stdout */ fd = fileno(stdout); - if (fd < 0) { -#ifdef MS_WINDOWS + if (!is_valid_fd(fd)) { std = Py_None; Py_INCREF(std); -#else - goto error; -#endif } else { std = create_stdio(iomod, fd, 1, "", encoding, errors); @@ -990,13 +995,9 @@ initstdio(void) #if 1 /* Disable this if you have trouble debugging bootstrap stuff */ /* Set sys.stderr, replaces the preliminary stderr */ fd = fileno(stderr); - if (fd < 0) { -#ifdef MS_WINDOWS + if (!is_valid_fd(fd)) { std = Py_None; Py_INCREF(std); -#else - goto error; -#endif } else { std = create_stdio(iomod, fd, 1, "", encoding, "backslashreplace"); -- cgit v1.2.1 From 88b12a304360b0b7dbf1e3b24b35956a2e71b5b4 Mon Sep 17 00:00:00 2001 From: Florent Xicluna Date: Fri, 9 Dec 2011 23:41:21 +0100 Subject: Remove obsolete py3k comment. --- Python/_warnings.c | 1 - 1 file changed, 1 deletion(-) (limited to 'Python') diff --git a/Python/_warnings.c b/Python/_warnings.c index 615a2d3217..c12db44d19 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -888,7 +888,6 @@ create_filter(PyObject *category, const char *action) static PyObject * init_filters(void) { - /* Don't silence DeprecationWarning if -3 was used. */ PyObject *filters = PyList_New(5); unsigned int pos = 0; /* Post-incremented in each use. */ unsigned int x; -- cgit v1.2.1 From 062d7a2220a83fed2ba92bb16c73a02e8bfa579b Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 31 Dec 2011 22:42:26 -0600 Subject: add another year to glorious PSF IP --- Python/getcopyright.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/getcopyright.c b/Python/getcopyright.c index 1388f2c98c..d1e2578747 100644 --- a/Python/getcopyright.c +++ b/Python/getcopyright.c @@ -4,7 +4,7 @@ static char cprt[] = "\ -Copyright (c) 2001-2011 Python Software Foundation.\n\ +Copyright (c) 2001-2012 Python Software Foundation.\n\ All Rights Reserved.\n\ \n\ Copyright (c) 2000 BeOpen.com.\n\ -- cgit v1.2.1 From 0f97cff6c6f527fcb4c4b7acad30cfb54b146934 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 3 Jan 2012 16:47:22 -0600 Subject: fix formatting --- Python/bltinmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 9e37d21b5d..11b7624e41 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -494,7 +494,7 @@ builtin_format(PyObject *self, PyObject *args) PyObject *format_spec = NULL; if (!PyArg_ParseTuple(args, "O|U:format", &value, &format_spec)) - return NULL; + return NULL; return PyObject_Format(value, format_spec); } -- cgit v1.2.1 From cc1c307aab7a507e0ecdb85e5bb19ecf9c6b4926 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 11 Jan 2012 21:00:16 -0500 Subject: fold into one if statement --- Python/bltinmodule.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 11b7624e41..e2ff0ba1c5 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1502,10 +1502,8 @@ builtin_print(PyObject *self, PyObject *args, PyObject *kwds) PyObject *sep = NULL, *end = NULL, *file = NULL; int i, err; - if (dummy_args == NULL) { - if (!(dummy_args = PyTuple_New(0))) + if (dummy_args == NULL && !(dummy_args = PyTuple_New(0))) return NULL; - } if (!PyArg_ParseTupleAndKeywords(dummy_args, kwds, "|OOO:print", kwlist, &sep, &end, &file)) return NULL; -- cgit v1.2.1 From 597d29ba18e75d535b7d8e033dc6ebb5c8b78396 Mon Sep 17 00:00:00 2001 From: Meador Inge Date: Sun, 15 Jan 2012 19:15:36 -0600 Subject: Issue #13629: Renumber the tokens in token.h to match the _PyParser_TokenNames indexes. --- Python/graminit.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'Python') diff --git a/Python/graminit.c b/Python/graminit.c index a8af5833a9..cabc4d63b3 100644 --- a/Python/graminit.c +++ b/Python/graminit.c @@ -1978,7 +1978,7 @@ static label labels[168] = { {258, 0}, {327, 0}, {259, 0}, - {50, 0}, + {49, 0}, {289, 0}, {7, 0}, {330, 0}, @@ -1990,7 +1990,7 @@ static label labels[168] = { {1, "def"}, {1, 0}, {263, 0}, - {51, 0}, + {50, 0}, {302, 0}, {11, 0}, {301, 0}, @@ -1999,7 +1999,7 @@ static label labels[168] = { {22, 0}, {12, 0}, {16, 0}, - {36, 0}, + {35, 0}, {266, 0}, {267, 0}, {270, 0}, @@ -2016,6 +2016,7 @@ static label labels[168] = { {273, 0}, {336, 0}, {311, 0}, + {36, 0}, {37, 0}, {38, 0}, {39, 0}, @@ -2026,8 +2027,7 @@ static label labels[168] = { {44, 0}, {45, 0}, {46, 0}, - {47, 0}, - {49, 0}, + {48, 0}, {1, "del"}, {326, 0}, {1, "pass"}, @@ -2046,7 +2046,7 @@ static label labels[168] = { {1, "import"}, {288, 0}, {23, 0}, - {52, 0}, + {51, 0}, {287, 0}, {285, 0}, {1, "as"}, @@ -2088,38 +2088,38 @@ static label labels[168] = { {310, 0}, {20, 0}, {21, 0}, - {28, 0}, - {31, 0}, + {27, 0}, {30, 0}, {29, 0}, - {29, 0}, + {28, 0}, + {28, 0}, {1, "is"}, {313, 0}, {18, 0}, {314, 0}, - {33, 0}, + {32, 0}, {315, 0}, {19, 0}, {316, 0}, + {33, 0}, {34, 0}, - {35, 0}, {317, 0}, {14, 0}, {15, 0}, {318, 0}, {17, 0}, {24, 0}, - {48, 0}, - {32, 0}, + {47, 0}, + {31, 0}, {319, 0}, {320, 0}, {322, 0}, {321, 0}, {9, 0}, {10, 0}, - {26, 0}, + {25, 0}, {328, 0}, - {27, 0}, + {26, 0}, {2, 0}, {3, 0}, {1, "None"}, -- cgit v1.2.1 From d7a1b71b34af52ecbc6f22544f0bc4eb1e7198f7 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Wed, 18 Jan 2012 15:14:46 +0100 Subject: Fix a memory leak when initializing the standard I/O streams. --- Python/pythonrun.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 4b0ac139a2..ec69bcba8f 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1012,7 +1012,8 @@ initstdio(void) const char * encoding; encoding = _PyUnicode_AsString(encoding_attr); if (encoding != NULL) { - _PyCodec_Lookup(encoding); + PyObject *codec_info = _PyCodec_Lookup(encoding); + Py_XDECREF(codec_info); } Py_DECREF(encoding_attr); } -- cgit v1.2.1 From 2f34ae1ecebc102c516807f72eb166914b765f9a Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Wed, 18 Jan 2012 20:16:09 +0100 Subject: Fix the builtin module initialization code to store the init function for future reinitialization. --- Python/import.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index e721498aaa..ee3f9b0682 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2169,6 +2169,7 @@ init_builtin(char *name) for (p = PyImport_Inittab; p->name != NULL; p++) { PyObject *mod; + PyModuleDef *def; if (strcmp(name, p->name) == 0) { if (p->initfunc == NULL) { PyErr_Format(PyExc_ImportError, @@ -2181,6 +2182,9 @@ init_builtin(char *name) mod = (*p->initfunc)(); if (mod == 0) return -1; + /* Remember pointer to module init function. */ + def = PyModule_GetDef(mod); + def->m_base.m_init = p->initfunc; if (_PyImport_FixupBuiltin(mod, name) < 0) return -1; /* FixupExtension has put the module into sys.modules, -- cgit v1.2.1 From cc0f5885dbb9226e53e449d6623df53fa75b66ce Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Wed, 18 Jan 2012 22:30:21 +0100 Subject: Issue #13722: Avoid silencing ImportErrors when initializing the codecs registry. --- Python/codecs.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'Python') diff --git a/Python/codecs.c b/Python/codecs.c index 1a3e45774c..c7f4a9cbc1 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -1067,15 +1067,6 @@ static int _PyCodecRegistry_Init(void) mod = PyImport_ImportModuleNoBlock("encodings"); 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); -- cgit v1.2.1 From c22bd520b185e4236e23fccbd3dba85e9159a233 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Tue, 24 Jan 2012 17:44:06 +0100 Subject: Issue #11235: Fix OverflowError when trying to import a source file whose modification time doesn't fit in a 32-bit timestamp. --- Python/import.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index ee3f9b0682..40b8d0a558 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1304,14 +1304,11 @@ load_source_module(char *name, char *pathname, FILE *fp) } #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. + in 4 bytes. Since the code only does an equality comparison, + ordering is not important and we can safely ignore the higher bits + (collisions are extremely unlikely). */ - if (st.st_mtime >> 32) { - PyErr_SetString(PyExc_OverflowError, - "modification time overflows a 4 byte field"); - return NULL; - } + st.st_mtime &= 0xFFFFFFFF; #endif cpathname = make_compiled_pathname( pathname, buf, (size_t)MAXPATHLEN + 1, !Py_OptimizeFlag); -- cgit v1.2.1 From 20a97f0f16c2e7920dda85c828079ec7108ca959 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Wed, 25 Jan 2012 18:01:45 +0100 Subject: Port import fixes from 2.7. --- Python/import.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 40b8d0a558..beda7f97d2 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1226,9 +1226,9 @@ write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat) (void) unlink(cpathname); return; } - /* Now write the true mtime */ + /* Now write the true mtime (as a 32-bit field) */ fseek(fp, 4L, 0); - assert(mtime < LONG_MAX); + assert(mtime <= 0xFFFFFFFF); PyMarshal_WriteLongToFile((long)mtime, fp, Py_MARSHAL_VERSION); fflush(fp); fclose(fp); @@ -1302,14 +1302,14 @@ load_source_module(char *name, char *pathname, FILE *fp) pathname); return NULL; } -#if SIZEOF_TIME_T > 4 - /* Python's .pyc timestamp handling presumes that the timestamp fits - in 4 bytes. Since the code only does an equality comparison, - ordering is not important and we can safely ignore the higher bits - (collisions are extremely unlikely). - */ - st.st_mtime &= 0xFFFFFFFF; -#endif + if (sizeof st.st_mtime > 4) { + /* Python's .pyc timestamp handling presumes that the timestamp fits + in 4 bytes. Since the code only does an equality comparison, + ordering is not important and we can safely ignore the higher bits + (collisions are extremely unlikely). + */ + st.st_mtime &= 0xFFFFFFFF; + } cpathname = make_compiled_pathname( pathname, buf, (size_t)MAXPATHLEN + 1, !Py_OptimizeFlag); if (cpathname != NULL && -- cgit v1.2.1 From 32695f2bd9c14551026e4ef35226ce233bad1234 Mon Sep 17 00:00:00 2001 From: Petri Lehtinen Date: Thu, 2 Feb 2012 20:59:48 +0200 Subject: Document absoluteness of sys.executable Closes #13402. --- Python/sysmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 73dc0dd592..8a659c5e46 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1263,7 +1263,7 @@ version_info -- version information as a named 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\ +executable -- absolute path of the executable binary of the Python interpreter\n\ prefix -- prefix used to find the Python library\n\ exec_prefix -- prefix used to find the machine-specific Python library\n\ float_repr_style -- string indicating the style of repr() output for floats\n\ -- cgit v1.2.1