summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/whatsnew/3.13.rst7
-rw-r--r--Include/Python.h1
-rw-r--r--Include/pyport.h38
-rw-r--r--Misc/NEWS.d/next/C API/2023-09-02-22-35-55.gh-issue-108765.4TOdBT.rst5
-rw-r--r--Modules/_localemodule.c34
-rw-r--r--Modules/_sre/sre.c38
-rw-r--r--Modules/_struct.c1
-rw-r--r--Modules/_tkinter.c13
-rw-r--r--Modules/_zoneinfo.c7
-rw-r--r--Modules/pyexpat.c1
-rw-r--r--Modules/timemodule.c7
-rw-r--r--Objects/abstract.c3
-rw-r--r--Objects/floatobject.c3
-rw-r--r--Objects/longobject.c6
-rw-r--r--Objects/typeobject.c2
-rw-r--r--Python/bltinmodule.c1
-rw-r--r--Python/ceval.c4
-rw-r--r--Python/codecs.c1
-rw-r--r--Python/dynload_win.c9
-rw-r--r--Python/errors.c1
-rw-r--r--Python/getargs.c4
-rw-r--r--Python/mystrtoul.c14
22 files changed, 86 insertions, 114 deletions
diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst
index 1c91a1d..5d8ecbb 100644
--- a/Doc/whatsnew/3.13.rst
+++ b/Doc/whatsnew/3.13.rst
@@ -942,6 +942,13 @@ Porting to Python 3.13
and ``setitimer()`` functions.
(Contributed by Victor Stinner in :gh:`108765`.)
+* ``Python.h`` no longer includes the ``<ctype.h>`` standard header file. If
+ needed, it should now be included explicitly. For example, it provides
+ ``isalpha()`` and ``tolower()`` functions which are locale dependent. Python
+ provides locale independent functions, like :c:func:`!Py_ISALPHA` and
+ :c:func:`!Py_TOLOWER`.
+ (Contributed by Victor Stinner in :gh:`108765`.)
+
Deprecated
----------
diff --git a/Include/Python.h b/Include/Python.h
index 4cc72bb..8b28200 100644
--- a/Include/Python.h
+++ b/Include/Python.h
@@ -17,7 +17,6 @@
// Include standard header files
#include <assert.h> // assert()
-#include <ctype.h> // tolower()
#include <inttypes.h> // uintptr_t
#include <limits.h> // INT_MAX
#include <math.h> // HUGE_VAL
diff --git a/Include/pyport.h b/Include/pyport.h
index c4168d1..4d9b9c0 100644
--- a/Include/pyport.h
+++ b/Include/pyport.h
@@ -392,44 +392,6 @@ extern "C" {
# define Py_NO_INLINE
#endif
-/* On 4.4BSD-descendants, ctype functions serves the whole range of
- * wchar_t character set rather than single byte code points only.
- * This characteristic can break some operations of string object
- * including str.upper() and str.split() on UTF-8 locales. This
- * workaround was provided by Tim Robbins of FreeBSD project.
- */
-
-#if defined(__APPLE__)
-# define _PY_PORT_CTYPE_UTF8_ISSUE
-#endif
-
-#ifdef _PY_PORT_CTYPE_UTF8_ISSUE
-#ifndef __cplusplus
- /* The workaround below is unsafe in C++ because
- * the <locale> defines these symbols as real functions,
- * with a slightly different signature.
- * See issue #10910
- */
-#include <ctype.h>
-#include <wctype.h>
-#undef isalnum
-#define isalnum(c) iswalnum(btowc(c))
-#undef isalpha
-#define isalpha(c) iswalpha(btowc(c))
-#undef islower
-#define islower(c) iswlower(btowc(c))
-#undef isspace
-#define isspace(c) iswspace(btowc(c))
-#undef isupper
-#define isupper(c) iswupper(btowc(c))
-#undef tolower
-#define tolower(c) towlower(btowc(c))
-#undef toupper
-#define toupper(c) towupper(btowc(c))
-#endif
-#endif
-
-
/* Declarations for symbol visibility.
PyAPI_FUNC(type): Declares a public Python API function and return type
diff --git a/Misc/NEWS.d/next/C API/2023-09-02-22-35-55.gh-issue-108765.4TOdBT.rst b/Misc/NEWS.d/next/C API/2023-09-02-22-35-55.gh-issue-108765.4TOdBT.rst
new file mode 100644
index 0000000..c13b6d9
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2023-09-02-22-35-55.gh-issue-108765.4TOdBT.rst
@@ -0,0 +1,5 @@
+``Python.h`` no longer includes the ``<ctype.h>`` standard header file. If
+needed, it should now be included explicitly. For example, it provides
+``isalpha()`` and ``tolower()`` functions which are locale dependent. Python
+provides locale independent functions, like :c:func:`!Py_ISALPHA` and
+:c:func:`!Py_TOLOWER`. Patch by Victor Stinner.
diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c
index 1847a48..fe8e4c5 100644
--- a/Modules/_localemodule.c
+++ b/Modules/_localemodule.c
@@ -10,35 +10,25 @@ This software comes with no warranty. Use at your own risk.
******************************************************************/
#include "Python.h"
-#include "pycore_fileutils.h"
-#include "pycore_pymem.h" // _PyMem_Strdup
-
-#include <stdio.h>
-#include <locale.h>
-#include <string.h>
-#include <ctype.h>
+#include "pycore_fileutils.h" // _Py_GetLocaleconvNumeric()
+#include "pycore_pymem.h" // _PyMem_Strdup()
+#include <locale.h> // setlocale()
+#include <string.h> // strlen()
#ifdef HAVE_ERRNO_H
-#include <errno.h>
+# include <errno.h> // errno
#endif
-
#ifdef HAVE_LANGINFO_H
-#include <langinfo.h>
+# include <langinfo.h> // nl_langinfo()
#endif
-
#ifdef HAVE_LIBINTL_H
-#include <libintl.h>
-#endif
-
-#ifdef HAVE_WCHAR_H
-#include <wchar.h>
+# include <libintl.h>
#endif
-
-#if defined(MS_WINDOWS)
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
+#ifdef MS_WINDOWS
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# include <windows.h>
#endif
PyDoc_STRVAR(locale__doc__, "Support for POSIX locales.");
diff --git a/Modules/_sre/sre.c b/Modules/_sre/sre.c
index 3872c36..07da5da 100644
--- a/Modules/_sre/sre.c
+++ b/Modules/_sre/sre.c
@@ -43,12 +43,40 @@ static const char copyright[] =
#include "pycore_long.h" // _PyLong_GetZero()
#include "pycore_moduleobject.h" // _PyModule_GetState()
+#include "sre.h" // SRE_CODE
-#include "sre.h"
+#include <ctype.h> // tolower(), toupper(), isalnum()
#define SRE_CODE_BITS (8 * sizeof(SRE_CODE))
-#include <ctype.h>
+// On macOS, use the wide character ctype API using btowc()
+#if defined(__APPLE__)
+# define USE_CTYPE_WINT_T
+#endif
+
+static int sre_isalnum(unsigned int ch) {
+#ifdef USE_CTYPE_WINT_T
+ return (unsigned int)iswalnum(btowc((int)ch));
+#else
+ return (unsigned int)isalnum((int)ch);
+#endif
+}
+
+static unsigned int sre_tolower(unsigned int ch) {
+#ifdef USE_CTYPE_WINT_T
+ return (unsigned int)towlower(btowc((int)ch));
+#else
+ return (unsigned int)tolower((int)ch);
+#endif
+}
+
+static unsigned int sre_toupper(unsigned int ch) {
+#ifdef USE_CTYPE_WINT_T
+ return (unsigned int)towupper(btowc((int)ch));
+#else
+ return (unsigned int)toupper((int)ch);
+#endif
+}
/* Defining this one controls tracing:
* 0 -- disabled
@@ -114,17 +142,17 @@ static unsigned int sre_lower_ascii(unsigned int ch)
/* locale-specific character predicates */
/* !(c & ~N) == (c < N+1) for any unsigned c, this avoids
* warnings when c's type supports only numbers < N+1 */
-#define SRE_LOC_IS_ALNUM(ch) (!((ch) & ~255) ? isalnum((ch)) : 0)
+#define SRE_LOC_IS_ALNUM(ch) (!((ch) & ~255) ? sre_isalnum((ch)) : 0)
#define SRE_LOC_IS_WORD(ch) (SRE_LOC_IS_ALNUM((ch)) || (ch) == '_')
static unsigned int sre_lower_locale(unsigned int ch)
{
- return ((ch) < 256 ? (unsigned int)tolower((ch)) : ch);
+ return ((ch) < 256 ? (unsigned int)sre_tolower((ch)) : ch);
}
static unsigned int sre_upper_locale(unsigned int ch)
{
- return ((ch) < 256 ? (unsigned int)toupper((ch)) : ch);
+ return ((ch) < 256 ? (unsigned int)sre_toupper((ch)) : ch);
}
/* unicode-specific character predicates */
diff --git a/Modules/_struct.c b/Modules/_struct.c
index be4c23a..1f8f9c4 100644
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -12,7 +12,6 @@
#include "pycore_long.h" // _PyLong_AsByteArray()
#include "pycore_moduleobject.h" // _PyModule_GetState()
-#include <ctype.h>
#include <stddef.h> // offsetof()
/*[clinic input]
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
index 663b411..f9a1864 100644
--- a/Modules/_tkinter.c
+++ b/Modules/_tkinter.c
@@ -26,15 +26,14 @@ Copyright (C) 1994 Steen Lumholt.
#endif
#include "Python.h"
-#include <ctype.h>
#ifdef MS_WINDOWS
# include "pycore_fileutils.h" // _Py_stat()
#endif
-#include "pycore_long.h"
+#include "pycore_long.h" // _PyLong_IsNegative()
#ifdef MS_WINDOWS
-#include <windows.h>
+# include <windows.h>
#endif
#define CHECK_SIZE(size, elemsize) \
@@ -46,11 +45,11 @@ Copyright (C) 1994 Steen Lumholt.
#define TCL_THREADS
#ifdef TK_FRAMEWORK
-#include <Tcl/tcl.h>
-#include <Tk/tk.h>
+# include <Tcl/tcl.h>
+# include <Tk/tk.h>
#else
-#include <tcl.h>
-#include <tk.h>
+# include <tcl.h>
+# include <tk.h>
#endif
#include "tkinter.h"
diff --git a/Modules/_zoneinfo.c b/Modules/_zoneinfo.c
index 3f7b285..eb4e522 100644
--- a/Modules/_zoneinfo.c
+++ b/Modules/_zoneinfo.c
@@ -6,11 +6,10 @@
#include "pycore_long.h" // _PyLong_GetOne()
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
-#include <ctype.h>
-#include <stddef.h>
-#include <stdint.h>
+#include "datetime.h" // PyDateTime_TZInfo
-#include "datetime.h"
+#include <stddef.h> // offsetof()
+#include <stdint.h>
#include "clinic/_zoneinfo.c.h"
/*[clinic input]
diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c
index 52dd06c..bd24523 100644
--- a/Modules/pyexpat.c
+++ b/Modules/pyexpat.c
@@ -7,7 +7,6 @@
#include "pycore_pyhash.h" // _Py_HashSecret
#include "pycore_traceback.h" // _PyTraceback_Add()
-#include <ctype.h>
#include <stddef.h> // offsetof()
#include "expat.h"
#include "pyexpat.h"
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
index 4e55da7..a2b6652 100644
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -6,22 +6,21 @@
#include "pycore_namespace.h" // _PyNamespace_New()
#include "pycore_runtime.h" // _Py_ID()
-#include <ctype.h>
#include <time.h> // clock()
#ifdef HAVE_SYS_TIMES_H
-# include <sys/times.h>
+# include <sys/times.h> // times()
#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#if defined(HAVE_SYS_RESOURCE_H)
-# include <sys/resource.h>
+# include <sys/resource.h> // getrusage(RUSAGE_SELF)
#endif
#ifdef QUICKWIN
# include <io.h>
#endif
#if defined(HAVE_PTHREAD_H)
-# include <pthread.h>
+# include <pthread.h> // pthread_getcpuclockid()
#endif
#if defined(_AIX)
# include <sys/thread.h>
diff --git a/Objects/abstract.c b/Objects/abstract.c
index c113364..6713926 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -9,9 +9,8 @@
#include "pycore_pyerrors.h" // _PyErr_Occurred()
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_unionobject.h" // _PyUnion_Check()
-#include <ctype.h>
-#include <stddef.h> // offsetof()
+#include <stddef.h> // offsetof()
/* Shorthands to return certain errors */
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index 1c5078b..776c709 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -16,8 +16,7 @@
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "pycore_structseq.h" // _PyStructSequence_FiniBuiltin()
-#include <ctype.h>
-#include <float.h>
+#include <float.h> // DBL_MAX
#include <stdlib.h> // strtol()
/*[clinic input]
diff --git a/Objects/longobject.c b/Objects/longobject.c
index d20ef41..e73de74 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -10,10 +10,8 @@
#include "pycore_runtime.h" // _PY_NSMALLPOSINTS
#include "pycore_structseq.h" // _PyStructSequence_FiniBuiltin()
-#include <ctype.h>
-#include <float.h>
-#include <stddef.h>
-#include <stdlib.h> // abs()
+#include <float.h> // DBL_MANT_DIG
+#include <stddef.h> // offsetof
#include "clinic/longobject.c.h"
/*[clinic input]
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 67e059c..84c5050 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -19,8 +19,6 @@
#include "pycore_weakref.h" // _PyWeakref_GET_REF()
#include "opcode.h" // MAKE_CELL
-
-#include <ctype.h>
#include <stddef.h> // ptrdiff_t
/*[clinic input]
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 971067e..8e234e0 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -1,7 +1,6 @@
/* Built-in functions */
#include "Python.h"
-#include <ctype.h>
#include "pycore_ast.h" // _PyAST_Validate()
#include "pycore_call.h" // _PyObject_CallNoArgs()
#include "pycore_ceval.h" // _PyEval_Vector()
diff --git a/Python/ceval.c b/Python/ceval.c
index a22852e..6f90d8e 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -35,9 +35,7 @@
#include "pydtrace.h"
#include "setobject.h"
-
-#include <ctype.h>
-#include <stdbool.h>
+#include <stdbool.h> // bool
#ifdef Py_DEBUG
/* For debugging the interpreter: */
diff --git a/Python/codecs.c b/Python/codecs.c
index 87ae896..b79bf55 100644
--- a/Python/codecs.c
+++ b/Python/codecs.c
@@ -14,7 +14,6 @@ Copyright (c) Corporation for National Research Initiatives.
#include "pycore_pyerrors.h" // _PyErr_FormatNote()
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "pycore_ucnhash.h" // _PyUnicode_Name_CAPI
-#include <ctype.h>
const char *Py_hexdigits = "0123456789abcdef";
diff --git a/Python/dynload_win.c b/Python/dynload_win.c
index acab05e..f69995b 100644
--- a/Python/dynload_win.c
+++ b/Python/dynload_win.c
@@ -5,13 +5,8 @@
#include "pycore_fileutils.h" // _Py_add_relfile()
#include "pycore_pystate.h" // _PyInterpreterState_GET()
-#ifdef HAVE_DIRECT_H
-#include <direct.h>
-#endif
-#include <ctype.h>
-
-#include "importdl.h"
-#include "patchlevel.h"
+#include "importdl.h" // dl_funcptr
+#include "patchlevel.h" // PY_MAJOR_VERSION
#include <windows.h>
#ifdef _DEBUG
diff --git a/Python/errors.c b/Python/errors.c
index fb5b3ff..f670b78 100644
--- a/Python/errors.c
+++ b/Python/errors.c
@@ -10,7 +10,6 @@
#include "pycore_sysmodule.h" // _PySys_Audit()
#include "pycore_traceback.h" // _PyTraceBack_FromFrame()
-#include <ctype.h>
#ifdef MS_WINDOWS
# include <windows.h>
# include <winbase.h>
diff --git a/Python/getargs.c b/Python/getargs.c
index fdc1444..cbfe561 100644
--- a/Python/getargs.c
+++ b/Python/getargs.c
@@ -7,10 +7,6 @@
#include "pycore_pylifecycle.h" // _PyArg_Fini
#include "pycore_tuple.h" // _PyTuple_ITEMS()
-#include <ctype.h>
-#include <float.h>
-
-
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/Python/mystrtoul.c b/Python/mystrtoul.c
index e6fe154..fcd3e27 100644
--- a/Python/mystrtoul.c
+++ b/Python/mystrtoul.c
@@ -1,16 +1,22 @@
+// strtol() and strtoul(), renamed to avoid conflicts.
+//
+// API:
+//
+// - PyOS_strtol(): convert string to C long integer.
+// - PyOS_strtoul(): convert string to C unsigned long integer.
+
#include "Python.h"
#include "pycore_long.h" // _PyLong_DigitValue
#if defined(__sgi) && !defined(_SGI_MP_SOURCE)
-#define _SGI_MP_SOURCE
+# define _SGI_MP_SOURCE
#endif
/* strtol and strtoul, renamed to avoid conflicts */
-#include <ctype.h>
#ifdef HAVE_ERRNO_H
-#include <errno.h>
+# include <errno.h> // errno
#endif
/* Static overflow check values for bases 2 through 36.
@@ -75,7 +81,7 @@ static const int digitlimit[] = {
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"
+# error "Need table for SIZEOF_LONG"
#endif
/*