testRunPlatform: macos
pool:
- vmImage: xcode9-macos10.13
+ vmImage: macos-10.14
steps:
- template: ./macos-steps.yml
variables:
testRunTitle: '$(build.sourceBranchName)-linux'
testRunPlatform: linux
- openssl_version: 1.1.1c
+ openssl_version: 1.1.1d
steps:
- template: ./posix-steps.yml
variables:
testRunTitle: '$(Build.SourceBranchName)-linux-coverage'
testRunPlatform: linux-coverage
- openssl_version: 1.1.1c
+ openssl_version: 1.1.1d
steps:
- template: ./posix-steps.yml
- script: make buildbottest TESTOPTS="-j4 -uall,-cpu --junit-xml=$(build.binariesDirectory)/test-results.xml"
displayName: 'Tests'
+ continueOnError: true
+ timeoutInMinutes: 30
- task: PublishTestResults@2
displayName: 'Publish Test Results'
testRunPlatform: macos
pool:
- vmImage: xcode9-macos10.13
+ vmImage: macos-10.14
steps:
- template: ./macos-steps.yml
variables:
testRunTitle: '$(system.pullRequest.TargetBranch)-linux'
testRunPlatform: linux
- openssl_version: 1.1.1c
+ openssl_version: 1.1.1d
steps:
- template: ./posix-steps.yml
variables:
testRunTitle: '$(Build.SourceBranchName)-linux-coverage'
testRunPlatform: linux-coverage
- openssl_version: 1.1.1c
+ openssl_version: 1.1.1d
steps:
- template: ./posix-steps.yml
SOURCES =
DISTVERSION = $(shell $(PYTHON) tools/extensions/patchlevel.py)
-ALLSPHINXOPTS = -b $(BUILDER) -d build/doctrees -D latex_elements.papersize=$(PAPER) \
+# Internal variables.
+PAPEROPT_a4 = -D latex_elements.papersize=a4paper
+PAPEROPT_letter = -D latex_elements.papersize=letterpaper
+
+ALLSPHINXOPTS = -b $(BUILDER) -d build/doctrees $(PAPEROPT_$(PAPER)) \
$(SPHINXOPTS) . build/$(BUILDER) $(SOURCES)
.PHONY: help build html htmlhelp latex text changes linkcheck \
Article which goes into some detail about how to create a useful bug report.
This describes what kind of information is useful and why it is useful.
- `Bug Writing Guidelines <https://developer.mozilla.org/en-US/docs/Mozilla/QA/Bug_writing_guidelines>`_
+ `Bug Report Writing Guidelines <https://developer.mozilla.org/en-US/docs/Mozilla/QA/Bug_writing_guidelines>`_
Information about writing a good bug report. Some of this is specific to the
Mozilla project, but describes general good practices.
improving the memory management efficiency.
-.. c:function:: void PyObject_Del(PyObject *op)
+.. c:function:: void PyObject_Del(void *op)
Releases memory allocated to an object using :c:func:`PyObject_New` or
:c:func:`PyObject_NewVar`. This is normally called from the
a standard n-dimensional C-array. Otherwise, the consumer must access an
n-dimensional array as follows:
- ``ptr = (char *)buf + indices[0] * strides[0] + ... + indices[n-1] * strides[n-1]``
- ``item = *((typeof(item) *)ptr);``
+.. code-block:: c
+
+ ptr = (char *)buf + indices[0] * strides[0] + ... + indices[n-1] * strides[n-1];
+ item = *((typeof(item) *)ptr);
As noted above, :c:member:`~Py_buffer.buf` can point to any location within
(*order* is ``'A'``). Return ``0`` otherwise. This function always succeeds.
+.. c:function:: void* PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices)
+
+ Get the memory area pointed to by the *indices* inside the given *view*.
+ *indices* must point to an array of ``view->ndim`` indices.
+
+
+.. c:function:: int PyBuffer_FromContiguous(Py_buffer *view, void *buf, Py_ssize_t len, char fort)
+
+ Copy contiguous *len* bytes from *buf* to *view*.
+ *fort* can be ``'C'`` or ``'F'`` (for C-style or Fortran-style ordering).
+ ``0`` is returned on success, ``-1`` on error.
+
+
.. c:function:: int PyBuffer_ToContiguous(void *buf, Py_buffer *src, Py_ssize_t len, char order)
Copy *len* bytes from *src* to its contiguous representation in *buf*.
- *order* can be ``'C'`` or ``'F'`` (for C-style or Fortran-style ordering).
- ``0`` is returned on success, ``-1`` on error.
+ *order* can be ``'C'`` or ``'F'`` or ``'A'`` (for C-style or Fortran-style
+ ordering or either one). ``0`` is returned on success, ``-1`` on error.
This function fails if *len* != *src->len*.
:mod:`warnings` module and the :option:`-W` option in the command line
documentation. There is no C API for warning control.
-.. c:function:: PyObject* PyErr_SetImportErrorSubclass(PyObject *msg, PyObject *name, PyObject *path)
+.. c:function:: PyObject* PyErr_SetImportErrorSubclass(PyObject *exception, PyObject *msg, PyObject *name, PyObject *path)
Much like :c:func:`PyErr_SetImportError` but this function allows for
specifying a subclass of :exc:`ImportError` to raise.
with ``_Py`` are for internal use by the Python implementation and should not be
used by extension writers. Structure member names do not have a reserved prefix.
-**Important:** user code should never define names that begin with ``Py`` or
-``_Py``. This confuses the reader, and jeopardizes the portability of the user
-code to future Python versions, which may define additional names beginning with
-one of these prefixes.
+.. note::
+
+ User code should never define names that begin with ``Py`` or ``_Py``. This
+ confuses the reader, and jeopardizes the portability of the user code to
+ future Python versions, which may define additional names beginning with one
+ of these prefixes.
The header files are typically installed with Python. On Unix, these are
located in the directories :file:`{prefix}/include/pythonversion/` and
:envvar:`prefix` include the platform specific headers from
:envvar:`exec_prefix`.
-C++ users should note that though the API is defined entirely using C, the
-header files do properly declare the entry points to be ``extern "C"``, so there
-is no need to do anything special to use the API from C++.
+C++ users should note that although the API is defined entirely using C, the
+header files properly declare the entry points to be ``extern "C"``. As a result,
+there is no need to do anything special to use the API from C++.
Useful macros
.. c:function:: PyObject* PyList_GetItem(PyObject *list, Py_ssize_t index)
Return the object at position *index* in the list pointed to by *list*. The
- position must be positive, indexing from the end of the list is not
- supported. If *index* is out of bounds, return *NULL* and set an
- :exc:`IndexError` exception.
+ position must be non-negative; indexing from the end of the list is not
+ supported. If *index* is out of bounds (<0 or >=len(list)),
+ return *NULL* and set an :exc:`IndexError` exception.
.. c:function:: PyObject* PyList_GET_ITEM(PyObject *list, Py_ssize_t i)
In this example, the memory request for the I/O buffer is handled by the C
library allocator. The Python memory manager is involved only in the allocation
-of the string object returned as a result.
+of the bytes object returned as a result.
In most situations, however, it is recommended to allocate memory from the
Python heap specifically because the latter is under control of the Python
Add an object to *module* as *name*. This is a convenience function which can
be used from the module's initialization function. This steals a reference to
- *value*. Return ``-1`` on error, ``0`` on success.
+ *value* on success. Return ``-1`` on error, ``0`` on success.
+
+ .. note::
+
+ Unlike other functions that steal references, ``PyModule_AddObject()`` only
+ decrements the reference count of *value* **on success**.
+
+ This means that its return value must be checked, and calling code must
+ :c:func:`Py_DECREF` *value* manually on error. Example usage::
+
+ Py_INCREF(spam);
+ if (PyModule_AddObject(module, "spam", spam) < 0) {
+ Py_DECREF(module);
+ Py_DECREF(spam);
+ return NULL;
+ }
.. c:function:: int PyModule_AddIntConstant(PyObject *module, const char *name, long value)
.. c:function:: PyObject* PySequence_Fast(PyObject *o, const char *m)
- Return the sequence or iterable *o* as a list, unless it is already a tuple or list, in
- which case *o* is returned. Use :c:func:`PySequence_Fast_GET_ITEM` to access
- the members of the result. Returns *NULL* on failure. If the object is not
- a sequence or iterable, raises :exc:`TypeError` with *m* as the message text.
+ Return the sequence or iterable *o* as an object usable by the other
+ ``PySequence_Fast*`` family of functions. If the object is not a sequence or
+ iterable, raises :exc:`TypeError` with *m* as the message text. Returns
+ *NULL* on failure.
+
+ The ``PySequence_Fast*`` functions are thus named because they assume
+ *o* is a :c:type:`PyTupleObject` or a :c:type:`PyListObject` and access
+ the data fields of *o* directly.
+
+ As a CPython implementation detail, if *o* is already a sequence or list, it
+ will be returned.
.. c:function:: Py_ssize_t PySequence_Fast_GET_SIZE(PyObject *o)
Returns the length of *o*, assuming that *o* was returned by
:c:func:`PySequence_Fast` and that *o* is not *NULL*. The size can also be
gotten by calling :c:func:`PySequence_Size` on *o*, but
- :c:func:`PySequence_Fast_GET_SIZE` is faster because it can assume *o* is a list
- or tuple.
+ :c:func:`PySequence_Fast_GET_SIZE` is faster because it can assume *o* is a
+ list or tuple.
.. c:function:: PyObject* PySequence_Fast_GET_ITEM(PyObject *o, Py_ssize_t i)
.. c:function:: PyObject* PySequence_ITEM(PyObject *o, Py_ssize_t i)
- Return the *i*\ th element of *o* or *NULL* on failure. Macro form of
+ Return the *i*\ th element of *o* or *NULL* on failure. Faster form of
:c:func:`PySequence_GetItem` but without checking that
:c:func:`PySequence_Check` on *o* is true and without adjustment for negative
indices.
needs_sphinx = "1.6.6"
# Ignore any .rst files in the venv/ directory.
-venvdir = os.getenv('VENVDIR', 'venv')
-exclude_patterns = [venvdir+'/*', 'README.rst']
+exclude_patterns = ['venv/*', 'README.rst']
+venvdir = os.getenv('VENVDIR')
+if venvdir is not None:
+ exclude_patterns.append(venvdir + '/*')
# Disable Docutils smartquotes for several translations
smartquotes_excludes = {
PyUnicode_AsWideChar:Py_ssize_t:::
PyUnicode_AsWideChar:PyObject*:*unicode:0:
PyUnicode_AsWideChar:wchar_t*:w::
-PyUnicode_AsWideChar:Pyssize_t:size::
+PyUnicode_AsWideChar:Py_ssize_t:size::
PyUnicode_AsWideCharString:wchar_t*:::
PyUnicode_AsWideCharString:PyObject*:unicode:0:
If you have a pure module distribution (only containing pure Python modules and
packages), the resulting installer will be version independent and have a name
-like :file:`foo-1.0.win32.exe`. These installers can even be created on Unix
-platforms or Mac OS X.
+like :file:`foo-1.0.win32.exe`. Note that creating ``wininst`` binary
+distributions in only supported on Windows systems.
If you have a non-pure distribution, the extensions can only be created on a
Windows platform, and will be Python version dependent. The installer filename
static PyObject *SpamError;
and initialize it in your module's initialization function (:c:func:`PyInit_spam`)
-with an exception object (leaving out the error checking for now)::
+with an exception object::
PyMODINIT_FUNC
PyInit_spam(void)
return NULL;
SpamError = PyErr_NewException("spam.error", NULL, NULL);
- Py_INCREF(SpamError);
- PyModule_AddObject(m, "error", SpamError);
+ Py_XINCREF(SpamError);
+ if (PyModule_AddObject(m, "error", SpamError) < 0) {
+ Py_XDECREF(SpamError);
+ Py_CLEAR(SpamError);
+ Py_DECREF(m);
+ return NULL;
+ }
+
return m;
}
/* Create a Capsule containing the API pointer array's address */
c_api_object = PyCapsule_New((void *)PySpam_API, "spam._C_API", NULL);
- if (c_api_object != NULL)
- PyModule_AddObject(m, "_C_API", c_api_object);
+ if (PyModule_AddObject(m, "_C_API", c_api_object) < 0) {
+ Py_XDECREF(c_api_object);
+ Py_DECREF(m);
+ return NULL;
+ }
+
return m;
}
to the appropriate default values, including :attr:`ob_type` that we initially
set to *NULL*. ::
- PyModule_AddObject(m, "Custom", (PyObject *) &CustomType);
+ Py_INCREF(&CustomType);
+ if (PyModule_AddObject(m, "Custom", (PyObject *) &CustomType) < 0) {
+ Py_DECREF(&CustomType);
+ Py_DECREF(m);
+ return NULL;
+ }
This adds the type to the module dictionary. This allows us to create
:class:`Custom` instances by calling the :class:`Custom` class:
return NULL;
Py_INCREF(&SubListType);
- PyModule_AddObject(m, "SubList", (PyObject *) &SubListType);
+ if (PyModule_AddObject(m, "SubList", (PyObject *) &SubListType) < 0) {
+ Py_DECREF(&SubListType);
+ Py_DECREF(m);
+ return NULL;
+ }
+
return m;
}
-----------------------------------------------
Generally speaking, it can't, because objects don't really have names.
-Essentially, assignment always binds a name to a value; The same is true of
+Essentially, assignment always binds a name to a value; the same is true of
``def`` and ``class`` statements, but in that case the value is a
callable. Consider the following code::
Fortran contiguous arrays, the first index varies the fastest.
coroutine
- Coroutines is a more generalized form of subroutines. Subroutines are
+ Coroutines are a more generalized form of subroutines. Subroutines are
entered at one point and exited at another point. Coroutines can be
entered, exited, and resumed at many different points. They can be
implemented with the :keyword:`async def` statement. See also
also :term:`immutable`.
named tuple
- Any tuple-like class whose indexable elements are also accessible using
- named attributes (for example, :func:`time.localtime` returns a
- tuple-like object where the *year* is accessible either with an
- index such as ``t[0]`` or with a named attribute like ``t.tm_year``).
-
- A named tuple can be a built-in type such as :class:`time.struct_time`,
- or it can be created with a regular class definition. A full featured
- named tuple can also be created with the factory function
- :func:`collections.namedtuple`. The latter approach automatically
- provides extra features such as a self-documenting representation like
- ``Employee(name='jones', title='programmer')``.
+ The term "named tuple" applies to any type or class that inherits from
+ tuple and whose indexable elements are also accessible using named
+ attributes. The type or class may have other features as well.
+
+ Several built-in types are named tuples, including the values returned
+ by :func:`time.localtime` and :func:`os.stat`. Another example is
+ :data:`sys.float_info`::
+
+ >>> sys.float_info[1] # indexed access
+ 1024
+ >>> sys.float_info.max_exp # named field access
+ 1024
+ >>> isinstance(sys.float_info, tuple) # kind of tuple
+ True
+
+ Some named tuples are built-in types (such as the above examples).
+ Alternatively, a named tuple can be created from a regular class
+ definition that inherits from :class:`tuple` and that defines named
+ fields. Such a class can be written by hand or it can be created with
+ the factory function :func:`collections.namedtuple`. The latter
+ technique also adds some extra methods that may not be found in
+ hand-written or built-in named tuples.
namespace
The place where a variable is stored. Namespaces are implemented as
an :term:`expression` or one of several constructs with a keyword, such
as :keyword:`if`, :keyword:`while` or :keyword:`for`.
- struct sequence
- A tuple with named elements. Struct sequences expose an interface similar
- to :term:`named tuple` in that elements can be accessed either by
- index or as an attribute. However, they do not have any of the named tuple
- methods like :meth:`~collections.somenamedtuple._make` or
- :meth:`~collections.somenamedtuple._asdict`. Examples of struct sequences
- include :data:`sys.float_info` and the return value of :func:`os.stat`.
-
text encoding
A codec which encodes Unicode strings to bytes.
machinery in the main process (even though the logging events are generated in
the worker processes) to direct the messages to the appropriate destinations.
+Using concurrent.futures.ProcessPoolExecutor
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If you want to use :class:`concurrent.futures.ProcessPoolExecutor` to start
+your worker processes, you need to create the queue slightly differently.
+Instead of
+
+.. code-block:: python
+
+ queue = multiprocessing.Queue(-1)
+
+you should use
+
+.. code-block:: python
+
+ queue = multiprocessing.Manager().Queue(-1) # also works with the examples above
+
+and you can then replace the worker creation from this::
+
+ workers = []
+ for i in range(10):
+ worker = multiprocessing.Process(target=worker_process,
+ args=(queue, worker_configurer))
+ workers.append(worker)
+ worker.start()
+ for w in workers:
+ w.join()
+
+to this (remembering to first import :mod:`concurrent.futures`)::
+
+ with concurrent.futures.ProcessPoolExecutor(max_workers=10) as executor:
+ for i in range(10):
+ executor.submit(worker_process, queue, worker_configurer)
+
+
Using file rotation
-------------------
conditional logging that's required. The decorator takes a logger as a parameter
and attaches a memory handler for the duration of the call to the decorated
function. The decorator can be additionally parameterised using a target handler,
-a level at which flushing should occur, and a capacity for the buffer. These
-default to a :class:`~logging.StreamHandler` which writes to ``sys.stderr``,
-``logging.ERROR`` and ``100`` respectively.
+a level at which flushing should occur, and a capacity for the buffer (number of
+records buffered). These default to a :class:`~logging.StreamHandler` which
+writes to ``sys.stderr``, ``logging.ERROR`` and ``100`` respectively.
Here's the script::
...
007B '{'; LEFT CURLY BRACKET
...
- 2167 'â\85¦': ROMAN NUMERAL EIGHT
- 2168 'Ⅸ': ROMAN NUMERAL NINE
+ 2167 'â\85§'; ROMAN NUMERAL EIGHT
+ 2168 'Ⅸ'; ROMAN NUMERAL NINE
...
- 265E '♞': BLACK CHESS KNIGHT
- 265F '♟': BLACK CHESS PAWN
+ 265E '♞'; BLACK CHESS KNIGHT
+ 265F '♟'; BLACK CHESS PAWN
...
- 1F600 '😀': GRINNING FACE
- 1F609 '😉': WINKING FACE
+ 1F600 '😀'; GRINNING FACE
+ 1F609 '😉'; WINKING FACE
...
Strictly, these definitions imply that it's meaningless to say 'this is
return NULL;
Py_INCREF(&CustomType);
- PyModule_AddObject(m, "Custom", (PyObject *) &CustomType);
+ if (PyModule_AddObject(m, "Custom", (PyObject *) &CustomType) < 0) {
+ Py_DECREF(&CustomType);
+ PY_DECREF(m);
+ return NULL;
+ }
+
return m;
}
return NULL;
Py_INCREF(&CustomType);
- PyModule_AddObject(m, "Custom", (PyObject *) &CustomType);
+ if (PyModule_AddObject(m, "Custom", (PyObject *) &CustomType) < 0) {
+ Py_DECREF(&CustomType);
+ Py_DECREF(m);
+ return NULL;
+ }
+
return m;
}
return NULL;
Py_INCREF(&CustomType);
- PyModule_AddObject(m, "Custom", (PyObject *) &CustomType);
+ if (PyModule_AddObject(m, "Custom", (PyObject *) &CustomType) < 0) {
+ Py_DECREF(&CustomType);
+ Py_DECREF(m);
+ return NULL;
+ }
+
return m;
}
return NULL;
Py_INCREF(&CustomType);
- PyModule_AddObject(m, "Custom", (PyObject *) &CustomType);
+ if (PyModule_AddObject(m, "Custom", (PyObject *) &CustomType) < 0) {
+ Py_DECREF(&CustomType);
+ Py_DECREF(m);
+ return NULL;
+ }
+
return m;
}
# family = the list of all recipients' email addresses
msg['From'] = me
msg['To'] = ', '.join(family)
-msg.preamble = 'Our family reunion'
+msg.preamble = 'You will not see this in a MIME-aware mail reader.\n'
# Open the files in binary mode. Use imghdr to figure out the
# MIME subtype for each specific image.
return NULL;
Py_INCREF(&SubListType);
- PyModule_AddObject(m, "SubList", (PyObject *) &SubListType);
+ if (PyModule_AddObject(m, "SubList", (PyObject *) &SubListType) < 0) {
+ Py_DECREF(&SubListType);
+ Py_DECREF(m);
+ return NULL;
+ }
+
return m;
}
stored; by default ``None`` and no value is stored
* required_ - Whether or not a subcommand must be provided, by default
- ``False``.
+ ``False`` (added in 3.7)
* help_ - help for sub-parser group in help output, by default ``None``
>>> parser.parse_args(['2', 'frobble'])
Namespace(subparser_name='2', y='frobble')
+ .. versionchanged:: 3.7
+ New *required* keyword argument.
+
FileType objects
^^^^^^^^^^^^^^^^
+-----------+--------------------+-------------------+-----------------------+-------+
| ``'L'`` | unsigned long | int | 4 | |
+-----------+--------------------+-------------------+-----------------------+-------+
-| ``'q'`` | signed long long | int | 8 | \(2) |
+| ``'q'`` | signed long long | int | 8 | |
+-----------+--------------------+-------------------+-----------------------+-------+
-| ``'Q'`` | unsigned long long | int | 8 | \(2) |
+| ``'Q'`` | unsigned long long | int | 8 | |
+-----------+--------------------+-------------------+-----------------------+-------+
| ``'f'`` | float | float | 4 | |
+-----------+--------------------+-------------------+-----------------------+-------+
.. deprecated-removed:: 3.3 4.0
-(2)
- The ``'q'`` and ``'Q'`` type codes are available only if
- the platform C compiler used to build Python supports C :c:type:`long long`,
- or, on Windows, :c:type:`__int64`.
-
- .. versionadded:: 3.3
-
The actual representation of values is determined by the machine architecture
(strictly speaking, by the C implementation). The actual size can be accessed
through the :attr:`itemsize` attribute.
.. function:: dump(node, annotate_fields=True, include_attributes=False)
Return a formatted dump of the tree in *node*. This is mainly useful for
- debugging purposes. The returned string will show the names and the values
- for fields. This makes the code impossible to evaluate, so if evaluation is
- wanted *annotate_fields* must be set to ``False``. Attributes such as line
+ debugging purposes. If *annotate_fields* is true (by default),
+ the returned string will show the names and the values for fields.
+ If *annotate_fields* is false, the result string will be more compact by
+ omitting unambiguous field names. Attributes such as line
numbers and column offsets are not dumped by default. If this is wanted,
- *include_attributes* can be set to ``True``.
+ *include_attributes* can be set to true.
.. seealso::
by 1 second.
An executor can be used to run a task in a different thread or even in
-a different process to avoid blocking block the OS thread with the
+a different process to avoid blocking the OS thread with the
event loop. See the :meth:`loop.run_in_executor` method for more
details.
is used for the test.)
* a :class:`Task` object wrapping *obj*, if *obj* is a
- coroutine (:func:`iscoroutine` is used for the test.)
+ coroutine (:func:`iscoroutine` is used for the test);
+ in this case the coroutine will be scheduled by
+ ``ensure_future()``.
* a :class:`Task` object that would await on *obj*, if *obj* is an
awaitable (:func:`inspect.isawaitable` is used for the test.)
class EchoClientProtocol(asyncio.Protocol):
- def __init__(self, message, on_con_lost, loop):
+ def __init__(self, message, on_con_lost):
self.message = message
- self.loop = loop
self.on_con_lost = on_con_lost
def connection_made(self, transport):
message = 'Hello World!'
transport, protocol = await loop.create_connection(
- lambda: EchoClientProtocol(message, on_con_lost, loop),
+ lambda: EchoClientProtocol(message, on_con_lost),
'127.0.0.1', 8888)
# Wait until the protocol signals that the connection
class EchoClientProtocol:
- def __init__(self, message, loop):
+ def __init__(self, message, on_con_lost):
self.message = message
- self.loop = loop
+ self.on_con_lost = on_con_lost
self.transport = None
- self.on_con_lost = loop.create_future()
def connection_made(self, transport):
self.transport = transport
# low-level APIs.
loop = asyncio.get_running_loop()
+ on_con_lost = loop.create_future()
message = "Hello World!"
+
transport, protocol = await loop.create_datagram_endpoint(
- lambda: EchoClientProtocol(message, loop),
+ lambda: EchoClientProtocol(message, on_con_lost),
remote_addr=('127.0.0.1', 9999))
try:
- await protocol.on_con_lost
+ await on_con_lost
finally:
transport.close()
class MyProtocol(asyncio.Protocol):
- def __init__(self, loop):
+ def __init__(self, on_con_lost):
self.transport = None
- self.on_con_lost = loop.create_future()
+ self.on_con_lost = on_con_lost
def connection_made(self, transport):
self.transport = transport
# Get a reference to the event loop as we plan to use
# low-level APIs.
loop = asyncio.get_running_loop()
+ on_con_lost = loop.create_future()
# Create a pair of connected sockets
rsock, wsock = socket.socketpair()
# Register the socket to wait for data.
transport, protocol = await loop.create_connection(
- lambda: MyProtocol(loop), sock=rsock)
+ lambda: MyProtocol(on_con_lost), sock=rsock)
# Simulate the reception of data from the network.
loop.call_soon(wsock.send, 'abc'.encode())
cond = asyncio.Condition()
# ... later
- await lock.acquire()
+ await cond.acquire()
try:
await cond.wait()
finally:
- lock.release()
+ cond.release()
.. coroutinemethod:: acquire()
.. function:: run(coro, \*, debug=False)
+ Execute the :term:`coroutine` *coro* and return the result.
+
This function runs the passed coroutine, taking care of
managing the asyncio event loop and *finalizing asynchronous
generators*.
the end. It should be used as a main entry point for asyncio
programs, and should ideally only be called once.
+ Example::
+
+ async def main():
+ await asyncio.sleep(1)
+ print('hello')
+
+ asyncio.run(main())
+
.. versionadded:: 3.7
**Important:** this function has been added to asyncio in
Python 3.7 on a :term:`provisional basis <provisional api>`.
To simplify and standardize error handling,
codecs may implement different error handling schemes by
-accepting the *errors* string argument. The following string values are
+accepting the *errors* string argument. The following string values are
defined and implemented by all standard Python codecs:
.. tabularcolumns:: |l|L|
| Value | Meaning |
+=========================+===============================================+
| ``'strict'`` | Raise :exc:`UnicodeError` (or a subclass); |
-| | this is the default. Implemented in |
+| | this is the default. Implemented in |
| | :func:`strict_errors`. |
+-------------------------+-----------------------------------------------+
| ``'ignore'`` | Ignore the malformed data and continue |
-| | without further notice. Implemented in |
+| | without further notice. Implemented in |
| | :func:`ignore_errors`. |
+-------------------------+-----------------------------------------------+
| | marker; Python will use the official |
| | ``U+FFFD`` REPLACEMENT CHARACTER for the |
| | built-in codecs on decoding, and '?' on |
-| | encoding. Implemented in |
+| | encoding. Implemented in |
| | :func:`replace_errors`. |
+-------------------------+-----------------------------------------------+
| ``'xmlcharrefreplace'`` | Replace with the appropriate XML character |
-| | reference (only for encoding). Implemented |
+| | reference (only for encoding). Implemented |
| | in :func:`xmlcharrefreplace_errors`. |
+-------------------------+-----------------------------------------------+
| ``'backslashreplace'`` | Replace with backslashed escape sequences. |
| | :func:`backslashreplace_errors`. |
+-------------------------+-----------------------------------------------+
| ``'namereplace'`` | Replace with ``\N{...}`` escape sequences |
-| | (only for encoding). Implemented in |
+| | (only for encoding). Implemented in |
| | :func:`namereplace_errors`. |
+-------------------------+-----------------------------------------------+
| ``'surrogateescape'`` | On decoding, replace byte with individual |
| | surrogate code ranging from ``U+DC80`` to |
-| | ``U+DCFF``. This code will then be turned |
+| | ``U+DCFF``. This code will then be turned |
| | back into the same byte when the |
| | ``'surrogateescape'`` error handler is used |
-| | when encoding the data. (See :pep:`383` for |
+| | when encoding the data. (See :pep:`383` for |
| | more.) |
+-------------------------+-----------------------------------------------+
| Value | Codecs | Meaning |
+===================+========================+===========================================+
|``'surrogatepass'``| utf-8, utf-16, utf-32, | Allow encoding and decoding of surrogate |
-| | utf-16-be, utf-16-le, | codes. These codecs normally treat the |
+| | utf-16-be, utf-16-le, | codes. These codecs normally treat the |
| | utf-32-be, utf-32-le | presence of surrogates as an error. |
+-------------------+------------------------+-------------------------------------------+
error handler must either raise this or a different exception, or return a
tuple with a replacement for the unencodable part of the input and a position
where encoding should continue. The replacement may be either :class:`str` or
- :class:`bytes`. If the replacement is bytes, the encoder will simply copy
+ :class:`bytes`. If the replacement is bytes, the encoder will simply copy
them into the output buffer. If the replacement is a string, the encoder will
- encode the replacement. Encoding continues on original input at the
+ encode the replacement. Encoding continues on original input at the
specified position. Negative position values will be treated as being
relative to the end of the input string. If the resulting position is out of
bound an :exc:`IndexError` will be raised.
.. method:: Codec.decode(input[, errors])
Decodes the object *input* and returns a tuple (output object, length
- consumed). For instance, for a :term:`text encoding`, decoding converts
+ consumed). For instance, for a :term:`text encoding`, decoding converts
a bytes object encoded using a particular
character set encoding to a string object.
implementation should make sure that ``0`` is the most common
state. (States that are more complicated than integers can be converted
into an integer by marshaling/pickling the state and encoding the bytes
- of the resulting string into an integer).
+ of the resulting string into an integer.)
.. method:: setstate(state)
number of encoded bytes or code points to read
for decoding. The decoder can modify this setting as
appropriate. The default value -1 indicates to read and decode as much as
- possible. This parameter is intended to
+ possible. This parameter is intended to
prevent having to decode huge files in one step.
The *firstline* flag indicates that
Read all lines available on the input stream and return them as a list of
lines.
- Line-endings are implemented using the codec's decoder method and are
- included in the list entries if *keepends* is true.
+ Line-endings are implemented using the codec's :meth:`decode` method and
+ are included in the list entries if *keepends* is true.
*sizehint*, if given, is passed as the *size* argument to the stream's
:meth:`read` method.
Resets the codec buffers used for keeping state.
- Note that no stream repositioning should take place. This method is
+ Note that no stream repositioning should take place. This method is
primarily intended to be able to recover from decoding errors.
code calling :meth:`read` and :meth:`write`, while *Reader* and *Writer*
work on the backend — the data in *stream*.
- You can use these objects to do transparent transcodings from e.g. Latin-1
+ You can use these objects to do transparent transcodings, e.g., from Latin-1
to UTF-8 and back.
The *stream* argument must be a file-like object.
---------------------
Strings are stored internally as sequences of code points in
-range ``0x0``--``0x10FFFF``. (See :pep:`393` for
+range ``0x0``--``0x10FFFF``. (See :pep:`393` for
more details about the implementation.)
Once a string object is used outside of CPU and memory, endianness
-and how these arrays are stored as bytes become an issue. As with other
+and how these arrays are stored as bytes become an issue. As with other
codecs, serialising a string into a sequence of bytes is known as *encoding*,
and recreating the string from the sequence of bytes is known as *decoding*.
There are a variety of different text serialisation codecs, which are
signature that helps in guessing the encoding. On encoding the utf-8-sig codec
will write ``0xef``, ``0xbb``, ``0xbf`` as the first three bytes to the file. On
decoding ``utf-8-sig`` will skip those three bytes if they appear as the first
-three bytes in the file. In UTF-8, the use of the BOM is discouraged and
+three bytes in the file. In UTF-8, the use of the BOM is discouraged and
should generally be avoided.
.. impl-detail::
Some common encodings can bypass the codecs lookup machinery to
- improve performance. These optimization opportunities are only
+ improve performance. These optimization opportunities are only
recognized by CPython for a limited set of (case insensitive)
aliases: utf-8, utf8, latin-1, latin1, iso-8859-1, iso8859-1, mbcs
(Windows only), ascii, us-ascii, utf-16, utf16, utf-32, utf32, and
| iso2022_kr | csiso2022kr, iso2022kr, | Korean |
| | iso-2022-kr | |
+-----------------+--------------------------------+--------------------------------+
-| latin_1 | iso-8859-1, iso8859-1, 8859, | West Europe |
+| latin_1 | iso-8859-1, iso8859-1, 8859, | Western Europe |
| | cp819, latin, latin1, L1 | |
+-----------------+--------------------------------+--------------------------------+
| iso8859_2 | iso-8859-2, latin2, L2 | Central and Eastern Europe |
-------------------------
A number of predefined codecs are specific to Python, so their codec names have
-no meaning outside Python. These are listed in the tables below based on the
+no meaning outside Python. These are listed in the tables below based on the
expected input and output types (note that while text encodings are the most
common use case for codecs, the underlying codec infrastructure supports
-arbitrary data transforms rather than just text encodings). For asymmetric
-codecs, the stated purpose describes the encoding direction.
+arbitrary data transforms rather than just text encodings). For asymmetric
+codecs, the stated meaning describes the encoding direction.
Text Encodings
^^^^^^^^^^^^^^
.. tabularcolumns:: |l|p{0.3\linewidth}|p{0.3\linewidth}|
+--------------------+---------+---------------------------+
-| Codec | Aliases | Purpose |
+| Codec | Aliases | Meaning |
+====================+=========+===========================+
-| idna | | Implements :rfc:`3490`, |
+| idna | | Implement :rfc:`3490`, |
| | | see also |
| | | :mod:`encodings.idna`. |
| | | Only ``errors='strict'`` |
| | | is supported. |
+--------------------+---------+---------------------------+
-| mbcs | ansi, | Windows only: Encode |
+| mbcs | ansi, | Windows only: Encode the |
| | dbcs | operand according to the |
-| | | ANSI codepage (CP_ACP) |
+| | | ANSI codepage (CP_ACP). |
+--------------------+---------+---------------------------+
-| oem | | Windows only: Encode |
+| oem | | Windows only: Encode the |
| | | operand according to the |
-| | | OEM codepage (CP_OEMCP) |
+| | | OEM codepage (CP_OEMCP). |
| | | |
| | | .. versionadded:: 3.6 |
+--------------------+---------+---------------------------+
-| palmos | | Encoding of PalmOS 3.5 |
+| palmos | | Encoding of PalmOS 3.5. |
+--------------------+---------+---------------------------+
-| punycode | | Implements :rfc:`3492`. |
+| punycode | | Implement :rfc:`3492`. |
| | | Stateful codecs are not |
| | | supported. |
+--------------------+---------+---------------------------+
| | | literal in ASCII-encoded |
| | | Python source code, |
| | | except that quotes are |
-| | | not escaped. Decodes from |
-| | | Latin-1 source code. |
+| | | not escaped. Decode |
+| | | from Latin-1 source code. |
| | | Beware that Python source |
| | | code actually uses UTF-8 |
| | | by default. |
^^^^^^^^^^^^^^^^^
The following codecs provide binary transforms: :term:`bytes-like object`
-to :class:`bytes` mappings. They are not supported by :meth:`bytes.decode`
+to :class:`bytes` mappings. They are not supported by :meth:`bytes.decode`
(which only produces :class:`str` output).
.. tabularcolumns:: |l|L|L|L|
+----------------------+------------------+------------------------------+------------------------------+
-| Codec | Aliases | Purpose | Encoder / decoder |
+| Codec | Aliases | Meaning | Encoder / decoder |
+======================+==================+==============================+==============================+
-| base64_codec [#b64]_ | base64, base_64 | Convert operand to multiline | :meth:`base64.encodebytes` / |
-| | | MIME base64 (the result | :meth:`base64.decodebytes` |
-| | | always includes a trailing | |
-| | | ``'\n'``) | |
+| base64_codec [#b64]_ | base64, base_64 | Convert the operand to | :meth:`base64.encodebytes` / |
+| | | multiline MIME base64 (the | :meth:`base64.decodebytes` |
+| | | result always includes a | |
+| | | trailing ``'\n'``). | |
| | | | |
| | | .. versionchanged:: 3.4 | |
| | | accepts any | |
| | | as input for encoding and | |
| | | decoding | |
+----------------------+------------------+------------------------------+------------------------------+
-| bz2_codec | bz2 | Compress the operand | :meth:`bz2.compress` / |
-| | | using bz2 | :meth:`bz2.decompress` |
+| bz2_codec | bz2 | Compress the operand using | :meth:`bz2.compress` / |
+| | | bz2. | :meth:`bz2.decompress` |
+----------------------+------------------+------------------------------+------------------------------+
-| hex_codec | hex | Convert operand to | :meth:`binascii.b2a_hex` / |
+| hex_codec | hex | Convert the operand to | :meth:`binascii.b2a_hex` / |
| | | hexadecimal | :meth:`binascii.a2b_hex` |
| | | representation, with two | |
-| | | digits per byte | |
+| | | digits per byte. | |
+----------------------+------------------+------------------------------+------------------------------+
-| quopri_codec | quopri, | Convert operand to MIME | :meth:`quopri.encode` with |
-| | quotedprintable, | quoted printable | ``quotetabs=True`` / |
+| quopri_codec | quopri, | Convert the operand to MIME | :meth:`quopri.encode` with |
+| | quotedprintable, | quoted printable. | ``quotetabs=True`` / |
| | quoted_printable | | :meth:`quopri.decode` |
+----------------------+------------------+------------------------------+------------------------------+
| uu_codec | uu | Convert the operand using | :meth:`uu.encode` / |
-| | | uuencode | :meth:`uu.decode` |
+| | | uuencode. | :meth:`uu.decode` |
+----------------------+------------------+------------------------------+------------------------------+
-| zlib_codec | zip, zlib | Compress the operand | :meth:`zlib.compress` / |
-| | | using gzip | :meth:`zlib.decompress` |
+| zlib_codec | zip, zlib | Compress the operand using | :meth:`zlib.compress` / |
+| | | gzip. | :meth:`zlib.decompress` |
+----------------------+------------------+------------------------------+------------------------------+
.. [#b64] In addition to :term:`bytes-like objects <bytes-like object>`,
^^^^^^^^^^^^^^^
The following codec provides a text transform: a :class:`str` to :class:`str`
-mapping. It is not supported by :meth:`str.encode` (which only produces
+mapping. It is not supported by :meth:`str.encode` (which only produces
:class:`bytes` output).
.. tabularcolumns:: |l|l|L|
+--------------------+---------+---------------------------+
-| Codec | Aliases | Purpose |
+| Codec | Aliases | Meaning |
+====================+=========+===========================+
-| rot_13 | rot13 | Returns the Caesar-cypher |
-| | | encryption of the operand |
+| rot_13 | rot13 | Return the Caesar-cypher |
+| | | encryption of the |
+| | | operand. |
+--------------------+---------+---------------------------+
.. versionadded:: 3.2
based on the separator characters defined in :rfc:`section 3.1 of RFC 3490 <3490#section-3.1>`
and converting each label to ACE as required, and conversely separating an input
byte string into labels based on the ``.`` separator and converting any ACE
-labels found into unicode. Furthermore, the :mod:`socket` module
+labels found into unicode. Furthermore, the :mod:`socket` module
transparently converts Unicode host names to ACE, so that applications need not
be concerned about converting host names themselves when they pass them to the
socket module. On top of that, modules that have host names as function
:mailheader:`Host` field if it sends that field at all).
When receiving host names from the wire (such as in reverse name lookup), no
-automatic conversion to Unicode is performed: Applications wishing to present
+automatic conversion to Unicode is performed: applications wishing to present
such host names to the user should decode them to Unicode.
The module :mod:`encodings.idna` also implements the nameprep procedure, which
.. module:: encodings.mbcs
:synopsis: Windows ANSI codepage
-Encode operand according to the ANSI codepage (CP_ACP).
+This module implements the ANSI codepage (CP_ACP).
.. availability:: Windows only.
:synopsis: UTF-8 codec with BOM signature
.. moduleauthor:: Walter Dörwald
-This module implements a variant of the UTF-8 codec: On encoding a UTF-8 encoded
+This module implements a variant of the UTF-8 codec. On encoding, a UTF-8 encoded
BOM will be prepended to the UTF-8 encoded bytes. For the stateful encoder this
-is only done once (on the first write to the byte stream). For decoding an
+is only done once (on the first write to the byte stream). On decoding, an
optional UTF-8 encoded BOM at the start of the data will be skipped.
:class:`UserString` wrapper around string objects for easier string subclassing
===================== ====================================================================
-.. versionchanged:: 3.3
+.. deprecated-removed:: 3.3 3.9
Moved :ref:`collections-abstract-base-classes` to the :mod:`collections.abc` module.
For backwards compatibility, they continue to be visible in this module through
- Python 3.7. Subsequently, they will be removed entirely.
+ Python 3.8.
:class:`ChainMap` objects
my_dir: %(home_dir)s/lumberjack
my_pictures: %(my_dir)s/Pictures
+ [Escape]
+ gain: 80%% # use a %% to escape the % sign (% is the only character that needs to be escaped)
In the example above, :class:`ConfigParser` with *interpolation* set to
``BasicInterpolation()`` would resolve ``%(home_dir)s`` to the value of
my_dir: ${home_dir}/lumberjack
my_pictures: ${my_dir}/Pictures
+ [Escape]
+ cost: $$80 # use a $$ to escape the $ sign ($ is the only character that needs to be escaped)
+
Values from other sections can be fetched as well:
.. code-block:: ini
>>> POINT(1, 2, 3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
- ValueError: too many initializers
+ TypeError: too many initializers
>>>
You can, however, build much more complicated structures. A structure can
doesn't *copy* the sub-object, instead it retrieves a wrapper object accessing
the root-object's underlying buffer.
-Another example that may behave different from what one would expect is this::
+Another example that may behave differently from what one would expect is this::
>>> s = c_char_p()
- >>> s.value = "abc def ghi"
+ >>> s.value = b"abc def ghi"
>>> s.value
- 'abc def ghi'
+ b'abc def ghi'
>>> s.value is s.value
False
>>>
+.. note::
+
+ Objects instantiated from :class:`c_char_p` can only have their value set to bytes
+ or integers.
+
Why is it printing ``False``? ctypes instances are objects containing a memory
block plus some :term:`descriptor`\s accessing the contents of the memory.
Storing a Python object in the memory block does not store the object itself,
.. data:: ERR
- Some curses routines that return an integer, such as :func:`getch`, return
+ Some curses routines that return an integer, such as :meth:`~window.getch`, return
:const:`ERR` upon failure.
**********
The modules described in this chapter provide a variety of specialized data
-types such as dates and times, fixed-type arrays, heap queues, synchronized
-queues, and sets.
+types such as dates and times, fixed-type arrays, heap queues, double-ended
+queues, and enumerations.
Python also provides some built-in data types, in particular,
:class:`dict`, :class:`list`, :class:`set` and :class:`frozenset`, and
:class:`tuple`. The :class:`str` class is used to hold
-Unicode strings, and the :class:`bytes` class is used to hold binary data.
+Unicode strings, and the :class:`bytes` and :class:`bytearray` classes are used
+to hold binary data.
The following modules are documented in this chapter:
.. class:: date(year, month, day)
- All arguments are required. Arguments may be integers, in the following
+ All arguments are required. Arguments must be integers in the following
ranges:
* ``MINYEAR <= year <= MAXYEAR``
.. class:: datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0)
The year, month and day arguments are required. *tzinfo* may be ``None``, or an
- instance of a :class:`tzinfo` subclass. The remaining arguments may be integers,
+ instance of a :class:`tzinfo` subclass. The remaining arguments must be integers
in the following ranges:
* ``MINYEAR <= year <= MAXYEAR``,
.. caution::
This does not support parsing arbitrary ISO 8601 strings - it is only intended
- as the inverse operation of :meth:`datetime.isoformat`.
+ as the inverse operation of :meth:`datetime.isoformat`. A more full-featured
+ ISO 8601 parser, ``dateutil.parser.isoparse`` is available in the third-party package
+ `dateutil <https://dateutil.readthedocs.io/en/stable/parser.html#dateutil.parser.isoparse>`_.
.. versionadded:: 3.7
.. class:: time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0)
All arguments are optional. *tzinfo* may be ``None``, or an instance of a
- :class:`tzinfo` subclass. The remaining arguments may be integers, in the
+ :class:`tzinfo` subclass. The remaining arguments must be integers in the
following ranges:
* ``0 <= hour < 24``,
to try :meth:`quick_ratio` or :meth:`real_quick_ratio` first to get an
upper bound.
+ .. note::
+
+ Caution: The result of a :meth:`ratio` call may depend on the order of
+ the arguments. For instance::
+
+ >>> SequenceMatcher(None, 'tide', 'diet').ratio()
+ 0.25
+ >>> SequenceMatcher(None, 'diet', 'tide').ratio()
+ 0.5
+
.. method:: quick_ratio()
:func:`cancel_dump_traceback_later` is called: see :ref:`issue with file
descriptors <faulthandler-fd>`.
- This function is implemented using a watchdog thread and therefore is not
- available if Python is compiled with threads disabled.
+ This function is implemented using a watchdog thread.
+
+ .. versionchanged:: 3.7
+ This function is now always available.
.. versionchanged:: 3.5
Added support for passing file descriptor to this function.
drwxr-sr-x 4 1176 1176 4096 Nov 17 2008 project
drwxr-xr-x 3 1176 1176 4096 Oct 10 2012 tools
'226 Directory send OK.'
- >>> ftp.retrbinary('RETR README', open('README', 'wb').write)
+ >>> with open('README', 'wb') as fp:
+ >>> ftp.retrbinary('RETR README', fp.write)
'226 Transfer complete.'
>>> ftp.quit()
n += 1
-.. function:: eval(expression, globals=None, locals=None)
+.. function:: eval(expression[, globals[, locals]])
The arguments are a string and optional globals and locals. If provided,
*globals* must be a dictionary. If provided, *locals* can be any mapping
super().method(arg) # This does the same thing as:
# super(C, self).method(arg)
+ In addition to method lookups, :func:`super` also works for attribute
+ lookups. One possible use case for this is calling :term:`descriptor`\s
+ in a parent or sibling class.
+
Note that :func:`super` is implemented as part of the binding process for
explicit dotted attribute lookups such as ``super().__getitem__(name)``.
It does so by implementing its own :meth:`__getattribute__` method for searching
single: **; in glob-style wildcards
If *recursive* is true, the pattern "``**``" will match any files and zero or
- more directories and subdirectories. If the pattern is followed by an
- ``os.sep``, only directories and subdirectories match.
+ more directories, subdirectories and symbolic links to directories. If the
+ pattern is followed by an :data:`os.sep` or :data:`os.altsep` then files will not
+ match.
.. note::
Using the "``**``" pattern in large directory trees may consume
>>> # The following example demonstrates reading data in chunks.
>>> conn.request("GET", "/")
>>> r1 = conn.getresponse()
- >>> while not r1.closed:
- ... print(r1.read(200)) # 200 bytes
+ >>> while True:
+ ... chunk = r1.read(200) # 200 bytes
+ ... if not chunk:
+ ... break
+ ... print(repr(chunk))
b'<!doctype html>\n<!--[if"...
...
>>> # Example of an invalid request
the :class:`CookieJar`'s :class:`CookiePolicy` instance are true and false
respectively), the :mailheader:`Cookie2` header is also added when appropriate.
- The *request* object (usually a :class:`urllib.request..Request` instance)
+ The *request* object (usually a :class:`urllib.request.Request` instance)
must support the methods :meth:`get_full_url`, :meth:`get_host`,
:meth:`get_type`, :meth:`unverifiable`, :meth:`has_header`,
:meth:`get_header`, :meth:`header_items`, :meth:`add_unredirected_header`
Run menu (Editor window only)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-.. _python-shell:
-
-Python Shell
- Open or wake up the Python Shell window.
-
-.. _check-module:
-
-Check Module
- Check the syntax of the module currently open in the Editor window. If the
- module has not been saved IDLE will either prompt the user to save or
- autosave, as selected in the General tab of the Idle Settings dialog. If
- there is a syntax error, the approximate location is indicated in the
- Editor window.
-
.. _run-module:
Run Module
settings. *Command Line Arguments* extend :data:`sys.argv` as if passed
on a command line. The module can be run in the Shell without restarting.
+.. _check-module:
+
+Check Module
+ Check the syntax of the module currently open in the Editor window. If the
+ module has not been saved IDLE will either prompt the user to save or
+ autosave, as selected in the General tab of the Idle Settings dialog. If
+ there is a syntax error, the approximate location is indicated in the
+ Editor window.
+
+.. _python-shell:
+
+Python Shell
+ Open or wake up the Python Shell window.
+
Shell menu (Shell window only)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Configure IDLE
Open a configuration dialog and change preferences for the following:
fonts, indentation, keybindings, text color themes, startup windows and
- size, additional help sources, and extensions. On macOS, open the
+ size, additional help sources, and extensions. On macOS, open the
configuration dialog by selecting Preferences in the application
- menu. For more, see
+ menu. For more details, see
:ref:`Setting preferences <preferences>` under Help and preferences.
+Most configuration options apply to all windows or all future windows.
+The option items below only apply to the active window.
+
Show/Hide Code Context (Editor Window only)
Open a pane at the top of the edit window which shows the block context
of the code which has scrolled above the top of the window. See
- :ref:`Code Context <code-context>` in the Editing and Navigation section below.
+ :ref:`Code Context <code-context>` in the Editing and Navigation section
+ below.
+
+Show/Hide Line Numbers (Editor Window only)
+ Open a column to the left of the edit window which shows the number
+ of each line of text. The default is off, which may be changed in the
+ preferences (see :ref:`Setting preferences <preferences>`).
Zoom/Restore Height
Toggles the window between normal size and maximum height. The initial size
defaults to 40 lines by 80 chars unless changed on the General tab of the
Configure IDLE dialog. The maximum height for a screen is determined by
momentarily maximizing a window the first time one is zoomed on the screen.
- Changing screen settings may invalidate the saved height. This toogle has
+ Changing screen settings may invalidate the saved height. This toggle has
no effect when a window is maximized.
Window menu (Shell and Editor)
IDLE should be started in a command line window. The secondary subprocess
will then be attached to that window for input and output.
+The IDLE code running in the execution process adds frames to the call stack
+that would not be there otherwise. IDLE wraps ``sys.getrecursionlimit`` and
+``sys.setrecursionlimit`` to reduce the effect of the additional stack frames.
+
If ``sys`` is reset by user code, such as with ``importlib.reload(sys)``,
IDLE's changes are lost and input from the keyboard and output to the screen
will not work correctly.
contained in the list returned by :func:`get_suffixes` describing the kind of
module found.
- If the module does not live in a file, the returned *file* is ``None``,
- *pathname* is the empty string, and the *description* tuple contains empty
- strings for its suffix and mode; the module type is indicated as given in
- parentheses above. If the search is unsuccessful, :exc:`ImportError` is
- raised. Other exceptions indicate problems with the arguments or
- environment.
+ If the module is built-in or frozen then *file* and *pathname* are both ``None``
+ and the *description* tuple contains empty strings for its suffix and mode;
+ the module type is indicated as given in parentheses above. If the search
+ is unsuccessful, :exc:`ImportError` is raised. Other exceptions indicate
+ problems with the arguments or environment.
If the module is a package, *file* is ``None``, *pathname* is the package
path and the last item in the *description* tuple is :const:`PKG_DIRECTORY`.
parent package. If a spec cannot be found, ``None`` is returned.
When passed in, ``target`` is a module object that the finder may
use to make a more educated guess about what spec to return.
+ :func:`importlib.util.spec_from_loader` may be useful for implementing
+ concrete ``MetaPathFinders``.
.. versionadded:: 3.4
within the :term:`path entry` to which it is assigned. If a spec
cannot be found, ``None`` is returned. When passed in, ``target``
is a module object that the finder may use to make a more educated
- guess about what spec to return.
+ guess about what spec to return. :func:`importlib.util.spec_from_loader`
+ may be useful for implementing concrete ``PathEntryFinders``.
.. versionadded:: 3.4
packages or a module).
Loaders that wish to support resource reading are expected to
- provide a method called ``get_resource_loader(fullname)`` which
+ provide a method called ``get_resource_reader(fullname)`` which
returns an object implementing this ABC's interface. If the module
specified by fullname is not a package, this method should return
:const:`None`. An object compatible with this ABC should only be
Note that it's already possible to iterate on file objects using ``for
line in file: ...`` without calling ``file.readlines()``.
- .. method:: seek(offset[, whence])
+ .. method:: seek(offset, whence=SEEK_SET)
Change the stream position to the given byte *offset*. *offset* is
interpreted relative to the position indicated by *whence*. The default
If *size* is specified, at most *size* characters will be read.
- .. method:: seek(offset[, whence])
+ .. method:: seek(offset, whence=SEEK_SET)
Change the stream position to the given *offset*. Behaviour depends on
the *whence* parameter. The default value for *whence* is
*errors*, *newline*, *line_buffering* and *write_through*.
Parameters not specified keep current settings, except
- ``errors='strict`` is used when *encoding* is specified but
+ ``errors='strict'`` is used when *encoding* is specified but
*errors* is not specified.
It is not possible to change the encoding or newline if some data
used anywhere else; otherwise, the *iterable* could get advanced without
the tee objects being informed.
+ ``tee`` iterators are not threadsafe. A :exc:`RuntimeError` may be
+ raised when using simultaneously iterators returned by the same :func:`tee`
+ call, even if the original *iterable* is threadsafe.
+
This itertool may require significant auxiliary storage (depending on how
much temporary data needs to be stored). In general, if one iterator uses
most or all of the data before another iterator starts, it is faster to use
.. method:: makePickle(record)
Pickles the record's attribute dictionary in binary format with a length
- prefix, and returns it ready for transmission across the socket.
+ prefix, and returns it ready for transmission across the socket. The
+ details of this operation are equivalent to::
+
+ data = pickle.dumps(record_attr_dict, 1)
+ datalen = struct.pack('>L', len(data))
+ return datalen + data
Note that pickles aren't completely secure. If you are concerned about
security, you may want to override this method to implement a more secure
.. method:: send(packet)
- Send a pickled string *packet* to the socket. This function allows for
- partial sends which can happen when the network is busy.
+ Send a pickled byte-string *packet* to the socket. The format of the sent
+ byte-string is as described in the documentation for
+ :meth:`~SocketHandler.makePickle`.
+
+ This function allows for partial sends, which can happen when the network
+ is busy.
.. method:: createSocket()
.. method:: send(s)
- Send a pickled string to a socket.
+ Send a pickled byte-string to a socket. The format of the sent byte-string
+ is as described in the documentation for :meth:`SocketHandler.makePickle`.
.. _syslog-handler:
.. class:: BufferingHandler(capacity)
- Initializes the handler with a buffer of the specified capacity.
+ Initializes the handler with a buffer of the specified capacity. Here,
+ *capacity* means the number of logging records buffered.
.. method:: emit(record)
.. class:: MemoryHandler(capacity, flushLevel=ERROR, target=None, flushOnClose=True)
Returns a new instance of the :class:`MemoryHandler` class. The instance is
- initialized with a buffer size of *capacity*. If *flushLevel* is not specified,
- :const:`ERROR` is used. If no *target* is specified, the target will need to be
- set using :meth:`setTarget` before this handler does anything useful. If
- *flushOnClose* is specified as ``False``, then the buffer is *not* flushed when
- the handler is closed. If not specified or specified as ``True``, the previous
- behaviour of flushing the buffer will occur when the handler is closed.
+ initialized with a buffer size of *capacity* (number of records buffered).
+ If *flushLevel* is not specified, :const:`ERROR` is used. If no *target* is
+ specified, the target will need to be set using :meth:`setTarget` before this
+ handler does anything useful. If *flushOnClose* is specified as ``False``,
+ then the buffer is *not* flushed when the handler is closed. If not specified
+ or specified as ``True``, the previous behaviour of flushing the buffer will
+ occur when the handler is closed.
.. versionchanged:: 3.6
The *flushOnClose* parameter was added.
.. class:: QueueHandler(queue)
Returns a new instance of the :class:`QueueHandler` class. The instance is
- initialized with the queue to send messages to. The queue can be any
- queue-like object; it's used as-is by the :meth:`enqueue` method, which needs
- to know how to send messages to it.
+ initialized with the queue to send messages to. The *queue* can be any
+ queue-like object; it's used as-is by the :meth:`enqueue` method, which
+ needs to know how to send messages to it. The queue is not *required* to
+ have the task tracking API, which means that you can use
+ :class:`~queue.SimpleQueue` instances for *queue*.
.. method:: emit(record)
- Enqueues the result of preparing the LogRecord.
+ Enqueues the result of preparing the LogRecord. Should an exception
+ occur (e.g. because a bounded queue has filled up), the
+ :meth:`~logging.Handler.handleError` method is called to handle the
+ error. This can result in the record silently being dropped (if
+ :attr:`logging.raiseExceptions` is ``False``) or a message printed to
+ ``sys.stderr`` (if :attr:`logging.raiseExceptions` is ``True``).
.. method:: prepare(record)
initialized with the queue to send messages to and a list of handlers which
will handle entries placed on the queue. The queue can be any queue-like
object; it's passed as-is to the :meth:`dequeue` method, which needs
- to know how to get messages from it. If ``respect_handler_level`` is ``True``,
- a handler's level is respected (compared with the level for the message) when
- deciding whether to pass messages to that handler; otherwise, the behaviour
- is as in previous Python versions - to always pass each message to each
- handler.
+ to know how to get messages from it. The queue is not *required* to have the
+ task tracking API (though it's used if available), which means that you can
+ use :class:`~queue.SimpleQueue` instances for *queue*.
+
+ If ``respect_handler_level`` is ``True``, a handler's level is respected
+ (compared with the level for the message) when deciding whether to pass
+ messages to that handler; otherwise, the behaviour is as in previous Python
+ versions - to always pass each message to each handler.
.. versionchanged:: 3.5
- The ``respect_handler_levels`` argument was added.
+ The ``respect_handler_level`` argument was added.
.. method:: dequeue(block)
Logger Objects
--------------
-Loggers have the following attributes and methods. Note that Loggers are never
-instantiated directly, but always through the module-level function
+Loggers have the following attributes and methods. Note that Loggers should
+*NEVER* be instantiated directly, but always through the module-level function
``logging.getLogger(name)``. Multiple calls to :func:`getLogger` with the same
name will always return a reference to the same Logger object.
:meth:`isEnabledFor` will return/expect to be passed integers.
- .. method:: Logger.isEnabledFor(lvl)
+ .. method:: Logger.isEnabledFor(level)
- Indicates if a message of severity *lvl* would be processed by this logger.
+ Indicates if a message of severity *level* would be processed by this logger.
This method checks first the module-level level set by
- ``logging.disable(lvl)`` and then the logger's effective level as determined
+ ``logging.disable(level)`` and then the logger's effective level as determined
by :meth:`getEffectiveLevel`.
interpreted as for :meth:`debug`.
- .. method:: Logger.log(lvl, msg, *args, **kwargs)
+ .. method:: Logger.log(level, msg, *args, **kwargs)
- Logs a message with integer level *lvl* on this logger. The other arguments are
+ Logs a message with integer level *level* on this logger. The other arguments are
interpreted as for :meth:`debug`.
Logger-level filtering is applied using :meth:`~Logger.filter`.
- .. method:: Logger.makeRecord(name, lvl, fn, lno, msg, args, exc_info, func=None, extra=None, sinfo=None)
+ .. method:: Logger.makeRecord(name, level, fn, lno, msg, args, exc_info, func=None, extra=None, sinfo=None)
This is a factory method which can be overridden in subclasses to create
specialized :class:`LogRecord` instances.
handlers being added multiple times to the root logger, which can in turn
lead to multiple messages for the same event.
-.. function:: disable(lvl=CRITICAL)
+.. function:: disable(level=CRITICAL)
- Provides an overriding level *lvl* for all loggers which takes precedence over
+ Provides an overriding level *level* for all loggers which takes precedence over
the logger's own level. When the need arises to temporarily throttle logging
output down across the whole application, this function can be useful. Its
- effect is to disable all logging calls of severity *lvl* and below, so that
+ effect is to disable all logging calls of severity *level* and below, so that
if you call it with a value of INFO, then all INFO and DEBUG events would be
discarded, whereas those of severity WARNING and above would be processed
according to the logger's effective level. If
Note that if you have defined any custom logging level higher than
``CRITICAL`` (this is not recommended), you won't be able to rely on the
- default value for the *lvl* parameter, but will have to explicitly supply a
+ default value for the *level* parameter, but will have to explicitly supply a
suitable value.
.. versionchanged:: 3.7
- The *lvl* parameter was defaulted to level ``CRITICAL``. See Issue
+ The *level* parameter was defaulted to level ``CRITICAL``. See Issue
#28524 for more information about this change.
-.. function:: addLevelName(lvl, levelName)
+.. function:: addLevelName(level, levelName)
- Associates level *lvl* with text *levelName* in an internal dictionary, which is
+ Associates level *level* with text *levelName* in an internal dictionary, which is
used to map numeric levels to a textual representation, for example when a
:class:`Formatter` formats a message. This function can also be used to define
your own levels. The only constraints are that all levels used must be
.. note:: If you are thinking of defining your own levels, please see the
section on :ref:`custom-levels`.
-.. function:: getLevelName(lvl)
+.. function:: getLevelName(level)
- Returns the textual representation of logging level *lvl*. If the level is one
+ Returns the textual representation of logging level *level*. If the level is one
of the predefined levels :const:`CRITICAL`, :const:`ERROR`, :const:`WARNING`,
:const:`INFO` or :const:`DEBUG` then you get the corresponding string. If you
have associated levels with names using :func:`addLevelName` then the name you
- have associated with *lvl* is returned. If a numeric value corresponding to one
+ have associated with *level* is returned. If a numeric value corresponding to one
of the defined levels is passed in, the corresponding string representation is
- returned. Otherwise, the string 'Level %s' % lvl is returned.
+ returned. Otherwise, the string 'Level %s' % level is returned.
.. note:: Levels are internally integers (as they need to be compared in the
logging logic). This function is used to convert between an integer level
The class should define :meth:`__init__` such that only a name argument is
required, and the :meth:`__init__` should call :meth:`Logger.__init__`. This
function is typically called before any loggers are instantiated by applications
- which need to use custom logger behavior.
+ which need to use custom logger behavior. After this call, as at any other
+ time, do not instantiate loggers directly using the subclass: continue to use
+ the :func:`logging.getLogger` API to get your loggers.
.. function:: setLogRecordFactory(factory)
representation. If *create* is ``True``, the mailbox is created if it does not
exist.
+ If *create* is ``True`` and the *dirname* path exists, it will be treated as
+ an existing maildir without attempting to verify its directory layout.
+
It is for historical reasons that *dirname* is named as such rather than *path*.
Maildir is a directory-based mailbox format invented for the qmail mail
Specifying an empty list for *files* will prevent the system defaults from
being applied: only the well-known values will be present from a built-in list.
+ If *files* is ``None`` the internal data structure is completely rebuilt to its
+ initial default value. This is a stable operation and will produce the same results
+ when called multiple times.
+
.. versionchanged:: 3.2
Previously, Windows registry settings were ignored.
.. note::
- All functions in this module raise :exc:`OSError` in the case of invalid or
- inaccessible file names and paths, or other arguments that have the correct
- type, but are not accepted by the operating system.
+ All functions in this module raise :exc:`OSError` (or subclasses thereof) in
+ the case of invalid or inaccessible file names and paths, or other arguments
+ that have the correct type, but are not accepted by the operating system.
.. exception:: error
This function can support :ref:`specifying a file descriptor <path_fd>`. The
descriptor must refer to an opened directory, not an open file.
+ This function can raise :exc:`OSError` and subclasses such as
+ :exc:`FileNotFoundError`, :exc:`PermissionError`, and :exc:`NotADirectoryError`.
+
.. versionadded:: 3.3
Added support for specifying *path* as a file descriptor
on some platforms.
directories you can set the umask before invoking :func:`makedirs`. The
file permission bits of existing parent directories are not changed.
- If *exist_ok* is ``False`` (the default), an :exc:`OSError` is raised if the
- target directory already exists.
+ If *exist_ok* is ``False`` (the default), an :exc:`FileExistsError` is
+ raised if the target directory already exists.
.. note::
.. function:: remove(path, *, dir_fd=None)
- Remove (delete) the file *path*. If *path* is a directory, :exc:`OSError` is
- raised. Use :func:`rmdir` to remove directories.
+ Remove (delete) the file *path*. If *path* is a directory, an
+ :exc:`IsADirectoryError` is raised. Use :func:`rmdir` to remove directories.
This function can support :ref:`paths relative to directory descriptors
<dir_fd>`.
.. function:: rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None)
- Rename the file or directory *src* to *dst*. If *dst* is a directory,
- :exc:`OSError` will be raised. On Unix, if *dst* exists and is a file, it will
- be replaced silently if the user has permission. The operation may fail on some
- Unix flavors if *src* and *dst* are on different filesystems. If successful,
- the renaming will be an atomic operation (this is a POSIX requirement). On
- Windows, if *dst* already exists, :exc:`OSError` will be raised even if it is a
- file.
+ Rename the file or directory *src* to *dst*. If *dst* exists, the operation
+ will fail with an :exc:`OSError` subclass in a number of cases:
+
+ On Windows, if *dst* exists a :exc:`FileExistsError` is always raised.
+
+ On Unix, if *src* is a file and *dst* is a directory or vice-versa, an
+ :exc:`IsADirectoryError` or a :exc:`NotADirectoryError` will be raised
+ respectively. If both are directories and *dst* is empty, *dst* will be
+ silently replaced. If *dst* is a non-empty directory, an :exc:`OSError`
+ is raised. If both are files, *dst* it will be replaced silently if the user
+ has permission. The operation may fail on some Unix flavors if *src* and
+ *dst* are on different filesystems. If successful, the renaming will be an
+ atomic operation (this is a POSIX requirement).
This function can support specifying *src_dir_fd* and/or *dst_dir_fd* to
supply :ref:`paths relative to directory descriptors <dir_fd>`.
.. function:: rmdir(path, *, dir_fd=None)
- Remove (delete) the directory *path*. Only works when the directory is
- empty, otherwise, :exc:`OSError` is raised. In order to remove whole
- directory trees, :func:`shutil.rmtree` can be used.
+ Remove (delete) the directory *path*. If the directory does not exist or is
+ not empty, an :exc:`FileNotFoundError` or an :exc:`OSError` is raised
+ respectively. In order to remove whole directory trees,
+ :func:`shutil.rmtree` can be used.
This function can support :ref:`paths relative to directory descriptors
<dir_fd>`.
:attr:`children_system`, and :attr:`elapsed` in that order.
See the Unix manual page
- :manpage:`times(2)` or the corresponding Windows Platform API documentation.
+ :manpage:`times(2)` and :manpage:`times(3)` manual page on Unix or `the GetProcessTimes MSDN
+ <https://docs.microsoft.com/windows/win32/api/processthreadsapi/nf-processthreadsapi-getprocesstimes>`
+ _ on Windows.
On Windows, only :attr:`user` and :attr:`system` are known; the other
attributes are zero.
to be created in the target version, with the only restriction being that
migrating to an older version of the interpreter will not support more recent
language constructs. The parse trees are not typically compatible from one
-version to another, whereas source code has always been forward-compatible.
+version to another, though source code has usually been forward-compatible within
+a major release series.
Each element of the sequences returned by :func:`st2list` or :func:`st2tuple`
has a simple form. Sequences representing non-terminal elements in the grammar
.. function:: dump(obj, file, protocol=None, \*, fix_imports=True)
- Write a pickled representation of *obj* to the open :term:`file object` *file*.
- This is equivalent to ``Pickler(file, protocol).dump(obj)``.
+ Write the pickled representation of the object *obj* to the open
+ :term:`file object` *file*. This is equivalent to
+ ``Pickler(file, protocol).dump(obj)``.
The optional *protocol* argument, an integer, tells the pickler to use
the given protocol; supported protocols are 0 to :data:`HIGHEST_PROTOCOL`.
.. function:: dumps(obj, protocol=None, \*, fix_imports=True)
- Return the pickled representation of the object as a :class:`bytes` object,
+ Return the pickled representation of the object *obj* as a :class:`bytes` object,
instead of writing it to a file.
Arguments *protocol* and *fix_imports* have the same meaning as in
.. function:: load(file, \*, fix_imports=True, encoding="ASCII", errors="strict")
- Read a pickled object representation from the open :term:`file object`
+ Read the pickled representation of an object from the open :term:`file object`
*file* and return the reconstituted object hierarchy specified therein.
This is equivalent to ``Unpickler(file).load()``.
The protocol version of the pickle is detected automatically, so no
- protocol argument is needed. Bytes past the pickled object's
- representation are ignored.
+ protocol argument is needed. Bytes past the pickled representation
+ of the object are ignored.
The argument *file* must have two methods, a read() method that takes an
integer argument, and a readline() method that requires no arguments. Both
.. function:: loads(bytes_object, \*, fix_imports=True, encoding="ASCII", errors="strict")
- Read a pickled object hierarchy from a :class:`bytes` object and return the
- reconstituted object hierarchy specified therein.
+ Return the reconstituted object hierarchy of the pickled representation
+ *bytes_object* of an object.
The protocol version of the pickle is detected automatically, so no
- protocol argument is needed. Bytes past the pickled object's
- representation are ignored.
+ protocol argument is needed. Bytes past the pickled representation
+ of the object are ignored.
Optional keyword arguments are *fix_imports*, *encoding* and *errors*,
which are used to control compatibility support for pickle stream generated
.. method:: dump(obj)
- Write a pickled representation of *obj* to the open file object given in
+ Write the pickled representation of *obj* to the open file object given in
the constructor.
.. method:: persistent_id(obj)
.. method:: load()
- Read a pickled object representation from the open file object given in
- the constructor, and return the reconstituted object hierarchy specified
- therein. Bytes past the pickled object's representation are ignored.
+ Read the pickled representation of an object from the open file object
+ given in the constructor, and return the reconstituted object hierarchy
+ specified therein. Bytes past the pickled representation of the object
+ are ignored.
.. method:: persistent_load(pid)
any newer protocol).
The resolution of such persistent IDs is not defined by the :mod:`pickle`
-module; it will delegate this resolution to the user defined methods on the
+module; it will delegate this resolution to the user-defined methods on the
pickler and unpickler, :meth:`~Pickler.persistent_id` and
:meth:`~Unpickler.persistent_load` respectively.
-To pickle objects that have an external persistent id, the pickler must have a
+To pickle objects that have an external persistent ID, the pickler must have a
custom :meth:`~Pickler.persistent_id` method that takes an object as an
-argument and returns either ``None`` or the persistent id for that object.
+argument and returns either ``None`` or the persistent ID for that object.
When ``None`` is returned, the pickler simply pickles the object as normal.
When a persistent ID string is returned, the pickler will pickle that object,
along with a marker so that the unpickler will recognize it as a persistent ID.
sometimes referred to as :dfn:`large files`.
Large file support is enabled in Python when the size of an :c:type:`off_t` is
-larger than a :c:type:`long` and the :c:type:`long long` type is available and is
-at least as large as an :c:type:`off_t`.
+larger than a :c:type:`long` and the :c:type:`long long` is at least as large
+as an :c:type:`off_t`.
It may be necessary to configure and compile Python with certain compiler flags
to enable this mode. For example, it is enabled by default with recent versions
of Irix, but with Solaris 2.6 and 2.7 you need to do something like::
Matches any character which is not a word character. This is
the opposite of ``\w``. If the :const:`ASCII` flag is used this
becomes the equivalent of ``[^a-zA-Z0-9_]``. If the :const:`LOCALE` flag is
- used, matches characters considered alphanumeric in the current locale
- and the underscore.
+ used, matches characters which are neither alphanumeric in the current locale
+ nor the underscore.
.. index:: single: \Z; in regular expressions
This is useful if you want to match an arbitrary literal string that may
have regular expression metacharacters in it. For example::
- >>> print(re.escape('python.exe'))
- python\.exe
+ >>> print(re.escape('http://www.python.org'))
+ http://www\.python\.org
>>> legal_chars = string.ascii_lowercase + string.digits + "!#$%&'*+-.^_`|~:"
>>> print('[%s]+' % re.escape(legal_chars))
>>> print('|'.join(map(re.escape, sorted(operators, reverse=True))))
/|\-|\+|\*\*|\*
- This functions must not be used for the replacement string in :func:`sub`
+ This function must not be used for the replacement string in :func:`sub`
and :func:`subn`, only backslashes should be escaped. For example::
>>> digits_re = r'\d+'
.. versionchanged:: 3.7
Only characters that can have special meaning in a regular expression
- are escaped.
+ are escaped. As a result, ``'!'``, ``'"'``, ``'%'``, ``"'"``, ``','``,
+ ``'/'``, ``':'``, ``';'``, ``'<'``, ``'='``, ``'>'``, ``'@'``, and
+ ``"`"`` are no longer escaped.
.. function:: purge()
Create a kqueue object from a given file descriptor.
-.. method:: kqueue.control(changelist, max_events[, timeout=None]) -> eventlist
+.. method:: kqueue.control(changelist, max_events[, timeout]) -> eventlist
Low level interface to kevent
- - changelist must be an iterable of kevent object or ``None``
+ - changelist must be an iterable of kevent objects or ``None``
- max_events must be 0 or a positive integer
- - timeout in seconds (floats possible)
+ - timeout in seconds (floats possible); the default is ``None``,
+ to wait forever
.. versionchanged:: 3.5
The function is now retried with a recomputed timeout when interrupted by
characters, those characters will be used as the punctuation characters. Any
characters in the :attr:`wordchars` attribute that appear in
*punctuation_chars* will be removed from :attr:`wordchars`. See
- :ref:`improved-shell-compatibility` for more information.
+ :ref:`improved-shell-compatibility` for more information. *punctuation_chars*
+ can be set only upon :class:`~shlex.shlex` instance creation and can't be
+ modified later.
.. versionchanged:: 3.6
The *punctuation_chars* parameter was added.
.. attribute:: shlex.punctuation_chars
- Characters that will be considered punctuation. Runs of punctuation
- characters will be returned as a single token. However, note that no
+ A read-only property. Characters that will be considered punctuation. Runs of
+ punctuation characters will be returned as a single token. However, note that no
semantic validity checking will be performed: for example, '>>>' could be
returned as a token, even though it may not be recognised as such by shells.
All the signal numbers are defined symbolically. For example, the hangup signal
is defined as :const:`signal.SIGHUP`; the variable names are identical to the
- names used in C programs, as found in ``<signal.h>``. The Unix man page for
+ names used in C programs, as found in ``<signal.h>``. The Unix man page for
':c:func:`signal`' lists the existing signals (on some systems this is
:manpage:`signal(2)`, on others the list is in :manpage:`signal(7)`). Note that
not all systems define the same set of signal names; only those names defined by
canceled (only one alarm can be scheduled at any time). The returned value is
then the number of seconds before any previously set alarm was to have been
delivered. If *time* is zero, no alarm is scheduled, and any scheduled alarm is
- canceled. If the return value is zero, no alarm is currently scheduled. (See
- the Unix man page :manpage:`alarm(2)`.)
+ canceled. If the return value is zero, no alarm is currently scheduled.
- .. availability:: Unix.
+ .. availability:: Unix. See the man page :manpage:`alarm(2)` for further
+ information.
.. function:: getsignal(signalnum)
.. function:: pause()
Cause the process to sleep until a signal is received; the appropriate handler
- will then be called. Returns nothing. Not on Windows. (See the Unix man page
- :manpage:`signal(2)`.)
+ will then be called. Returns nothing.
+
+ .. availability:: Unix. See the man page :manpage:`signal(2)` for further
+ information.
See also :func:`sigwait`, :func:`sigwaitinfo`, :func:`sigtimedwait` and
:func:`sigpending`.
If *signalnum* is 0, then no signal is sent, but error checking is still
performed; this can be used to check if the target thread is still running.
- .. availability:: Unix (see the man page :manpage:`pthread_kill(3)` for further
- information).
+ .. availability:: Unix. See the man page :manpage:`pthread_kill(3)` for further
+ information.
See also :func:`os.kill`.
For example, ``signal.pthread_sigmask(signal.SIG_BLOCK, [])`` reads the
signal mask of the calling thread.
- .. availability:: Unix. See the man page :manpage:`sigprocmask(3)` and
+ .. availability:: Unix. See the man page :manpage:`sigprocmask(3)` and
:manpage:`pthread_sigmask(3)` for further information.
See also :func:`pause`, :func:`sigpending` and :func:`sigwait`.
calls will be restarted when interrupted by signal *signalnum*, otherwise
system calls will be interrupted. Returns nothing.
- .. availability:: Unix (see the man page :manpage:`siginterrupt(3)`
- for further information).
+ .. availability:: Unix. See the man page :manpage:`siginterrupt(3)`
+ for further information.
Note that installing a signal handler with :func:`signal` will reset the
restart behaviour to interruptible by implicitly calling
be a callable Python object taking two arguments (see below), or one of the
special values :const:`signal.SIG_IGN` or :const:`signal.SIG_DFL`. The previous
signal handler will be returned (see the description of :func:`getsignal`
- above). (See the Unix man page :manpage:`signal(2)`.)
+ above). (See the Unix man page :manpage:`signal(2)` for further information.)
When threads are enabled, this function can only be called from the main thread;
attempting to call it from other threads will cause a :exc:`ValueError`
thread (i.e., the signals which have been raised while blocked). Return the
set of the pending signals.
- .. availability:: Unix (see the man page :manpage:`sigpending(2)` for further
- information).
+ .. availability:: Unix. See the man page :manpage:`sigpending(2)` for further
+ information.
See also :func:`pause`, :func:`pthread_sigmask` and :func:`sigwait`.
signals specified in the signal set *sigset*. The function accepts the signal
(removes it from the pending list of signals), and returns the signal number.
- .. availability:: Unix (see the man page :manpage:`sigwait(3)` for further
- information).
+ .. availability:: Unix. See the man page :manpage:`sigwait(3)` for further
+ information.
See also :func:`pause`, :func:`pthread_sigmask`, :func:`sigpending`,
:func:`sigwaitinfo` and :func:`sigtimedwait`.
:attr:`si_errno`, :attr:`si_pid`, :attr:`si_uid`, :attr:`si_status`,
:attr:`si_band`.
- .. availability:: Unix (see the man page :manpage:`sigwaitinfo(2)` for further
- information).
+ .. availability:: Unix. See the man page :manpage:`sigwaitinfo(2)` for further
+ information.
See also :func:`pause`, :func:`sigwait` and :func:`sigtimedwait`.
specifying a timeout. If *timeout* is specified as :const:`0`, a poll is
performed. Returns :const:`None` if a timeout occurs.
- .. availability:: Unix (see the man page :manpage:`sigtimedwait(2)` for further
- information).
+ .. availability:: Unix. See the man page :manpage:`sigtimedwait(2)` for further
+ information.
See also :func:`pause`, :func:`sigwait` and :func:`sigwaitinfo`.
.. data:: VERIFY_CRL_CHECK_LEAF
Possible value for :attr:`SSLContext.verify_flags`. In this mode, only the
- peer cert is check but non of the intermediate CA certificates. The mode
+ peer cert is checked but none of the intermediate CA certificates. The mode
requires a valid CRL that is signed by the peer cert's issuer (its direct
- ancestor CA). If no proper has been loaded
+ ancestor CA). If no proper CRL has has been loaded with
:attr:`SSLContext.load_verify_locations`, validation will fail.
.. versionadded:: 3.4
.. data:: PROTOCOL_SSLv23
- Alias for data:`PROTOCOL_TLS`.
+ Alias for :data:`PROTOCOL_TLS`.
.. deprecated:: 3.6
.. attribute:: SSLContext.sslsocket_class
- The return type of :meth:`SSLContext.wrap_sockets`, defaults to
+ The return type of :meth:`SSLContext.wrap_socket`, defaults to
:class:`SSLSocket`. The attribute can be overridden on instance of class
in order to return a custom subclass of :class:`SSLSocket`.
server_hostname=None, session=None)
Wrap the BIO objects *incoming* and *outgoing* and return an instance of
- attr:`SSLContext.sslobject_class` (default :class:`SSLObject`). The SSL
+ :attr:`SSLContext.sslobject_class` (default :class:`SSLObject`). The SSL
routines will read input data from the incoming BIO and write data to the
outgoing BIO.
:meth:`~SSLContext.wrap_socket` in order to match the hostname. Enabling
hostname checking automatically sets :attr:`~SSLContext.verify_mode` from
:data:`CERT_NONE` to :data:`CERT_REQUIRED`. It cannot be set back to
- :data:`CERT_NONE` as long as hostname checking is enabled.
+ :data:`CERT_NONE` as long as hostname checking is enabled. The
+ :data:`PROTOCOL_TLS_CLIENT` protocol enables hostname checking by default.
+ With other protocols, hostname checking must be enabled explicitly.
Example::
import socket, ssl
- context = ssl.SSLContext()
+ context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = True
context.load_default_certs()
a context from scratch (but beware that you might not get the settings
right)::
- >>> context = ssl.SSLContext()
- >>> context.verify_mode = ssl.CERT_REQUIRED
- >>> context.check_hostname = True
+ >>> context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
>>> context.load_verify_locations("/etc/ssl/certs/ca-bundle.crt")
(this snippet assumes your operating system places a bundle of all CA
certificates in ``/etc/ssl/certs/ca-bundle.crt``; if not, you'll get an
error and have to adjust the location)
+The :data:`PROTOCOL_TLS_CLIENT` protocol configures the context for cert
+validation and hostname verification. :attr:`~SSLContext.verify_mode` is
+set to :data:`CERT_REQUIRED` and :attr:`~SSLContext.check_hostname` is set
+to ``True``. All other protocols create SSL contexts with insecure defaults.
+
When you use the context to connect to a server, :const:`CERT_REQUIRED`
-validates the server certificate: it ensures that the server certificate
-was signed with one of the CA certificates, and checks the signature for
-correctness::
+and :attr:`~SSLContext.check_hostname` validate the server certificate: it
+ensures that the server certificate was signed with one of the CA
+certificates, checks the signature for correctness, and verifies other
+properties like validity and identity of the hostname::
>>> conn = context.wrap_socket(socket.socket(socket.AF_INET),
... server_hostname="www.python.org")
the same rule. [2]_ The constructors :func:`int`, :func:`float`, and
:func:`complex` can be used to produce numbers of a specific type.
-All numeric types (except complex) support the following operations, sorted by
-ascending priority (all numeric operations have a higher priority than
-comparison operations):
+All numeric types (except complex) support the following operations (for priorities of
+the operations, see :ref:`operator-summary`):
+---------------------+---------------------------------+---------+--------------------+
| Operation | Result | Notes | Full documentation |
.. method:: str.isspace()
Return true if there are only whitespace characters in the string and there is
- at least one character, false otherwise. Whitespace characters are those
- characters defined in the Unicode character database as "Other" or "Separator"
- and those with bidirectional property being one of "WS", "B", or "S".
+ at least one character, false otherwise.
+
+ A character is *whitespace* if in the Unicode character database
+ (see :mod:`unicodedata`), either its general category is ``Zs``
+ ("Separator, space"), or its bidirectional class is one of ``WS``,
+ ``B``, or ``S``.
+
.. method:: str.istitle()
>>> z.nbytes
48
- Cast 1D/unsigned char to 2D/unsigned long::
+ Cast 1D/unsigned long to 2D/unsigned long::
>>> buf = struct.pack("L"*6, *list(range(6)))
>>> x = memoryview(buf)
These are the operations that dictionaries support (and therefore, custom
mapping types should support too):
+ .. describe:: list(d)
+
+ Return a list of all the keys used in the dictionary *d*.
+
.. describe:: len(d)
Return the number of items in the dictionary *d*.
Return a new view of the dictionary's values. See the
:ref:`documentation of view objects <dict-views>`.
+ An equality comparison between one ``dict.values()`` view and another
+ will always return ``False``. This also applies when comparing
+ ``dict.values()`` to itself::
+
+ >>> d = {'a': 1}
+ >>> d.values() == d.values()
+ False
+
Dictionaries compare equal if and only if they have the same ``(key,
- value)`` pairs. Order comparisons ('<', '<=', '>=', '>') raise
+ value)`` pairs (regardless of ordering). Order comparisons ('<', '<=', '>=', '>') raise
:exc:`TypeError`.
Dictionaries preserve insertion order. Note that updating a key does not
| | with presentation type ``'e'`` and precision ``p-1``. |
| | In both cases insignificant trailing zeros are removed |
| | from the significand, and the decimal point is also |
- | | removed if there are no remaining digits following it. |
+ | | removed if there are no remaining digits following it, |
+ | | unless the ``'#'`` option is used. |
| | |
| | Positive and negative infinity, positive and negative |
| | zero, and nans, are formatted as ``inf``, ``-inf``, |
+--------+--------------------------+--------------------+----------------+------------+
| ``c`` | :c:type:`char` | bytes of length 1 | 1 | |
+--------+--------------------------+--------------------+----------------+------------+
-| ``b`` | :c:type:`signed char` | integer | 1 | \(1),\(3) |
+| ``b`` | :c:type:`signed char` | integer | 1 | \(1), \(2) |
+--------+--------------------------+--------------------+----------------+------------+
-| ``B`` | :c:type:`unsigned char` | integer | 1 | \(3) |
+| ``B`` | :c:type:`unsigned char` | integer | 1 | \(2) |
+--------+--------------------------+--------------------+----------------+------------+
| ``?`` | :c:type:`_Bool` | bool | 1 | \(1) |
+--------+--------------------------+--------------------+----------------+------------+
-| ``h`` | :c:type:`short` | integer | 2 | \(3) |
+| ``h`` | :c:type:`short` | integer | 2 | \(2) |
+--------+--------------------------+--------------------+----------------+------------+
-| ``H`` | :c:type:`unsigned short` | integer | 2 | \(3) |
+| ``H`` | :c:type:`unsigned short` | integer | 2 | \(2) |
+--------+--------------------------+--------------------+----------------+------------+
-| ``i`` | :c:type:`int` | integer | 4 | \(3) |
+| ``i`` | :c:type:`int` | integer | 4 | \(2) |
+--------+--------------------------+--------------------+----------------+------------+
-| ``I`` | :c:type:`unsigned int` | integer | 4 | \(3) |
+| ``I`` | :c:type:`unsigned int` | integer | 4 | \(2) |
+--------+--------------------------+--------------------+----------------+------------+
-| ``l`` | :c:type:`long` | integer | 4 | \(3) |
+| ``l`` | :c:type:`long` | integer | 4 | \(2) |
+--------+--------------------------+--------------------+----------------+------------+
-| ``L`` | :c:type:`unsigned long` | integer | 4 | \(3) |
+| ``L`` | :c:type:`unsigned long` | integer | 4 | \(2) |
+--------+--------------------------+--------------------+----------------+------------+
-| ``q`` | :c:type:`long long` | integer | 8 | \(2), \(3) |
+| ``q`` | :c:type:`long long` | integer | 8 | \(2) |
+--------+--------------------------+--------------------+----------------+------------+
-| ``Q`` | :c:type:`unsigned long | integer | 8 | \(2), \(3) |
+| ``Q`` | :c:type:`unsigned long | integer | 8 | \(2) |
| | long` | | | |
+--------+--------------------------+--------------------+----------------+------------+
-| ``n`` | :c:type:`ssize_t` | integer | | \(4) |
+| ``n`` | :c:type:`ssize_t` | integer | | \(3) |
+--------+--------------------------+--------------------+----------------+------------+
-| ``N`` | :c:type:`size_t` | integer | | \(4) |
+| ``N`` | :c:type:`size_t` | integer | | \(3) |
+--------+--------------------------+--------------------+----------------+------------+
-| ``e`` | \(7) | float | 2 | \(5) |
+| ``e`` | \(6) | float | 2 | \(4) |
+--------+--------------------------+--------------------+----------------+------------+
-| ``f`` | :c:type:`float` | float | 4 | \(5) |
+| ``f`` | :c:type:`float` | float | 4 | \(4) |
+--------+--------------------------+--------------------+----------------+------------+
-| ``d`` | :c:type:`double` | float | 8 | \(5) |
+| ``d`` | :c:type:`double` | float | 8 | \(4) |
+--------+--------------------------+--------------------+----------------+------------+
| ``s`` | :c:type:`char[]` | bytes | | |
+--------+--------------------------+--------------------+----------------+------------+
| ``p`` | :c:type:`char[]` | bytes | | |
+--------+--------------------------+--------------------+----------------+------------+
-| ``P`` | :c:type:`void \*` | integer | | \(6) |
+| ``P`` | :c:type:`void \*` | integer | | \(5) |
+--------+--------------------------+--------------------+----------------+------------+
.. versionchanged:: 3.3
standard mode, it is always represented by one byte.
(2)
- The ``'q'`` and ``'Q'`` conversion codes are available in native mode only if
- the platform C compiler supports C :c:type:`long long`, or, on Windows,
- :c:type:`__int64`. They are always available in standard modes.
-
-(3)
When attempting to pack a non-integer using any of the integer conversion
codes, if the non-integer has a :meth:`__index__` method then that method is
called to convert the argument to an integer before packing.
.. versionchanged:: 3.2
Use of the :meth:`__index__` method for non-integers is new in 3.2.
-(4)
+(3)
The ``'n'`` and ``'N'`` conversion codes are only available for the native
size (selected as the default or with the ``'@'`` byte order character).
For the standard size, you can use whichever of the other integer formats
fits your application.
-(5)
+(4)
For the ``'f'``, ``'d'`` and ``'e'`` conversion codes, the packed
representation uses the IEEE 754 binary32, binary64 or binary16 format (for
``'f'``, ``'d'`` or ``'e'`` respectively), regardless of the floating-point
format used by the platform.
-(6)
+(5)
The ``'P'`` format character is only available for the native byte ordering
(selected as the default or with the ``'@'`` byte order character). The byte
order character ``'='`` chooses to use little- or big-endian ordering based
on the host system. The struct module does not interpret this as native
ordering, so the ``'P'`` format is not available.
-(7)
+(6)
The IEEE 754 binary16 "half precision" type was introduced in the 2008
revision of the `IEEE 754 standard <ieee 754 standard_>`_. It has a sign
bit, a 5-bit exponent and 11-bit precision (with 10 bits explicitly stored),
.. data:: flags
- The :term:`struct sequence` *flags* exposes the status of command line
+ The :term:`named tuple` *flags* exposes the status of command line
flags. The attributes are read only.
============================= =============================
.. data:: float_info
- A :term:`struct sequence` holding information about the float type. It
+ A :term:`named tuple` holding information about the float type. It
contains low level information about the precision and internal
representation. The values correspond to the various floating-point
constants defined in the standard header file :file:`float.h` for the 'C'
.. data:: hash_info
- A :term:`struct sequence` giving parameters of the numeric hash
+ A :term:`named tuple` giving parameters of the numeric hash
implementation. For more details about hashing of numeric types, see
:ref:`numeric-hash`.
This is called ``hexversion`` since it only really looks meaningful when viewed
as the result of passing it to the built-in :func:`hex` function. The
- :term:`struct sequence` :data:`sys.version_info` may be used for a more
+ :term:`named tuple` :data:`sys.version_info` may be used for a more
human-friendly encoding of the same information.
More details of ``hexversion`` can be found at :ref:`apiabiversion`.
.. versionadded:: 3.3
+ .. note::
+
+ The addition of new required attributes must go through the normal PEP
+ process. See :pep:`421` for more information.
.. data:: int_info
- A :term:`struct sequence` that holds information about Python's internal
+ A :term:`named tuple` that holds information about Python's internal
representation of integers. The attributes are read only.
.. tabularcolumns:: |l|L|
The trace function is invoked (with *event* set to ``'call'``) whenever a new
local scope is entered; it should return a reference to a local trace
- function to be used that scope, or ``None`` if the scope shouldn't be traced.
+ function to be used for the new scope, or ``None`` if the scope shouldn't be
+ traced.
The local trace function should return a reference to itself (or to another
function for further tracing in that scope), or ``None`` to turn off tracing
Note that as an exception is propagated down the chain of callers, an
``'exception'`` event is generated at each level.
+ For more fine-grained usage, it's possible to set a trace function by
+ assigning ``frame.f_trace = tracefunc`` explicitly, rather than relying on
+ it being set indirectly via the return value from an already installed
+ trace function. This is also required for activating the trace function on
+ the current frame, which :func:`settrace` doesn't do. Note that in order
+ for this to work, a global tracing function must have been installed
+ with :func:`settrace` in order to enable the runtime tracing machinery,
+ but it doesn't need to be the same tracing function (e.g. it could be a
+ low overhead tracing function that simply returns ``None`` to disable
+ itself immediately on each frame).
+
For more information on code and frame objects, refer to :ref:`types`.
.. impl-detail::
.. data:: thread_info
- A :term:`struct sequence` holding information about the thread
+ A :term:`named tuple` holding information about the thread
implementation.
.. tabularcolumns:: |l|p{0.7\linewidth}|
.. class:: Telnet(host=None, port=0[, timeout])
:class:`Telnet` represents a connection to a Telnet server. The instance is
- initially not connected by default; the :meth:`open` method must be used to
+ initially not connected by default; the :meth:`~Telnet.open` method must be used to
establish a connection. Alternatively, the host name and optional port
number can be passed to the constructor too, in which case the connection to
the server will be established before the constructor returns. The optional
*suffix* and *prefix* now accept and default to ``None`` to cause
an appropriate default value to be used.
+ .. versionchanged:: 3.6
+ The *dir* parameter now accepts a :term:`path-like object`.
+
.. function:: mkdtemp(suffix=None, prefix=None, dir=None)
*suffix* and *prefix* now accept and default to ``None`` to cause
an appropriate default value to be used.
+ .. versionchanged:: 3.6
+ The *dir* parameter now accepts a :term:`path-like object`.
+
.. function:: gettempdir()
Check for presence of docstrings.
+
.. data:: TEST_HTTP_URL
Define the URL of a dedicated HTTP server for the network tests.
+.. data:: ALWAYS_EQ
+
+ Object that is equal to anything. Used to test mixed type comparison.
+
+
+.. data:: LARGEST
+
+ Object that is greater than anything (except itself).
+ Used to test mixed type comparison.
+
+
+.. data:: SMALLEST
+
+ Object that is less than anything (except itself).
+ Used to test mixed type comparison.
+
The :mod:`test.support` module defines the following functions:
equal: the lines ``" hello"`` and ``"\thello"`` are considered to have no
common leading whitespace.
+ Lines containing only whitespace are ignored in the input and normalized to a
+ single newline character in the output.
+
For example::
def test():
.. function:: time_ns() -> int
- Similar to :func:`time` but returns time as an integer number of nanoseconds
+ Similar to :func:`~time.time` but returns time as an integer number of nanoseconds
since the epoch_.
.. versionadded:: 3.7
.. note::
- The typing module has been included in the standard library on a
- :term:`provisional basis <provisional api>`. New features might
- be added and API may change even between minor releases if deemed
- necessary by the core developers.
+ The Python runtime does not enforce function and variable type annotations.
+ They can be used by third party tools such as type checkers, IDEs, linters,
+ etc.
--------------
single type parameter ``T`` . This also makes ``T`` valid as a type within the
class body.
-The :class:`Generic` base class uses a metaclass that defines
-:meth:`__getitem__` so that ``LoggedVar[t]`` is valid as a type::
+The :class:`Generic` base class defines :meth:`__class_getitem__` so that
+``LoggedVar[t]`` is valid as a type::
from typing import Iterable
def inproduct(v: Vec[T]) -> T: # Same as Iterable[Tuple[T, T]]
return sum(x*y for x, y in v)
-The metaclass used by :class:`Generic` is a subclass of :class:`abc.ABCMeta`.
-A generic class can be an ABC by including abstract methods or properties,
-and generic classes can also have ABCs as base classes without a metaclass
+.. versionchanged:: 3.7
+ :class:`Generic` no longer has a custom metaclass.
+
+A user-defined generic class can have ABCs as base classes without a metaclass
conflict. Generic metaclasses are not supported. The outcome of parameterizing
generics is cached, and most types in the typing module are hashable and
comparable for equality.
.. versionchanged:: 3.6.1
Added support for default values, methods, and docstrings.
+.. class:: ForwardRef
+
+ A class used for internal typing representation of string forward references.
+ For example, ``List["SomeClass"]`` is implicitly transformed into
+ ``List[ForwardRef("SomeClass")]``. This class should not be instantiated by
+ a user, but may be used by introspection tools.
+
.. function:: NewType(typ)
A helper function to indicate a distinct types to a typechecker,
.. data:: Tuple
Tuple type; ``Tuple[X, Y]`` is the type of a tuple of two items
- with the first item of type X and the second of type Y.
+ with the first item of type X and the second of type Y. The type of
+ the empty tuple can be written as ``Tuple[()]``.
Example: ``Tuple[T1, T2]`` is a tuple of two elements corresponding
to type variables T1 and T2. ``Tuple[int, float, str]`` is a tuple
The module uses the same names and symbols as defined by Unicode
Standard Annex #44, `"Unicode Character Database"
-<http://www.unicode.org/reports/tr44/tr44-6.html>`_. It defines the
+<https://www.unicode.org/reports/tr44/>`_. It defines the
following functions:
used to set attributes on the mock after it is created. See the
:meth:`configure_mock` method for details.
- .. method:: assert_called(*args, **kwargs)
+ .. method:: assert_called()
Assert that the mock was called at least once.
.. versionadded:: 3.6
- .. method:: assert_called_once(*args, **kwargs)
+ .. method:: assert_called_once()
Assert that the mock was called exactly once.
is not None, ``Content-Type: application/x-www-form-urlencoded`` will
be added as a default.
- The final two arguments are only of interest for correct handling
+ The next two arguments are only of interest for correct handling
of third-party HTTP cookies:
*origin_req_host* should be the request-host of the origin
A virtual environment is a directory tree which contains Python executable
files and other files which indicate that it is a virtual environment.
- Common installation tools such as ``Setuptools`` and ``pip`` work as
+ Common installation tools such as setuptools_ and pip_ work as
expected with virtual environments. In other words, when a virtual
environment is active, they install Python packages into the virtual
environment without needing to be told to do so explicitly.
Python installation).
When a virtual environment is active, any options that change the
- installation path will be ignored from all distutils configuration files to
- prevent projects being inadvertently installed outside of the virtual
- environment.
+ installation path will be ignored from all :mod:`distutils` configuration
+ files to prevent projects being inadvertently installed outside of the
+ virtual environment.
When working in a command shell, users can make a virtual environment active
by running an ``activate`` script in the virtual environment's executables
- directory (the precise filename is shell-dependent), which prepends the
- virtual environment's directory for executables to the ``PATH`` environment
- variable for the running shell. There should be no need in other
- circumstances to activate a virtual environment—scripts installed into
- virtual environments have a "shebang" line which points to the virtual
- environment's Python interpreter. This means that the script will run with
- that interpreter regardless of the value of ``PATH``. On Windows, "shebang"
- line processing is supported if you have the Python Launcher for Windows
- installed (this was added to Python in 3.3 - see :pep:`397` for more
- details). Thus, double-clicking an installed script in a Windows Explorer
- window should run the script with the correct interpreter without there
- needing to be any reference to its virtual environment in ``PATH``.
+ directory (the precise filename and command to use the file is
+ shell-dependent), which prepends the virtual environment's directory for
+ executables to the ``PATH`` environment variable for the running shell. There
+ should be no need in other circumstances to activate a virtual
+ environment; scripts installed into virtual environments have a "shebang"
+ line which points to the virtual environment's Python interpreter. This means
+ that the script will run with that interpreter regardless of the value of
+ ``PATH``. On Windows, "shebang" line processing is supported if you have the
+ Python Launcher for Windows installed (this was added to Python in 3.3 - see
+ :pep:`397` for more details). Thus, double-clicking an installed script in a
+ Windows Explorer window should run the script with the correct interpreter
+ without there needing to be any reference to its virtual environment in
+ ``PATH``.
.. _venv-api:
Added the ``prompt`` parameter
Creators of third-party virtual environment tools will be free to use the
- provided ``EnvBuilder`` class as a base class.
+ provided :class:`EnvBuilder` class as a base class.
The returned env-builder is an object which has a method, ``create``:
.. method:: create(env_dir)
- This method takes as required argument the path (absolute or relative to
- the current directory) of the target directory which is to contain the
+ Create a virtual environment by specifying the target directory
+ (absolute or relative to the current directory) which is to contain the
virtual environment. The ``create`` method will either create the
environment in the specified directory, or raise an appropriate
exception.
- The ``create`` method of the ``EnvBuilder`` class illustrates the hooks
- available for subclass customization::
+ The ``create`` method of the :class:`EnvBuilder` class illustrates the
+ hooks available for subclass customization::
def create(self, env_dir):
"""
This script is also available for download `online
<https://gist.github.com/vsajip/4673395>`_.
+
+
+.. _setuptools: https://pypi.org/project/setuptools/
+.. _pip: https://pypi.org/project/pip/
*key* is an already open key, or one of the predefined :ref:`HKEY_* constants
<hkey-constants>`.
- Will generally raise :exc:`NotImplemented` if executed on a 32-bit operating
+ Will generally raise :exc:`NotImplementedError` if executed on a 32-bit operating
system.
If the key is not on the reflection list, the function succeeds but has no
*key* is an already open key, or one of the predefined :ref:`HKEY_* constants
<hkey-constants>`.
- Will generally raise :exc:`NotImplemented` if executed on a 32-bit operating
+ Will generally raise :exc:`NotImplementedError` if executed on a 32-bit operating
system.
Restoring reflection for a key does not affect reflection of any subkeys.
Returns ``True`` if reflection is disabled.
- Will generally raise :exc:`NotImplemented` if executed on a 32-bit
+ Will generally raise :exc:`NotImplementedError` if executed on a 32-bit
operating system.
:class:`Element` instance and a dictionary.
+.. _elementtree-xinclude:
+
+XInclude support
+----------------
+
+This module provides limited support for
+`XInclude directives <https://www.w3.org/TR/xinclude/>`_, via the :mod:`xml.etree.ElementInclude` helper module. This module can be used to insert subtrees and text strings into element trees, based on information in the tree.
+
+Example
+^^^^^^^
+
+Here's an example that demonstrates use of the XInclude module. To include an XML document in the current document, use the ``{http://www.w3.org/2001/XInclude}include`` element and set the **parse** attribute to ``"xml"``, and use the **href** attribute to specify the document to include.
+
+.. code-block:: xml
+
+ <?xml version="1.0"?>
+ <document xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="source.xml" parse="xml" />
+ </document>
+
+By default, the **href** attribute is treated as a file name. You can use custom loaders to override this behaviour. Also note that the standard helper does not support XPointer syntax.
+
+To process this file, load it as usual, and pass the root element to the :mod:`xml.etree.ElementTree` module:
+
+.. code-block:: python
+
+ from xml.etree import ElementTree, ElementInclude
+
+ tree = ElementTree.parse("document.xml")
+ root = tree.getroot()
+
+ ElementInclude.include(root)
+
+The ElementInclude module replaces the ``{http://www.w3.org/2001/XInclude}include`` element with the root element from the **source.xml** document. The result might look something like this:
+
+.. code-block:: xml
+
+ <document xmlns:xi="http://www.w3.org/2001/XInclude">
+ <para>This is a paragraph.</para>
+ </document>
+
+If the **parse** attribute is omitted, it defaults to "xml". The href attribute is required.
+
+To include a text document, use the ``{http://www.w3.org/2001/XInclude}include`` element, and set the **parse** attribute to "text":
+
+.. code-block:: xml
+
+ <?xml version="1.0"?>
+ <document xmlns:xi="http://www.w3.org/2001/XInclude">
+ Copyright (c) <xi:include href="year.txt" parse="text" />.
+ </document>
+
+The result might look something like:
+
+.. code-block:: xml
+
+ <document xmlns:xi="http://www.w3.org/2001/XInclude">
+ Copyright (c) 2003.
+ </document>
+
+Reference
+---------
+
+.. _elementinclude-functions:
+
+Functions
+^^^^^^^^^
+
+.. function:: xml.etree.ElementInclude.default_loader( href, parse, encoding=None)
+
+ Default loader. This default loader reads an included resource from disk. *href* is a URL.
+ *parse* is for parse mode either "xml" or "text". *encoding*
+ is an optional text encoding. If not given, encoding is ``utf-8``. Returns the
+ expanded resource. If the parse mode is ``"xml"``, this is an ElementTree
+ instance. If the parse mode is "text", this is a Unicode string. If the
+ loader fails, it can return None or raise an exception.
+
+
+.. function:: xml.etree.ElementInclude.include( elem, loader=None)
+
+ This function expands XInclude directives. *elem* is the root element. *loader* is
+ an optional resource loader. If omitted, it defaults to :func:`default_loader`.
+ If given, it should be a callable that implements the same interface as
+ :func:`default_loader`. Returns the expanded resource. If the parse mode is
+ ``"xml"``, this is an ElementTree instance. If the parse mode is "text",
+ this is a Unicode string. If the loader fails, it can return None or
+ raise an exception.
+
+
.. _elementtree-element-objects:
Element Objects
Called to implement :func:`operator.length_hint`. Should return an estimated
length for the object (which may be greater or less than the actual length).
- The length must be an integer ``>=`` 0. This method is purely an
+ The length must be an integer ``>=`` 0. The return value may also be
+ :const:`NotImplemented`, which is treated the same as if the
+ ``__length_hint__`` method didn't exist at all. This method is purely an
optimization and is never required for correctness.
.. versionadded:: 3.4
tuple may or may not yield the same object).
.. index::
- single: comma; tuple display
- pair: tuple; display
- single: , (comma); tuple display
+ single: comma
+ single: , (comma)
Note that tuples are not formed by the parentheses, but rather by use of the
comma operator. The exception is the empty tuple, for which parentheses *are*
| ``x[index]``, ``x[index:index]``, | Subscription, slicing, |
| ``x(arguments...)``, ``x.attribute`` | call, attribute reference |
+-----------------------------------------------+-------------------------------------+
-| ``(expressions...)``, | Binding or tuple display, |
+| ``(expressions...)``, | Binding or parenthesized |
+| | expression, |
| ``[expressions...]``, | list display, |
| ``{key: value...}``, | dictionary display, |
| ``{expressions...}`` | set display |
def finish(self):
unused_rules = [rule for rule in self.rules if not rule.used]
if unused_rules:
- self.warn('Found %s/%s unused rules:' %
- (len(unused_rules), len(self.rules)))
- for rule in unused_rules:
- self.logger.info(repr(rule))
+ self.logger.warning(
+ 'Found %s/%s unused rules: %s' % (
+ len(unused_rules), len(self.rules),
+ ''.join(repr(rule) for rule in unused_rules),
+ )
+ )
return
def check_issue(self, line, lineno, issue):
self.any_issue = True
self.write_log_entry(lineno, issue, text)
if py3:
- self.warn('[%s:%d] "%s" found in "%-.120s"' %
- (self.docname, lineno, issue, text))
+ self.logger.warning('[%s:%d] "%s" found in "%-.120s"' %
+ (self.docname, lineno, issue, text))
else:
- self.warn('[%s:%d] "%s" found in "%-.120s"' % (
- self.docname.encode(sys.getdefaultencoding(),'replace'),
- lineno,
- issue.encode(sys.getdefaultencoding(),'replace'),
- text.strip().encode(sys.getdefaultencoding(),'replace')))
+ self.logger.warning(
+ '[%s:%d] "%s" found in "%-.120s"' % (
+ self.docname.encode(sys.getdefaultencoding(),'replace'),
+ lineno,
+ issue.encode(sys.getdefaultencoding(),'replace'),
+ text.strip().encode(sys.getdefaultencoding(),'replace')))
self.app.statuscode = 1
def write_log_entry(self, lineno, issue, text):
library/xml.etree.elementtree,,:actor,"for actor in root.findall('real_person:actor', ns):"
library/xml.etree.elementtree,,:name,"name = actor.find('real_person:name', ns)"
library/xml.etree.elementtree,,:character,"for char in actor.findall('role:character', ns):"
+library/xml.etree.elementtree,,:xi,<document xmlns:xi="http://www.w3.org/2001/XInclude">
+library/xml.etree.elementtree,,:include, <xi:include href="source.xml" parse="xml" />
+library/xml.etree.elementtree,,:include, Copyright (c) <xi:include href="year.txt" parse="text" />.
library/zipapp,,:main,"$ python -m zipapp myapp -m ""myapp:main"""
library/zipapp,,:fn,"pkg.mod:fn"
library/zipapp,,:callable,"pkg.module:callable"
whatsnew/changelog,,::,error::BytesWarning
whatsnew/changelog,,::,default::BytesWarning
whatsnew/changelog,,::,default::DeprecationWarning
+library/re,,`,"`"
<h3>{% trans %}Docs by version{% endtrans %}</h3>
<ul>
<li><a href="https://docs.python.org/3.9/">{% trans %}Python 3.9 (in development){% endtrans %}</a></li>
- <li><a href="https://docs.python.org/3.8/">{% trans %}Python 3.8 (pre-release){% endtrans %}</a></li>
+ <li><a href="https://docs.python.org/3.8/">{% trans %}Python 3.8 (stable){% endtrans %}</a></li>
<li><a href="https://docs.python.org/3.7/">{% trans %}Python 3.7 (stable){% endtrans %}</a></li>
<li><a href="https://docs.python.org/3.6/">{% trans %}Python 3.6 (security-fixes){% endtrans %}</a></li>
<li><a href="https://docs.python.org/3.5/">{% trans %}Python 3.5 (security-fixes){% endtrans %}</a></li>
More Control Flow Tools
***********************
-Besides the :keyword:`while` statement just introduced, Python knows the usual
-control flow statements known from other languages, with some twists.
+Besides the :keyword:`while` statement just introduced, Python uses the usual
+flow control statements known from other languages, with some twists.
.. _tut-if:
bracketing constructs: ``a = f(1, 2) + g(3, 4)``.
* Name your classes and functions consistently; the convention is to use
- ``CamelCase`` for classes and ``lower_case_with_underscores`` for functions
+ ``UpperCamelCase`` for classes and ``lowercase_with_underscores`` for functions
and methods. Always use ``self`` as the name for the first method argument
(see :ref:`tut-firstclasses` for more on classes and methods).
File "<stdin>", line 2, in <module>
KeyboardInterrupt
-A *finally clause* is always executed before leaving the :keyword:`try`
-statement, whether an exception has occurred or not. When an exception has
-occurred in the :keyword:`!try` clause and has not been handled by an
-:keyword:`except` clause (or it has occurred in an :keyword:`!except` or
-:keyword:`!else` clause), it is re-raised after the :keyword:`finally` clause has
-been executed. The :keyword:`!finally` clause is also executed "on the way out"
-when any other clause of the :keyword:`!try` statement is left via a
-:keyword:`break`, :keyword:`continue` or :keyword:`return` statement. A more
-complicated example::
+If a :keyword:`finally` clause is present, the :keyword:`finally` clause will execute as the last task before the :keyword:`try` statement completes. The :keyword:`finally` clause runs whether or not the :keyword:`try` statement produces an exception. The following points discuss more complex cases when an exception occurs:
+
+* If an exception occurs during execution of the :keyword:`!try` clause, the exception may be handled by an :keyword:`except` clause. If the exception is not handled by an :keyword:`except` clause, the exception is re-raised after the :keyword:`!finally` clause has been executed.
+
+* An exception could occur during execution of an :keyword:`!except` or :keyword:`!else` clause. Again, the exception is re-raised after the :keyword:`!finally` clause has been executed.
+
+* If the :keyword:`!try` statement reaches a :keyword:`break`, :keyword:`continue` or :keyword:`return` statement, the :keyword:`finally` clause will execute just prior to the :keyword:`break`, :keyword:`continue` or :keyword:`return` statement's execution.
+
+* If a :keyword:`finally` clause includes a :keyword:`return` statement, the :keyword:`finally` clause's :keyword:`return` statement will execute before, and instead of, the :keyword:`return` statement in a :keyword:`try` clause.
+
+For example::
+
+ >>> def bool_return():
+ ... try:
+ ... return True
+ ... finally:
+ ... return False
+ ...
+ >>> bool_return()
+ False
+
+A more complicated example::
>>> def divide(x, y):
... try:
data and returns it as a string (in text mode) or bytes object (in binary mode).
*size* is an optional numeric argument. When *size* is omitted or negative, the
entire contents of the file will be read and returned; it's your problem if the
-file is twice as large as your machine's memory. Otherwise, at most *size* bytes
-are read and returned.
+file is twice as large as your machine's memory. Otherwise, at most *size*
+characters (in text mode) or *size* bytes (in binary mode) are read and returned.
If the end of the file has been reached, ``f.read()`` will return an empty
string (``''``). ::
represented as number of bytes from the beginning of the file when in binary mode and
an opaque number when in text mode.
-To change the file object's position, use ``f.seek(offset, from_what)``. The position is computed
+To change the file object's position, use ``f.seek(offset, whence)``. The position is computed
from adding *offset* to a reference point; the reference point is selected by
-the *from_what* argument. A *from_what* value of 0 measures from the beginning
+the *whence* argument. A *whence* value of 0 measures from the beginning
of the file, 1 uses the current file position, and 2 uses the end of the file as
-the reference point. *from_what* can be omitted and defaults to 0, using the
+the reference point. *whence* can be omitted and defaults to 0, using the
beginning of the file as the reference point. ::
>>> f = open('workfile', 'rb+')
following command: ``quit()``.
The interpreter's line-editing features include interactive editing, history
-substitution and code completion on systems that support readline. Perhaps the
-quickest check to see whether command line editing is supported is typing
-:kbd:`Control-P` to the first Python prompt you get. If it beeps, you have command
-line editing; see Appendix :ref:`tut-interacting` for an introduction to the
-keys. If nothing appears to happen, or if ``^P`` is echoed, command line
-editing isn't available; you'll only be able to use backspace to remove
-characters from the current line.
+substitution and code completion on systems that support the `GNU Readline
+<https://tiswww.case.edu/php/chet/readline/rltop.html>`_ library.
+Perhaps the quickest check to see whether command line editing is supported is
+typing :kbd:`Control-P` to the first Python prompt you get. If it beeps, you
+have command line editing; see Appendix :ref:`tut-interacting` for an
+introduction to the keys. If nothing appears to happen, or if ``^P`` is
+echoed, command line editing isn't available; you'll only be able to use
+backspace to remove characters from the current line.
The interpreter operates somewhat like the Unix shell: when called with standard
input connected to a tty device, it reads and executes commands interactively;
>>> print(sys.argv)
['demo.py', 'one', 'two', 'three']
-The :mod:`getopt` module processes *sys.argv* using the conventions of the Unix
-:func:`getopt` function. More powerful and flexible command line processing is
-provided by the :mod:`argparse` module.
-
+The :mod:`argparse` module provides a mechanism to process command line arguments.
+It should always be preferred over directly processing ``sys.argv`` manually.
+
+Take, for example, the below snippet of code::
+
+ >>> import argparse
+ >>> from getpass import getuser
+ >>> parser = argparse.ArgumentParser(description='An argparse example.')
+ >>> parser.add_argument('name', nargs='?', default=getuser(), help='The name of someone to greet.')
+ >>> parser.add_argument('--verbose', '-v', action='count')
+ >>> args = parser.parse_args()
+ >>> greeting = ["Hi", "Hello", "Greetings! its very nice to meet you"][args.verbose % 3]
+ >>> print(f'{greeting}, {args.name}')
+ >>> if not args.verbose:
+ >>> print('Try running this again with multiple "-v" flags!')
.. _tut-stderr:
first element will be set to ``"-m"``). As with the :option:`-c` option,
the current directory will be added to the start of :data:`sys.path`.
+ :option:`-I` option can be used to run the script in isolated mode where
+ :data:`sys.path` contains neither the current directory nor the user's
+ site-packages directory. All :envvar:`PYTHON*` environment variables are
+ ignored, too.
+
Many standard library modules contain code that is invoked on their execution
as a script. An example is the :mod:`timeit` module::
.. versionchanged:: 3.4
namespace packages are also supported
+.. _cmdarg-dash:
.. describe:: -
:data:`sys.path`.
+.. _cmdarg-script:
+
.. describe:: <script>
Execute the Python code contained in *script*, which must be a filesystem
added to the start of :data:`sys.path` and the ``__main__.py`` file in
that location is executed as the :mod:`__main__` module.
+ :option:`-I` option can be used to run the script in isolated mode where
+ :data:`sys.path` contains neither the script's directory nor the user's
+ site-packages directory. All :envvar:`PYTHON*` environment variables are
+ ignored, too.
+
.. seealso::
:func:`runpy.run_path`
Equivalent functionality directly available to Python code
--- /dev/null
+.. highlight:: none
+
+.. _editors:
+
+******************
+ Editors and IDEs
+******************
+
+There are a number of IDEs that support Python programming language.
+Many editors and IDEs provide syntax highlighting, debugging tools, and :pep:`8` checks.
+
+Please go to `Python Editors <https://wiki.python.org/moin/PythonEditors>`_ and
+`Integrated Development Environments <https://wiki.python.org/moin/IntegratedDevelopmentEnvironments>`_
+for a comprehensive list.
unix.rst
windows.rst
mac.rst
+ editors.rst
``/usr/bin/python3`` as the interpreter path.
To use shell commands in your Python scripts, look at the :mod:`subprocess` module.
-
-
-Editors and IDEs
-================
-
-There are a number of IDEs that support Python programming language.
-Many editors and IDEs provide syntax highlighting, debugging tools, and :pep:`8` checks.
-
-Please go to `Python Editors <https://wiki.python.org/moin/PythonEditors>`_ and
-`Integrated Development Environments <https://wiki.python.org/moin/IntegratedDevelopmentEnvironments>`_
-for a comprehensive list.
and run with the virtual environment's Python automatically.
You can deactivate a virtual environment by typing "deactivate" in your shell.
-The exact mechanism is platform-specific: for example, the Bash activation
-script defines a "deactivate" function, whereas on Windows there are separate
-scripts called ``deactivate.bat`` and ``Deactivate.ps1`` which are installed
-when the virtual environment is created.
+The exact mechanism is platform-specific and is an internal implementation
+detail (typically a script or shell function will be used).
.. versionadded:: 3.4
``fish`` and ``csh`` activation scripts.
sys
---
-The :mod:`sys` module has a new :data:`~sys.thread_info` :term:`struct
-sequence` holding information about the thread implementation
+The :mod:`sys` module has a new :data:`~sys.thread_info` :term:`named
+tuple` holding information about the thread implementation
(:issue:`11223`).
have a 64 bit data type. Any performance differences in comparison with the
older FNV algorithm are trivial.
-The PEP adds additional fields to the :attr:`sys.hash_info` struct sequence to
+The PEP adds additional fields to the :attr:`sys.hash_info` named tuple to
describe the hash algorithm in use by the currently executing binary. Otherwise,
the PEP does not alter any existing CPython APIs.
The changes above have been backported to 3.6 maintenance releases.
+NEW in 3.7.4:
+
+Add "Run Customized" to the Run menu to run a module with customized
+settings. Any command line arguments entered are added to sys.argv.
+They re-appear in the box for the next customized run. One can also
+suppress the normal Shell main module restart. (Contributed by Cheryl
+Sabella, Terry Jan Reedy, and others in :issue:`5680` and :issue:`37627`.)
+
+New in 3.7.5:
+
+Add optional line numbers for IDLE editor windows. Windows
+open without line numbers unless set otherwise in the General
+tab of the configuration dialog. Line numbers for an existing
+window are shown and hidden in the Options menu.
+(Contributed by Tal Einat and Saimadhav Heblikar in :issue:`17535`.)
+
importlib
---------
instead of a :class:`bytes` instance.
(Contributed by Victor Stinner in :issue:`21071`.)
+* :mod:`argparse` subparsers can now be made mandatory by passing ``required=True``
+ to :meth:`ArgumentParser.add_subparsers() <argparse.ArgumentParser.add_subparsers>`.
+ (Contributed by Anthony Sottile in :issue:`26510`.)
+
* :meth:`ast.literal_eval()` is now stricter. Addition and subtraction of
arbitrary numbers are no longer allowed.
(Contributed by Serhiy Storchaka in :issue:`31778`.)
/*--start constants--*/
#define PY_MAJOR_VERSION 3
#define PY_MINOR_VERSION 7
-#define PY_MICRO_VERSION 4
+#define PY_MICRO_VERSION 5
#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL
#define PY_RELEASE_SERIAL 0
/* Version as a string */
-#define PY_VERSION "3.7.4"
+#define PY_VERSION "3.7.5"
/*--end constants--*/
/* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2.
} \
} while(0)
-/* Py_SET_ERANGE_ON_OVERFLOW(x)
+/* Py_SET_ERANGE_IF_OVERFLOW(x)
* An alias of Py_SET_ERRNO_ON_MATH_ERROR for backward-compatibility.
*/
#define Py_SET_ERANGE_IF_OVERFLOW(X) Py_SET_ERRNO_ON_MATH_ERROR(X)
store a duration, and so indirectly a date (related to another date, like
UNIX epoch). */
typedef int64_t _PyTime_t;
-#define _PyTime_MIN PY_LLONG_MIN
-#define _PyTime_MAX PY_LLONG_MAX
+#define _PyTime_MIN INT64_MIN
+#define _PyTime_MAX INT64_MAX
typedef enum {
/* Round towards minus infinity (-inf).
inserts[start] += ' ['
else:
inserts[start] = '['
- inserts[end] = ']'
+ if end in inserts:
+ inserts[end] += ']'
+ else:
+ inserts[end] = ']'
else:
if start in inserts:
inserts[start] += ' ('
else:
inserts[start] = '('
- inserts[end] = ')'
+ if end in inserts:
+ inserts[end] += ')'
+ else:
+ inserts[end] = ')'
for i in range(start + 1, end):
inserts[i] = '|'
def dump(node, annotate_fields=True, include_attributes=False):
"""
- Return a formatted dump of the tree in *node*. This is mainly useful for
- debugging purposes. The returned string will show the names and the values
- for fields. This makes the code impossible to evaluate, so if evaluation is
- wanted *annotate_fields* must be set to False. Attributes such as line
+ Return a formatted dump of the tree in node. This is mainly useful for
+ debugging purposes. If annotate_fields is true (by default),
+ the returned string will show the names and the values for fields.
+ If annotate_fields is false, the result string will be more compact by
+ omitting unambiguous field names. Attributes such as line
numbers and column offsets are not dumped by default. If this is wanted,
- *include_attributes* can be set to True.
+ include_attributes can be set to true.
"""
def _format(node):
if isinstance(node, AST):
- fields = [(a, _format(b)) for a, b in iter_fields(node)]
- rv = '%s(%s' % (node.__class__.__name__, ', '.join(
- ('%s=%s' % field for field in fields)
- if annotate_fields else
- (b for a, b in fields)
- ))
+ args = []
+ keywords = annotate_fields
+ for field in node._fields:
+ try:
+ value = getattr(node, field)
+ except AttributeError:
+ keywords = True
+ else:
+ if keywords:
+ args.append('%s=%s' % (field, _format(value)))
+ else:
+ args.append(_format(value))
if include_attributes and node._attributes:
- rv += fields and ', ' or ' '
- rv += ', '.join('%s=%s' % (a, _format(getattr(node, a)))
- for a in node._attributes)
- return rv + ')'
+ for a in node._attributes:
+ try:
+ args.append('%s=%s' % (a, _format(getattr(node, a))))
+ except AttributeError:
+ pass
+ return '%s(%s)' % (node.__class__.__name__, ', '.join(args))
elif isinstance(node, list):
return '[%s]' % ', '.join(_format(x) for x in node)
return repr(node)
self._local = self._Local()
def get_event_loop(self):
- """Get the event loop.
+ """Get the event loop for the current context.
- This may be None or an instance of EventLoop.
+ Returns an instance of EventLoop or raises an exception.
"""
if (self._local._loop is None and
not self._local._set_called and
def run(main, *, debug=False):
- """Run a coroutine.
+ """Execute the coroutine and return the result.
This function runs the passed coroutine, taking care of
managing the asyncio event loop and finalizing asynchronous
self._fileno = pipe.fileno()
self._protocol = protocol
self._closing = False
+ self._paused = False
mode = os.fstat(self._fileno).st_mode
if not (stat.S_ISFIFO(mode) or
self._loop.call_soon(self._call_connection_lost, None)
def pause_reading(self):
+ if self._closing or self._paused:
+ return
+ self._paused = True
self._loop._remove_reader(self._fileno)
+ if self._loop.get_debug():
+ logger.debug("%r pauses reading", self)
def resume_reading(self):
+ if self._closing or not self._paused:
+ return
+ self._paused = False
self._loop._add_reader(self._fileno, self._read_ready)
+ if self._loop.get_debug():
+ logger.debug("%r resumes reading", self)
def set_protocol(self, protocol):
self._protocol = protocol
if maxlen and clen > maxlen:
raise ValueError('Maximum content length exceeded')
self.length = clen
- if self.limit is None and clen:
+ if self.limit is None and clen >= 0:
self.limit = clen
self.list = self.file = None
if 'content-length' in headers:
del headers['content-length']
+ limit = None if self.limit is None \
+ else self.limit - self.bytes_read
part = klass(self.fp, headers, ib, environ, keep_blank_values,
- strict_parsing,self.limit-self.bytes_read,
+ strict_parsing, limit,
self.encoding, self.errors, max_num_fields)
if max_num_fields is not None:
last_line_lfend = True
_read = 0
while 1:
- if _read >= self.limit:
+ if self.limit is not None and _read >= self.limit:
break
line = self.fp.readline(1<<16) # bytes
self.bytes_read += len(line)
obj = getattr(_collections_abc, name)
import warnings
warnings.warn("Using or importing the ABCs from 'collections' instead "
- "of from 'collections.abc' is deprecated, "
- "and in 3.8 it will stop working",
+ "of from 'collections.abc' is deprecated since Python 3.3,"
+ "and in 3.9 it will stop working",
DeprecationWarning, stacklevel=2)
globals()[name] = obj
return obj
'__slots__': (),
'_fields': field_names,
'_field_defaults': field_defaults,
- # alternate spelling for backward compatiblity
+ # alternate spelling for backward compatibility
'_fields_defaults': field_defaults,
'__new__': __new__,
'_make': _make,
+import platform
+import sys
import unittest
from ctypes import *
from ctypes.test import need_symbol
self.assertEqual(s.first, got.first)
self.assertEqual(s.second, got.second)
+ def test_array_in_struct(self):
+ # See bpo-22273
+
+ # These should mirror the structures in Modules/_ctypes/_ctypes_test.c
+ class Test2(Structure):
+ _fields_ = [
+ ('data', c_ubyte * 16),
+ ]
+
+ class Test3(Structure):
+ _fields_ = [
+ ('data', c_double * 2),
+ ]
+
+ class Test3A(Structure):
+ _fields_ = [
+ ('data', c_float * 2),
+ ]
+
+ class Test3B(Test3A):
+ _fields_ = [
+ ('more_data', c_float * 2),
+ ]
+
+ s = Test2()
+ expected = 0
+ for i in range(16):
+ s.data[i] = i
+ expected += i
+ dll = CDLL(_ctypes_test.__file__)
+ func = dll._testfunc_array_in_struct1
+ func.restype = c_int
+ func.argtypes = (Test2,)
+ result = func(s)
+ self.assertEqual(result, expected)
+ # check the passed-in struct hasn't changed
+ for i in range(16):
+ self.assertEqual(s.data[i], i)
+
+ s = Test3()
+ s.data[0] = 3.14159
+ s.data[1] = 2.71828
+ expected = 3.14159 + 2.71828
+ func = dll._testfunc_array_in_struct2
+ func.restype = c_double
+ func.argtypes = (Test3,)
+ result = func(s)
+ self.assertEqual(result, expected)
+ # check the passed-in struct hasn't changed
+ self.assertEqual(s.data[0], 3.14159)
+ self.assertEqual(s.data[1], 2.71828)
+
+ s = Test3B()
+ s.data[0] = 3.14159
+ s.data[1] = 2.71828
+ s.more_data[0] = -3.0
+ s.more_data[1] = -2.0
+
+ expected = 3.14159 + 2.71828 - 5.0
+ func = dll._testfunc_array_in_struct2a
+ func.restype = c_double
+ func.argtypes = (Test3B,)
+ result = func(s)
+ self.assertAlmostEqual(result, expected, places=6)
+ # check the passed-in struct hasn't changed
+ self.assertAlmostEqual(s.data[0], 3.14159, places=6)
+ self.assertAlmostEqual(s.data[1], 2.71828, places=6)
+ self.assertAlmostEqual(s.more_data[0], -3.0, places=6)
+ self.assertAlmostEqual(s.more_data[1], -2.0, places=6)
+
+ def test_38368(self):
+ class U(Union):
+ _fields_ = [
+ ('f1', c_uint8 * 16),
+ ('f2', c_uint16 * 8),
+ ('f3', c_uint32 * 4),
+ ]
+ u = U()
+ u.f3[0] = 0x01234567
+ u.f3[1] = 0x89ABCDEF
+ u.f3[2] = 0x76543210
+ u.f3[3] = 0xFEDCBA98
+ f1 = [u.f1[i] for i in range(16)]
+ f2 = [u.f2[i] for i in range(8)]
+ if sys.byteorder == 'little':
+ self.assertEqual(f1, [0x67, 0x45, 0x23, 0x01,
+ 0xef, 0xcd, 0xab, 0x89,
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xba, 0xdc, 0xfe])
+ self.assertEqual(f2, [0x4567, 0x0123, 0xcdef, 0x89ab,
+ 0x3210, 0x7654, 0xba98, 0xfedc])
class PointerMemberTestCase(unittest.TestCase):
def _is_dataclass_instance(obj):
"""Returns True if obj is an instance of a dataclass."""
- return not isinstance(obj, type) and hasattr(obj, _FIELDS)
+ return hasattr(type(obj), _FIELDS)
def is_dataclass(obj):
"""Returns True if obj is a dataclass or an instance of a
dataclass."""
- return hasattr(obj, _FIELDS)
+ cls = obj if isinstance(obj, type) else type(obj)
+ return hasattr(cls, _FIELDS)
def asdict(obj, *, dict_factory=dict):
raise TypeError(f'Invalid field: {item!r}')
if not isinstance(name, str) or not name.isidentifier():
- raise TypeError(f'Field names must be valid identifers: {name!r}')
+ raise TypeError(f'Field names must be valid identifiers: {name!r}')
if keyword.iskeyword(name):
raise TypeError(f'Field names must not be keywords: {name!r}')
if name in seen:
unsafe_hash=unsafe_hash, frozen=frozen)
-def replace(obj, **changes):
+def replace(*args, **changes):
"""Return a new object replacing specified fields with new values.
This is especially useful for frozen classes. Example usage:
c1 = replace(c, x=3)
assert c1.x == 3 and c1.y == 2
"""
+ if len(args) > 1:
+ raise TypeError(f'replace() takes 1 positional argument but {len(args)} were given')
+ if args:
+ obj, = args
+ elif 'obj' in changes:
+ obj = changes.pop('obj')
+ else:
+ raise TypeError("replace() missing 1 required positional argument: 'obj'")
# We're going to mutate 'changes', but that's okay because it's a
# new dict, even if called with 'replace(obj, **my_changes)'.
if isinstance(other, timedelta):
return self._cmp(other) == 0
else:
- return False
+ return NotImplemented
def __le__(self, other):
if isinstance(other, timedelta):
return self._cmp(other) <= 0
else:
- _cmperror(self, other)
+ return NotImplemented
def __lt__(self, other):
if isinstance(other, timedelta):
return self._cmp(other) < 0
else:
- _cmperror(self, other)
+ return NotImplemented
def __ge__(self, other):
if isinstance(other, timedelta):
return self._cmp(other) >= 0
else:
- _cmperror(self, other)
+ return NotImplemented
def __gt__(self, other):
if isinstance(other, timedelta):
return self._cmp(other) > 0
else:
- _cmperror(self, other)
+ return NotImplemented
def _cmp(self, other):
assert isinstance(other, timedelta)
if isinstance(other, time):
return self._cmp(other, allow_mixed=True) == 0
else:
- return False
+ return NotImplemented
def __le__(self, other):
if isinstance(other, time):
return self._cmp(other) <= 0
else:
- _cmperror(self, other)
+ return NotImplemented
def __lt__(self, other):
if isinstance(other, time):
return self._cmp(other) < 0
else:
- _cmperror(self, other)
+ return NotImplemented
def __ge__(self, other):
if isinstance(other, time):
return self._cmp(other) >= 0
else:
- _cmperror(self, other)
+ return NotImplemented
def __gt__(self, other):
if isinstance(other, time):
return self._cmp(other) > 0
else:
- _cmperror(self, other)
+ return NotImplemented
def _cmp(self, other, allow_mixed=False):
assert isinstance(other, time)
return (self._offset, self._name)
def __eq__(self, other):
- if type(other) != timezone:
- return False
- return self._offset == other._offset
+ if isinstance(other, timezone):
+ return self._offset == other._offset
+ return NotImplemented
def __hash__(self):
return hash(self._offset)
raise TypeError("fromutc() argument must be a datetime instance"
" or None")
- _maxoffset = timedelta(hours=23, minutes=59)
+ _maxoffset = timedelta(hours=24, microseconds=-1)
_minoffset = -_maxoffset
@staticmethod
return f'UTC{sign}{hours:02d}:{minutes:02d}'
timezone.utc = timezone._create(timedelta(0))
-timezone.min = timezone._create(timezone._minoffset)
-timezone.max = timezone._create(timezone._maxoffset)
+# bpo-37642: These attributes are rounded to the nearest minute for backwards
+# compatibility, even though the constructor will accept a wider range of
+# values. This may change in the future.
+timezone.min = timezone._create(-timedelta(hours=23, minutes=59))
+timezone.max = timezone._create(timedelta(hours=23, minutes=59))
_EPOCH = datetime(1970, 1, 1, tzinfo=timezone.utc)
# Some time zone algebra. For a datetime x, let
vcruntime_plat = 'x64' if 'amd64' in plat_spec else 'x86'
if best_dir:
vcredist = os.path.join(best_dir, "..", "..", "redist", "MSVC", "**",
- "Microsoft.VC141.CRT", "vcruntime140.dll")
+ vcruntime_plat, "Microsoft.VC14*.CRT", "vcruntime140.dll")
try:
import glob
vcruntime = glob.glob(vcredist, recursive=True)[-1]
for incl in includes:
f.write("""#include "%s"\n""" % incl)
f.write("""\
-main (int argc, char **argv) {
+int main (int argc, char **argv) {
%s();
+ return 0;
}
""" % funcname)
finally:
boolean_options = ['keep-temp', 'no-target-compile', 'no-target-optimize',
'skip-build']
+ # bpo-10945: bdist_wininst requires mbcs encoding only available on Windows
+ _unsupported = (sys.platform != "win32")
+
def initialize_options(self):
self.bdist_dir = None
self.plat_name = None
@property
def display_name(self):
res = TokenList(self)
+ if len(res) == 0:
+ return res.value
if res[0].token_type == 'cfws':
res.pop(0)
else:
for x in self:
if x.token_type == 'quoted-string':
quote = True
- if quote:
+ if len(self) != 0 and quote:
pre = post = ''
if self[0].token_type=='cfws' or self[0][0].token_type=='cfws':
pre = ' '
return ''
+class _InvalidEwError(errors.HeaderParseError):
+ """Invalid encoded word found while parsing headers."""
+
+
# XXX these need to become classes and used as instances so
# that a program can't change them in a parse tree and screw
# up other parse trees. Maybe should have tests for that, too.
raise errors.HeaderParseError(
"expected encoded word but found {}".format(value))
remstr = ''.join(remainder)
- if len(remstr) > 1 and remstr[0] in hexdigits and remstr[1] in hexdigits:
+ if (len(remstr) > 1 and
+ remstr[0] in hexdigits and
+ remstr[1] in hexdigits and
+ tok.count('?') < 2):
# The ? after the CTE was followed by an encoded word escape (=XX).
rest, *remainder = remstr.split('?=', 1)
tok = tok + '?=' + rest
try:
text, charset, lang, defects = _ew.decode('=?' + tok + '?=')
except ValueError:
- raise errors.HeaderParseError(
+ raise _InvalidEwError(
"encoded word format invalid: '{}'".format(ew.cte))
ew.charset = charset
ew.lang = lang
token, value = get_fws(value)
unstructured.append(token)
continue
+ valid_ew = True
if value.startswith('=?'):
try:
token, value = get_encoded_word(value)
+ except _InvalidEwError:
+ valid_ew = False
except errors.HeaderParseError:
# XXX: Need to figure out how to register defects when
# appropriate here.
# Split in the middle of an atom if there is a rfc2047 encoded word
# which does not have WSP on both sides. The defect will be registered
# the next time through the loop.
- if rfc2047_matcher.search(tok):
+ # This needs to only be performed when the encoded word is valid;
+ # otherwise, performing it on an invalid encoded word can cause
+ # the parser to go in an infinite loop.
+ if valid_ew and rfc2047_matcher.search(tok):
tok, *remainder = value.partition('=?')
vtext = ValueTerminal(tok, 'vtext')
_validate_xtext(vtext)
"expected '\"' but found '{}'".format(value))
bare_quoted_string = BareQuotedString()
value = value[1:]
- if value[0] == '"':
+ if value and value[0] == '"':
token, value = get_qcontent(value)
bare_quoted_string.append(token)
while value and value[0] != '"':
leader, value = get_cfws(value)
else:
leader = None
+ if not value:
+ raise errors.HeaderParseError(
+ "Expected 'atom' or 'quoted-string' but found nothing.")
if value[0]=='"':
token, value = get_quoted_string(value)
elif value[0] in SPECIALS:
token, value = get_dot_atom(value)
except errors.HeaderParseError:
token, value = get_atom(value)
+ if value and value[0] == '@':
+ raise errors.HeaderParseError('Invalid Domain')
if leader is not None:
token[:0] = [leader]
domain.append(token)
while value:
if value[0] in WSP:
token, value = get_fws(value)
+ elif value[0] == '"':
+ token = ValueTerminal('"', 'DQUOTE')
+ value = value[1:]
else:
token, value = get_qcontent(value)
v.append(token)
wrap_as_ew_blocked -= 1
continue
tstr = str(part)
+ if part.token_type == 'ptext' and set(tstr) & SPECIALS:
+ # Encode if tstr contains special characters.
+ want_encoding = True
try:
tstr.encode(encoding)
charset = encoding
trailing_wsp = to_encode[-1]
to_encode = to_encode[:-1]
new_last_ew = len(lines[-1]) if last_ew is None else last_ew
+
+ encode_as = 'utf-8' if charset == 'us-ascii' else charset
+
+ # The RFC2047 chrome takes up 7 characters plus the length
+ # of the charset name.
+ chrome_len = len(encode_as) + 7
+
+ if (chrome_len + 1) >= maxlen:
+ raise errors.HeaderParseError(
+ "max_line_length is too small to fit an encoded word")
+
while to_encode:
remaining_space = maxlen - len(lines[-1])
- # The RFC2047 chrome takes up 7 characters plus the length
- # of the charset name.
- encode_as = 'utf-8' if charset == 'us-ascii' else charset
- text_space = remaining_space - len(encode_as) - 7
+ text_space = remaining_space - chrome_len
if text_space <= 0:
lines.append(' ')
- # XXX We'll get an infinite loop here if maxlen is <= 7
continue
to_encode_word = to_encode[:text_space]
aslist.append('@')
self.pos += 1
self.gotonext()
- return EMPTYSTRING.join(aslist) + self.getdomain()
+ domain = self.getdomain()
+ if not domain:
+ # Invalid domain, return an empty address instead of returning a
+ # local part to denote failed parsing.
+ return EMPTYSTRING
+ return EMPTYSTRING.join(aslist) + domain
def getdomain(self):
"""Get the complete domain name from an address."""
elif self.field[self.pos] == '.':
self.pos += 1
sdlist.append('.')
+ elif self.field[self.pos] == '@':
+ # bpo-34155: Don't parse domains with two `@` like
+ # `a@malicious.org@important.com`.
+ return EMPTYSTRING
elif self.field[self.pos] in self.atomends:
break
else:
the header name and the ': ' separator.
"""
- # At some point we need to put fws here iif it was in the source.
+ # At some point we need to put fws here if it was in the source.
header = parser.Header([
parser.HeaderLabel([
parser.ValueTerminal(self.name, 'header-name'),
maintype, subtype = self.get_content_type().split('/')
if maintype != 'multipart' or subtype == 'alternative':
return
- parts = self.get_payload().copy()
+ payload = self.get_payload()
+ # Certain malformed messages can have content type set to `multipart/*`
+ # but still have single part body, in which case payload.copy() can
+ # fail with AttributeError.
+ try:
+ parts = payload.copy()
+ except AttributeError:
+ # payload is not a list, it is most probably a string.
+ return
+
if maintype == 'multipart' and subtype == 'related':
# For related, we treat everything but the root as an attachment.
# The root may be indicated by 'start'; if there's no start or we
from email._policybase import compat32
-\f
class Parser:
def __init__(self, _class=None, *, policy=compat32):
"""Parser of RFC 2822 and MIME email messages.
__all__ = ["version", "bootstrap"]
-_SETUPTOOLS_VERSION = "40.8.0"
+_SETUPTOOLS_VERSION = "41.2.0"
-_PIP_VERSION = "19.0.3"
+_PIP_VERSION = "19.2.3"
_PROJECTS = [
("setuptools", _SETUPTOOLS_VERSION),
Generate the next value when not given.
name: the name of the member
- start: the initital start value or None
+ start: the initial start value or None
count: the number of existing members
last_value: the last value assigned or None
"""
with f.cache_info(). Clear the cache and statistics with f.cache_clear().
Access the underlying function with f.__wrapped__.
- See: http://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used
+ See: http://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)
"""
# Are two filenames really pointing to the same file?
def samefile(f1, f2):
- """Test whether two pathnames reference the same actual file"""
+ """Test whether two pathnames reference the same actual file or directory
+
+ This is determined by the device number and i-node number and
+ raises an exception if an os.stat() call on either pathname fails.
+ """
s1 = os.stat(f1)
s2 = os.stat(f2)
return samestat(s1, s2)
TEMPORARY_REDIRECT = (307, 'Temporary Redirect',
'Object moved temporarily -- see URI list')
PERMANENT_REDIRECT = (308, 'Permanent Redirect',
- 'Object moved temporarily -- see URI list')
+ 'Object moved permanently -- see URI list')
# client error
BAD_REQUEST = (400, 'Bad Request',
else:
raise CannotSendRequest(self.__state)
- # Save the method we use, we need it later in the response phase
+ # Save the method for use later in the response phase
self._method = method
- if not url:
- url = '/'
- # Prevent CVE-2019-9740.
- match = _contains_disallowed_url_pchar_re.search(url)
- if match:
- raise InvalidURL(f"URL can't contain control characters. {url!r} "
- f"(found at least {match.group()!r})")
+
+ url = url or '/'
+ self._validate_path(url)
+
request = '%s %s %s' % (method, url, self._http_vsn_str)
- # Non-ASCII characters should have been eliminated earlier
- self._output(request.encode('ascii'))
+ self._output(self._encode_request(request))
if self._http_vsn == 11:
# Issue some standard headers for better HTTP/1.1 compliance
# For HTTP/1.0, the server will assume "not chunked"
pass
+ def _encode_request(self, request):
+ # ASCII also helps prevent CVE-2019-9740.
+ return request.encode('ascii')
+
+ def _validate_path(self, url):
+ """Validate a url for putrequest."""
+ # Prevent CVE-2019-9740.
+ match = _contains_disallowed_url_pchar_re.search(url)
+ if match:
+ raise InvalidURL(f"URL can't contain control characters. {url!r} "
+ f"(found at least {match.group()!r})")
+
def putheader(self, header, *values):
"""Send a request header line to the server.
headers = response.info()
rfc2965_hdrs = headers.get_all("Set-Cookie2", [])
ns_hdrs = headers.get_all("Set-Cookie", [])
+ self._policy._now = self._now = int(time.time())
rfc2965 = self._policy.rfc2965
netscape = self._policy.netscape
_debug("extract_cookies: %s", response.info())
self._cookies_lock.acquire()
try:
- self._policy._now = self._now = int(time.time())
-
for cookie in self.make_cookies(response, request):
if self._policy.set_ok(cookie, request):
_debug(" setting cookie: %s", cookie)
+What's New in IDLE 3.7.5
+Released on 2019-09-30?
+======================================
+
+bpo-35379: When exiting IDLE, catch any AttributeError. One happens
+when EditorWindow.close is called twice. Printing a traceback, when
+IDLE is run from a terminal, is useless and annoying.
+
+bpo-38183: To avoid test issues, test_idle ignores the user config
+directory. It no longer tries to create or access .idlerc or any files
+within. Users must run IDLE to discover problems with saving settings.
+
+bpo-38077: IDLE no longer adds 'argv' to the user namespace when
+initializing it. This bug only affected 3.7.4 and 3.8.0b2 to 3.8.0b4.
+
+bpo-38401: Shell restart lines now fill the window width, always start
+with '=', and avoid wrapping unnecessarily. The line will still wrap
+if the included file name is long relative to the width.
+
+bpo-37092: Add mousewheel scrolling for IDLE module, path, and stack
+browsers. Patch by George Zhang.
+
+bpo-35771: To avoid occasional spurious test_idle failures on slower
+machines, increase the ``hover_delay`` in test_tooltip.
+
+bpo-37824: Properly handle user input warnings in IDLE shell.
+Cease turning SyntaxWarnings into SyntaxErrors.
+
+bpo-37929: IDLE Settings dialog now closes properly when there is no
+shell window.
+
+bpo-37849: Fix completions list appearing too high or low when shown
+above the current line.
+
+bpo-36419: Refactor autocompete and improve testing.
+
+bpo-37748: Reorder the Run menu. Put the most common choice,
+Run Module, at the top.
+
+bpo-37692: Improve highlight config sample with example shell
+interaction and better labels for shell elements.
+
+bpo-37628: Settings dialog no longer expands with font size.
+The font and highlight sample boxes gain scrollbars instead.
+
+bpo-17535: Add optional line numbers for IDLE editor windows.
+
+bpo-37627: Initialize the Customize Run dialog with the command line
+arguments most recently entered before. The user can optionally edit
+before submitting them.
+
+bpo-33610: Code context always shows the correct context when toggled on.
+
+bpo-36390: Gather Format menu functions into format.py. Combine
+paragraph.py, rstrip.py, and format methods from editor.py.
+
+bpo-37530: Optimize code context to reduce unneeded background activity.
+Font and highlight changes now occur along with text changes instead
+of after a random delay.
+
+bpo-27452: Cleanup config.py by inlining RemoveFile and simplifying
+the handling of __file__ in CreateConfigHandlers/
+
+
What's New in IDLE 3.7.4
-Released on 2019-06-24?
+Released on 2019-07-08
======================================
+bpo-26806: To compensate for stack frames added by IDLE and avoid
+possible problems with low recursion limits, add 30 to limits in the
+user code execution process. Subtract 30 when reporting recursion
+limits to make this addition mostly transparent.
+
+bpo-37325: Fix tab focus traversal order for help source and custom
+run dialogs.
bpo-37321: Both subprocess connection error messages now refer to
the 'Startup failure' section of the IDLE doc.
-bpo-37039: Adjust "Zoom Height" to individual screens by momemtarily
+bpo-37177: Properly attach search dialogs to their main window so
+that they behave like other dialogs and do not get hidden behind
+their main window.
+
+bpo-37039: Adjust "Zoom Height" to individual screens by momentarily
maximizing the window on first use with a particular screen. Changing
screen settings may invalidate the saved height. While a window is
maximized, "Zoom Height" has no effect.
bpo-35763: Make calltip reminder about '/' meaning positional-only less
obtrusive by only adding it when there is room on the first line.
+bpo-5680: Add 'Run Customized' to the Run menu to run a module with
+customized settings. Any command line arguments entered are added
+to sys.argv. One can suppress the normal Shell main module restart.
+
bpo-35610: Replace now redundant editor.context_use_ps1 with
.prompt_last_line. This finishes change started in bpo-31858.
bpo-36096: Make colorizer state variables instance-only.
+bpo-32129: Avoid blurry IDLE application icon on macOS with Tk 8.6.
+Patch by Kevin Walzer.
+
bpo-24310: Document settings dialog font tab sample.
bpo-35689: Add docstrings and tests for colorizer.
query.py # Query user for information
redirector.py # Intercept widget subcommands (for percolator) (nim).
replace.py # Search and replace pattern in text.
-rpc.py # Commuicate between idle and user processes (nim).
+rpc.py # Communicate between idle and user processes (nim).
rstrip.py # Strip trailing whitespace.
run.py # Manage user code execution subprocess.
runscript.py # Check and run user code.
statusbar.py # Define status bar for windows (nim).
tabbedpages.py # Define tabbed pages widget (nim).
textview.py # Define read-only text widget (nim).
-tree.py # Define tree widger, used in browsers (nim).
+tree.py # Define tree widget, used in browsers (nim).
undo.py # Manage undo stack.
windows.py # Manage window list and define listed top level.
zoomheight.py # Zoom window to full height of screen.
CREDITS.txt # not maintained, displayed by About IDLE
HISTORY.txt # NEWS up to July 2001
NEWS.txt # commits, displayed by About IDLE
-README.txt # this file, displeyed by About IDLE
+README.txt # this file, displayed by About IDLE
TODO.txt # needs review
extend.txt # about writing extensions
help.html # copy of idle.html in docs, displayed by IDLE Help
IDLE MENUS
Top level items and most submenu items are defined in mainmenu.
-Extenstions add submenu items when active. The names given are
+Extensions add submenu items when active. The names given are
found, quoted, in one of these modules, paired with a '<<pseudoevent>>'.
Each pseudoevent is bound to an event handler. Some event handlers
call another function that does the actual work. The annotations below
Debug (Shell only)
Go to File/Line
- debugger # debugger, debugger_r, PyShell.toggle_debuger
+ debugger # debugger, debugger_r, PyShell.toggle_debugger
Stack Viewer # stackviewer, PyShell.open_stack_viewer
Auto-open Stack Viewer # stackviewer
import string
import sys
-# These constants represent the two different types of completions.
-# They must be defined here so autocomple_w can import them.
-COMPLETE_ATTRIBUTES, COMPLETE_FILES = range(1, 2+1)
-
+# Two types of completions; defined here for autocomplete_w import below.
+ATTRS, FILES = 0, 1
from idlelib import autocomplete_w
from idlelib.config import idleConf
from idlelib.hyperparser import HyperParser
+# Tuples passed to open_completions.
+# EvalFunc, Complete, WantWin, Mode
+FORCE = True, False, True, None # Control-Space.
+TAB = False, True, True, None # Tab.
+TRY_A = False, False, False, ATTRS # '.' for attributes.
+TRY_F = False, False, False, FILES # '/' in quotes for file name.
+
# This string includes all chars that may be in an identifier.
# TODO Update this here and elsewhere.
ID_CHARS = string.ascii_letters + string.digits + "_"
-SEPS = os.sep
-if os.altsep: # e.g. '/' on Windows...
- SEPS += os.altsep
-
+SEPS = f"{os.sep}{os.altsep if os.altsep else ''}"
+TRIGGERS = f".{SEPS}"
class AutoComplete:
def __init__(self, editwin=None):
self.editwin = editwin
- if editwin is not None: # not in subprocess or test
+ if editwin is not None: # not in subprocess or no-gui test
self.text = editwin.text
- self.autocompletewindow = None
- # id of delayed call, and the index of the text insert when
- # the delayed call was issued. If _delayed_completion_id is
- # None, there is no delayed call.
- self._delayed_completion_id = None
- self._delayed_completion_index = None
+ self.autocompletewindow = None
+ # id of delayed call, and the index of the text insert when
+ # the delayed call was issued. If _delayed_completion_id is
+ # None, there is no delayed call.
+ self._delayed_completion_id = None
+ self._delayed_completion_index = None
@classmethod
def reload(cls):
cls.popupwait = idleConf.GetOption(
"extensions", "AutoComplete", "popupwait", type="int", default=0)
- def _make_autocomplete_window(self):
+ def _make_autocomplete_window(self): # Makes mocking easier.
return autocomplete_w.AutoCompleteWindow(self.text)
def _remove_autocomplete_window(self, event=None):
self.autocompletewindow = None
def force_open_completions_event(self, event):
- """Happens when the user really wants to open a completion list, even
- if a function call is needed.
- """
- self.open_completions(True, False, True)
+ "(^space) Open completion list, even if a function call is needed."
+ self.open_completions(FORCE)
return "break"
- def try_open_completions_event(self, event):
- """Happens when it would be nice to open a completion list, but not
- really necessary, for example after a dot, so function
- calls won't be made.
- """
- lastchar = self.text.get("insert-1c")
- if lastchar == ".":
- self._open_completions_later(False, False, False,
- COMPLETE_ATTRIBUTES)
- elif lastchar in SEPS:
- self._open_completions_later(False, False, False,
- COMPLETE_FILES)
-
def autocomplete_event(self, event):
- """Happens when the user wants to complete his word, and if necessary,
- open a completion list after that (if there is more than one
- completion)
- """
+ "(tab) Complete word or open list if multiple options."
if hasattr(event, "mc_state") and event.mc_state or\
not self.text.get("insert linestart", "insert").strip():
# A modifier was pressed along with the tab or
self.autocompletewindow.complete()
return "break"
else:
- opened = self.open_completions(False, True, True)
+ opened = self.open_completions(TAB)
return "break" if opened else None
- def _open_completions_later(self, *args):
- self._delayed_completion_index = self.text.index("insert")
- if self._delayed_completion_id is not None:
- self.text.after_cancel(self._delayed_completion_id)
- self._delayed_completion_id = \
- self.text.after(self.popupwait, self._delayed_open_completions,
- *args)
-
- def _delayed_open_completions(self, *args):
+ def try_open_completions_event(self, event=None):
+ "(./) Open completion list after pause with no movement."
+ lastchar = self.text.get("insert-1c")
+ if lastchar in TRIGGERS:
+ args = TRY_A if lastchar == "." else TRY_F
+ self._delayed_completion_index = self.text.index("insert")
+ if self._delayed_completion_id is not None:
+ self.text.after_cancel(self._delayed_completion_id)
+ self._delayed_completion_id = self.text.after(
+ self.popupwait, self._delayed_open_completions, args)
+
+ def _delayed_open_completions(self, args):
+ "Call open_completions if index unchanged."
self._delayed_completion_id = None
if self.text.index("insert") == self._delayed_completion_index:
- self.open_completions(*args)
+ self.open_completions(args)
- def open_completions(self, evalfuncs, complete, userWantsWin, mode=None):
+ def open_completions(self, args):
"""Find the completions and create the AutoCompleteWindow.
Return True if successful (no syntax error or so found).
If complete is True, then if there's nothing to complete and no
start of completion, won't open completions and return False.
If mode is given, will open a completion list only in this mode.
-
- Action Function Eval Complete WantWin Mode
- ^space force_open_completions True, False, True no
- . or / try_open_completions False, False, False yes
- tab autocomplete False, True, True no
"""
+ evalfuncs, complete, wantwin, mode = args
# Cancel another delayed call, if it exists.
if self._delayed_completion_id is not None:
self.text.after_cancel(self._delayed_completion_id)
hp = HyperParser(self.editwin, "insert")
curline = self.text.get("insert linestart", "insert")
i = j = len(curline)
- if hp.is_in_string() and (not mode or mode==COMPLETE_FILES):
+ if hp.is_in_string() and (not mode or mode==FILES):
# Find the beginning of the string.
# fetch_completions will look at the file system to determine
# whether the string value constitutes an actual file name
# XXX could consider raw strings here and unescape the string
# value if it's not raw.
self._remove_autocomplete_window()
- mode = COMPLETE_FILES
+ mode = FILES
# Find last separator or string start
while i and curline[i-1] not in "'\"" + SEPS:
i -= 1
while i and curline[i-1] not in "'\"":
i -= 1
comp_what = curline[i:j]
- elif hp.is_in_code() and (not mode or mode==COMPLETE_ATTRIBUTES):
+ elif hp.is_in_code() and (not mode or mode==ATTRS):
self._remove_autocomplete_window()
- mode = COMPLETE_ATTRIBUTES
+ mode = ATTRS
while i and (curline[i-1] in ID_CHARS or ord(curline[i-1]) > 127):
i -= 1
comp_start = curline[i:j]
- if i and curline[i-1] == '.':
+ if i and curline[i-1] == '.': # Need object with attributes.
hp.set_index("insert-%dc" % (len(curline)-(i-1)))
comp_what = hp.get_expression()
- if not comp_what or \
- (not evalfuncs and comp_what.find('(') != -1):
+ if (not comp_what or
+ (not evalfuncs and comp_what.find('(') != -1)):
return None
else:
comp_what = ""
self.autocompletewindow = self._make_autocomplete_window()
return not self.autocompletewindow.show_window(
comp_lists, "insert-%dc" % len(comp_start),
- complete, mode, userWantsWin)
+ complete, mode, wantwin)
def fetch_completions(self, what, mode):
"""Return a pair of lists of completions for something. The first list
return rpcclt.remotecall("exec", "get_the_completion_list",
(what, mode), {})
else:
- if mode == COMPLETE_ATTRIBUTES:
+ if mode == ATTRS:
if what == "":
namespace = {**__main__.__builtins__.__dict__,
**__main__.__dict__}
except:
return [], []
- elif mode == COMPLETE_FILES:
+ elif mode == FILES:
if what == "":
what = "."
try:
from tkinter import *
from tkinter.ttk import Frame, Scrollbar
-from idlelib.autocomplete import COMPLETE_FILES, COMPLETE_ATTRIBUTES
+from idlelib.autocomplete import FILES, ATTRS
from idlelib.multicall import MC_SHIFT
HIDE_VIRTUAL_EVENT_NAME = "<<autocompletewindow-hide>>"
self.completions = None
# A list with more completions, or None
self.morecompletions = None
- # The completion mode. Either autocomplete.COMPLETE_ATTRIBUTES or
- # autocomplete.COMPLETE_FILES
+ # The completion mode, either autocomplete.ATTRS or .FILES.
self.mode = None
# The current completion start, on the text box (a string)
self.start = None
# (for example, he clicked the list)
self.userwantswindow = None
# event ids
- self.hideid = self.keypressid = self.listupdateid = self.winconfigid \
- = self.keyreleaseid = self.doubleclickid = None
+ self.hideid = self.keypressid = self.listupdateid = \
+ self.winconfigid = self.keyreleaseid = self.doubleclickid = None
# Flag set if last keypress was a tab
self.lastkey_was_tab = False
+ # Flag set to avoid recursive <Configure> callback invocations.
+ self.is_configuring = False
def _change_start(self, newstart):
min_len = min(len(self.start), len(newstart))
def _binary_search(self, s):
"""Find the first index in self.completions where completions[i] is
- greater or equal to s, or the last index if there is no such
- one."""
+ greater or equal to s, or the last index if there is no such.
+ """
i = 0; j = len(self.completions)
while j > i:
m = (i + j) // 2
def _complete_string(self, s):
"""Assuming that s is the prefix of a string in self.completions,
return the longest string which is a prefix of all the strings which
- s is a prefix of them. If s is not a prefix of a string, return s."""
+ s is a prefix of them. If s is not a prefix of a string, return s.
+ """
first = self._binary_search(s)
if self.completions[first][:len(s)] != s:
# There is not even one completion which s is a prefix of.
return first_comp[:i]
def _selection_changed(self):
- """Should be called when the selection of the Listbox has changed.
- Updates the Listbox display and calls _change_start."""
+ """Call when the selection of the Listbox has changed.
+
+ Updates the Listbox display and calls _change_start.
+ """
cursel = int(self.listbox.curselection()[0])
self.listbox.see(cursel)
def show_window(self, comp_lists, index, complete, mode, userWantsWin):
"""Show the autocomplete list, bind events.
- If complete is True, complete the text, and if there is exactly one
- matching completion, don't open a list."""
+
+ If complete is True, complete the text, and if there is exactly
+ one matching completion, don't open a list.
+ """
# Handle the start we already have
self.completions, self.morecompletions = comp_lists
self.mode = mode
self.widget.event_add(KEYRELEASE_VIRTUAL_EVENT_NAME,KEYRELEASE_SEQUENCE)
self.listupdateid = listbox.bind(LISTUPDATE_SEQUENCE,
self.listselect_event)
+ self.is_configuring = False
self.winconfigid = acw.bind(WINCONFIG_SEQUENCE, self.winconfig_event)
self.doubleclickid = listbox.bind(DOUBLECLICK_SEQUENCE,
self.doubleclick_event)
return None
def winconfig_event(self, event):
+ if self.is_configuring:
+ # Avoid running on recursive <Configure> callback invocations.
+ return
+
+ self.is_configuring = True
if not self.is_active():
return
# Position the completion list window
text.see(self.startindex)
x, y, cx, cy = text.bbox(self.startindex)
acw = self.autocompletewindow
+ acw.update()
acw_width, acw_height = acw.winfo_width(), acw.winfo_height()
text_width, text_height = text.winfo_width(), text.winfo_height()
new_x = text.winfo_rootx() + min(x, max(0, text_width - acw_width))
acw.unbind(WINCONFIG_SEQUENCE, self.winconfigid)
self.winconfigid = None
+ self.is_configuring = False
+
def _hide_event_check(self):
if not self.autocompletewindow:
return
if keysym != "Tab":
self.lastkey_was_tab = False
if (len(keysym) == 1 or keysym in ("underscore", "BackSpace")
- or (self.mode == COMPLETE_FILES and keysym in
+ or (self.mode == FILES and keysym in
("period", "minus"))) \
and not (state & ~MC_SHIFT):
# Normal editing of text
self.hide_window()
return 'break'
- elif (self.mode == COMPLETE_ATTRIBUTES and keysym in
+ elif (self.mode == ATTRS and keysym in
("period", "space", "parenleft", "parenright", "bracketleft",
"bracketright")) or \
- (self.mode == COMPLETE_FILES and keysym in
+ (self.mode == FILES and keysym in
("slash", "backslash", "quotedbl", "apostrophe")) \
and not (state & ~MC_SHIFT):
# If start is a prefix of the selection, but is not '' when
# selected completion. Anyway, close the list.
cursel = int(self.listbox.curselection()[0])
if self.completions[cursel][:len(self.start)] == self.start \
- and (self.mode == COMPLETE_ATTRIBUTES or self.start):
+ and (self.mode == ATTRS or self.start):
self._change_start(self.completions[cursel])
self.hide_window()
return None
The dictionary maps names to pyclbr information objects.
Filter out imported objects.
Augment class names with bases.
- The insertion order of the dictonary is assumed to have been in line
+ The insertion order of the dictionary is assumed to have been in line
number order, so sorting is not necessary.
The current tree only calls this once per child_dict as it saves
from sys import maxsize as INFINITY
import tkinter
-from tkinter.constants import TOP, X, SUNKEN
+from tkinter.constants import NSEW, SUNKEN
from idlelib.config import idleConf
BLOCKOPENERS = {"class", "def", "elif", "else", "except", "finally", "for",
"if", "try", "while", "with", "async"}
-UPDATEINTERVAL = 100 # millisec
-CONFIGUPDATEINTERVAL = 1000 # millisec
def get_spaces_firstword(codeline, c=re.compile(r"^(\s*)(\w*)")):
class CodeContext:
"Display block context above the edit window."
+ UPDATEINTERVAL = 100 # millisec
def __init__(self, editwin):
"""Initialize settings for context block.
editwin is the Editor window for the context block.
self.text is the editor window text widget.
- self.textfont is the editor window font.
self.context displays the code context text above the editor text.
Initially None, it is toggled via <<toggle-code-context>>.
"""
self.editwin = editwin
self.text = editwin.text
- self.textfont = self.text["font"]
- self.contextcolors = CodeContext.colors
+ self._reset()
+
+ def _reset(self):
self.context = None
+ self.cell00 = None
+ self.t1 = None
self.topvisible = 1
self.info = [(0, -1, "", False)]
- # Start two update cycles, one for context lines, one for font changes.
- self.t1 = self.text.after(UPDATEINTERVAL, self.timer_event)
- self.t2 = self.text.after(CONFIGUPDATEINTERVAL, self.config_timer_event)
@classmethod
def reload(cls):
"Load class variables from config."
cls.context_depth = idleConf.GetOption("extensions", "CodeContext",
- "maxlines", type="int", default=15)
- cls.colors = idleConf.GetHighlight(idleConf.CurrentTheme(), 'context')
+ "maxlines", type="int",
+ default=15)
def __del__(self):
"Cancel scheduled events."
- try:
- self.text.after_cancel(self.t1)
- self.text.after_cancel(self.t2)
- except:
- pass
+ if self.t1 is not None:
+ try:
+ self.text.after_cancel(self.t1)
+ except tkinter.TclError:
+ pass
+ self.t1 = None
def toggle_code_context_event(self, event=None):
"""Toggle code context display.
window text (toggle on). If it does exist, destroy it (toggle off).
Return 'break' to complete the processing of the binding.
"""
- if not self.context:
+ if self.context is None:
# Calculate the border width and horizontal padding required to
# align the context with the text in the main Text widget.
#
padx = 0
border = 0
for widget in widgets:
- padx += widget.tk.getint(widget.pack_info()['padx'])
+ info = (widget.grid_info()
+ if widget is self.editwin.text
+ else widget.pack_info())
+ padx += widget.tk.getint(info['padx'])
padx += widget.tk.getint(widget.cget('padx'))
border += widget.tk.getint(widget.cget('border'))
self.context = tkinter.Text(
- self.editwin.top, font=self.textfont,
- bg=self.contextcolors['background'],
- fg=self.contextcolors['foreground'],
- height=1,
- width=1, # Don't request more than we get.
- padx=padx, border=border, relief=SUNKEN, state='disabled')
+ self.editwin.text_frame,
+ height=1,
+ width=1, # Don't request more than we get.
+ highlightthickness=0,
+ padx=padx, border=border, relief=SUNKEN, state='disabled')
+ self.update_font()
+ self.update_highlight_colors()
self.context.bind('<ButtonRelease-1>', self.jumptoline)
- # Pack the context widget before and above the text_frame widget,
- # thus ensuring that it will appear directly above text_frame.
- self.context.pack(side=TOP, fill=X, expand=False,
- before=self.editwin.text_frame)
+ # Get the current context and initiate the recurring update event.
+ self.timer_event()
+ # Grid the context widget above the text widget.
+ self.context.grid(row=0, column=1, sticky=NSEW)
+
+ line_number_colors = idleConf.GetHighlight(idleConf.CurrentTheme(),
+ 'linenumber')
+ self.cell00 = tkinter.Frame(self.editwin.text_frame,
+ bg=line_number_colors['background'])
+ self.cell00.grid(row=0, column=0, sticky=NSEW)
menu_status = 'Hide'
else:
self.context.destroy()
self.context = None
+ self.cell00.destroy()
+ self.cell00 = None
+ self.text.after_cancel(self.t1)
+ self._reset()
menu_status = 'Show'
self.editwin.update_menu_label(menu='options', index='* Code Context',
label=f'{menu_status} Code Context')
be retrieved and the context area will be updated with the code,
up to the number of maxlines.
"""
- new_topvisible = int(self.text.index("@0,0").split('.')[0])
+ new_topvisible = self.editwin.getlineno("@0,0")
if self.topvisible == new_topvisible: # Haven't scrolled.
return
if self.topvisible < new_topvisible: # Scroll down.
def timer_event(self):
"Event on editor text widget triggered every UPDATEINTERVAL ms."
- if self.context:
+ if self.context is not None:
self.update_code_context()
- self.t1 = self.text.after(UPDATEINTERVAL, self.timer_event)
-
- def config_timer_event(self):
- "Event on editor text widget triggered every CONFIGUPDATEINTERVAL ms."
- newtextfont = self.text["font"]
- if (self.context and (newtextfont != self.textfont or
- CodeContext.colors != self.contextcolors)):
- self.textfont = newtextfont
- self.contextcolors = CodeContext.colors
- self.context["font"] = self.textfont
- self.context['background'] = self.contextcolors['background']
- self.context['foreground'] = self.contextcolors['foreground']
- self.t2 = self.text.after(CONFIGUPDATEINTERVAL, self.config_timer_event)
+ self.t1 = self.text.after(self.UPDATEINTERVAL, self.timer_event)
+
+ def update_font(self):
+ if self.context is not None:
+ font = idleConf.GetFont(self.text, 'main', 'EditorWindow')
+ self.context['font'] = font
+
+ def update_highlight_colors(self):
+ if self.context is not None:
+ colors = idleConf.GetHighlight(idleConf.CurrentTheme(), 'context')
+ self.context['background'] = colors['background']
+ self.context['foreground'] = colors['foreground']
+
+ if self.cell00 is not None:
+ line_number_colors = idleConf.GetHighlight(idleConf.CurrentTheme(),
+ 'linenumber')
+ self.cell00.config(bg=line_number_colors['background'])
CodeContext.reload()
hit-background= #000000
error-foreground= #000000
error-background= #ff7777
+context-foreground= #000000
+context-background= lightgray
+linenumber-foreground= gray
+linenumber-background= #ffffff
#cursor (only foreground can be set, restart IDLE)
cursor-foreground= black
#shell window
stderr-background= #ffffff
console-foreground= #770000
console-background= #ffffff
-context-foreground= #000000
-context-background= lightgray
[IDLE New]
normal-foreground= #000000
hit-background= #000000
error-foreground= #000000
error-background= #ff7777
+context-foreground= #000000
+context-background= lightgray
+linenumber-foreground= gray
+linenumber-background= #ffffff
#cursor (only foreground can be set, restart IDLE)
cursor-foreground= black
#shell window
stderr-background= #ffffff
console-foreground= #770000
console-background= #ffffff
-context-foreground= #000000
-context-background= lightgray
[IDLE Dark]
comment-foreground = #dd0000
break-foreground = #FFFFFF
context-foreground= #ffffff
context-background= #454545
+linenumber-foreground= gray
+linenumber-background= #002240
# Additional help sources are listed in the [HelpFiles] section below
# and should be viewable by a web browser (or the Windows Help viewer in
# the case of .chm files). These sources will be listed on the Help
-# menu. The pattern, and two examples, are
+# menu. The pattern, and two examples, are:
#
# <sequence_number = menu item;/path/to/help/source>
# 1 = IDLE;C:/Programs/Python36/Lib/idlelib/help.html
# platform specific because of path separators, drive specs etc.
#
# The default files should not be edited except to add new sections to
-# config-extensions.def for added extensions . The user files should be
+# config-extensions.def for added extensions. The user files should be
# modified through the Settings dialog.
[General]
font-size= 10
font-bold= 0
encoding= none
+line-numbers-default= 0
[PyShell]
auto-squeeze-min-lines= 50
self.RemoveEmptySections()
return not self.sections()
- def RemoveFile(self):
- "Remove user config file self.file from disk if it exists."
- if os.path.exists(self.file):
- os.remove(self.file)
-
def Save(self):
"""Update user configuration file.
If self not empty after removing empty sections, write the file
to disk. Otherwise, remove the file from disk if it exists.
-
"""
fname = self.file
- if fname:
+ if fname and fname[0] != '#':
if not self.IsEmpty():
try:
cfgFile = open(fname, 'w')
cfgFile = open(fname, 'w')
with cfgFile:
self.write(cfgFile)
- else:
- self.RemoveFile()
+ elif os.path.exists(self.file):
+ os.remove(self.file)
class IdleConf:
"""Hold config parsers for all idle config files in singleton instance.
def CreateConfigHandlers(self):
"Populate default and user config parser dictionaries."
- #build idle install path
- if __name__ != '__main__': # we were imported
- idleDir = os.path.dirname(__file__)
- else: # we were exec'ed (for testing only)
- idleDir = os.path.abspath(sys.path[0])
- self.userdir = userDir = self.GetUserCfgDir()
-
- defCfgFiles = {}
- usrCfgFiles = {}
- # TODO eliminate these temporaries by combining loops
- for cfgType in self.config_types: #build config file names
- defCfgFiles[cfgType] = os.path.join(
- idleDir, 'config-' + cfgType + '.def')
- usrCfgFiles[cfgType] = os.path.join(
- userDir, 'config-' + cfgType + '.cfg')
- for cfgType in self.config_types: #create config parsers
- self.defaultCfg[cfgType] = IdleConfParser(defCfgFiles[cfgType])
- self.userCfg[cfgType] = IdleUserConfParser(usrCfgFiles[cfgType])
+ idledir = os.path.dirname(__file__)
+ self.userdir = userdir = '' if idlelib.testing else self.GetUserCfgDir()
+ for cfg_type in self.config_types:
+ self.defaultCfg[cfg_type] = IdleConfParser(
+ os.path.join(idledir, f'config-{cfg_type}.def'))
+ self.userCfg[cfg_type] = IdleUserConfParser(
+ os.path.join(userdir or '#', f'config-{cfg_type}.cfg'))
def GetUserCfgDir(self):
"""Return a filesystem directory for storing user config files.
userDir = os.path.expanduser('~')
if userDir != '~': # expanduser() found user home dir
if not os.path.exists(userDir):
- warn = ('\n Warning: os.path.expanduser("~") points to\n ' +
- userDir + ',\n but the path does not exist.')
- try:
- print(warn, file=sys.stderr)
- except OSError:
- pass
+ if not idlelib.testing:
+ warn = ('\n Warning: os.path.expanduser("~") points to\n ' +
+ userDir + ',\n but the path does not exist.')
+ try:
+ print(warn, file=sys.stderr)
+ except OSError:
+ pass
userDir = '~'
if userDir == "~": # still no path to home!
# traditionally IDLE has defaulted to os.getcwd(), is this adequate?
try:
os.mkdir(userDir)
except OSError:
- warn = ('\n Warning: unable to create user config directory\n' +
- userDir + '\n Check path and permissions.\n Exiting!\n')
if not idlelib.testing:
- print(warn, file=sys.stderr)
+ warn = ('\n Warning: unable to create user config directory\n' +
+ userDir + '\n Check path and permissions.\n Exiting!\n')
+ try:
+ print(warn, file=sys.stderr)
+ except OSError:
+ pass
raise SystemExit
# TODO continue without userDIr instead of exit
return userDir
'hit-background':'#000000',
'error-foreground':'#ffffff',
'error-background':'#000000',
+ 'context-foreground':'#000000',
+ 'context-background':'#ffffff',
+ 'linenumber-foreground':'#000000',
+ 'linenumber-background':'#ffffff',
#cursor (only foreground can be set)
'cursor-foreground':'#000000',
#shell window
'stderr-background':'#ffffff',
'console-foreground':'#000000',
'console-background':'#ffffff',
- 'context-foreground':'#000000',
- 'context-background':'#ffffff',
}
for element in theme:
- if not cfgParser.has_option(themeName, element):
+ if not (cfgParser.has_option(themeName, element) or
+ # Skip warning for new elements.
+ element.startswith(('context-', 'linenumber-'))):
# Print warning that will return a default color
warning = ('\n Warning: config.IdleConf.GetThemeDict'
' -\n problem retrieving theme element %r'
Refer to comments in EditorWindow autoindent code for details.
"""
+import re
+
from tkinter import (Toplevel, Listbox, Text, Scale, Canvas,
StringVar, BooleanVar, IntVar, TRUE, FALSE,
TOP, BOTTOM, RIGHT, LEFT, SOLID, GROOVE,
from idlelib.autocomplete import AutoComplete
from idlelib.codecontext import CodeContext
from idlelib.parenmatch import ParenMatch
-from idlelib.paragraph import FormatParagraph
+from idlelib.format import FormatParagraph
from idlelib.squeezer import Squeezer
+from idlelib.textview import ScrollableTextFrame
changes = ConfigChanges()
# Reload changed options in the following classes.
frame_font_param, variable=self.font_bold,
onvalue=1, offvalue=0, text='Bold')
# frame_sample.
- self.font_sample = Text(frame_sample, width=20, height=20)
+ font_sample_frame = ScrollableTextFrame(frame_sample)
+ self.font_sample = font_sample_frame.text
+ self.font_sample.config(wrap=NONE, width=1, height=1)
self.font_sample.insert(END, font_sample_text)
# frame_indent.
indent_title = Label(
# Grid and pack widgets:
self.columnconfigure(1, weight=1)
+ self.rowconfigure(2, weight=1)
frame_font.grid(row=0, column=0, padx=5, pady=5)
- frame_sample.grid(row=0, column=1, rowspan=2, padx=5, pady=5,
+ frame_sample.grid(row=0, column=1, rowspan=3, padx=5, pady=5,
sticky='nsew')
frame_indent.grid(row=1, column=0, padx=5, pady=5, sticky='ew')
# frame_font.
self.sizelist.pack(side=LEFT, anchor=W)
self.bold_toggle.pack(side=LEFT, anchor=W, padx=20)
# frame_sample.
- self.font_sample.pack(expand=TRUE, fill=BOTH)
+ font_sample_frame.pack(expand=TRUE, fill=BOTH)
# frame_indent.
indent_title.pack(side=TOP, anchor=W, padx=5)
self.indent_scale.pack(side=TOP, padx=5, fill=X)
(*)theme_message: Label
"""
self.theme_elements = {
- 'Normal Text': ('normal', '00'),
+ 'Normal Code or Text': ('normal', '00'),
'Code Context': ('context', '01'),
'Python Keywords': ('keyword', '02'),
'Python Definitions': ('definition', '03'),
'Found Text': ('hit', '08'),
'Cursor': ('cursor', '09'),
'Editor Breakpoint': ('break', '10'),
- 'Shell Normal Text': ('console', '11'),
- 'Shell Error Text': ('error', '12'),
- 'Shell Stdout Text': ('stdout', '13'),
- 'Shell Stderr Text': ('stderr', '14'),
+ 'Shell Prompt': ('console', '11'),
+ 'Error Text': ('error', '12'),
+ 'Shell User Output': ('stdout', '13'),
+ 'Shell User Exception': ('stderr', '14'),
+ 'Line Number': ('linenumber', '16'),
}
self.builtin_name = tracers.add(
StringVar(self), self.var_changed_builtin_name)
frame_theme = LabelFrame(self, borderwidth=2, relief=GROOVE,
text=' Highlighting Theme ')
# frame_custom.
- text = self.highlight_sample = Text(
- frame_custom, relief=SOLID, borderwidth=1,
- font=('courier', 12, ''), cursor='hand2', width=21, height=13,
+ sample_frame = ScrollableTextFrame(
+ frame_custom, relief=SOLID, borderwidth=1)
+ text = self.highlight_sample = sample_frame.text
+ text.configure(
+ font=('courier', 12, ''), cursor='hand2', width=1, height=1,
takefocus=FALSE, highlightthickness=0, wrap=NONE)
text.bind('<Double-Button-1>', lambda e: 'break')
text.bind('<B1-Motion>', lambda e: 'break')
- text_and_tags=(
- ('\n', 'normal'),
- ('#you can click here', 'comment'), ('\n', 'normal'),
- ('#to choose items', 'comment'), ('\n', 'normal'),
- ('code context section', 'context'), ('\n\n', 'normal'),
+ string_tags=(
+ ('# Click selects item.', 'comment'), ('\n', 'normal'),
+ ('code context section', 'context'), ('\n', 'normal'),
+ ('| cursor', 'cursor'), ('\n', 'normal'),
('def', 'keyword'), (' ', 'normal'),
('func', 'definition'), ('(param):\n ', 'normal'),
- ('"""string"""', 'string'), ('\n var0 = ', 'normal'),
+ ('"Return None."', 'string'), ('\n var0 = ', 'normal'),
("'string'", 'string'), ('\n var1 = ', 'normal'),
("'selected'", 'hilite'), ('\n var2 = ', 'normal'),
("'found'", 'hit'), ('\n var3 = ', 'normal'),
('list', 'builtin'), ('(', 'normal'),
('None', 'keyword'), (')\n', 'normal'),
(' breakpoint("line")', 'break'), ('\n\n', 'normal'),
- (' error ', 'error'), (' ', 'normal'),
- ('cursor |', 'cursor'), ('\n ', 'normal'),
- ('shell', 'console'), (' ', 'normal'),
- ('stdout', 'stdout'), (' ', 'normal'),
- ('stderr', 'stderr'), ('\n\n', 'normal'))
- for texttag in text_and_tags:
- text.insert(END, texttag[0], texttag[1])
+ ('>>>', 'console'), (' 3.14**2\n', 'normal'),
+ ('9.8596', 'stdout'), ('\n', 'normal'),
+ ('>>>', 'console'), (' pri ', 'normal'),
+ ('n', 'error'), ('t(\n', 'normal'),
+ ('SyntaxError', 'stderr'), ('\n', 'normal'))
+ for string, tag in string_tags:
+ text.insert(END, string, tag)
+ n_lines = len(text.get('1.0', END).splitlines())
+ for lineno in range(1, n_lines):
+ text.insert(f'{lineno}.0',
+ f'{lineno:{len(str(n_lines))}d} ',
+ 'linenumber')
for element in self.theme_elements:
def tem(event, elem=element):
# event.widget.winfo_top_level().highlight_target.set(elem)
frame_custom.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH)
frame_theme.pack(side=TOP, padx=5, pady=5, fill=X)
# frame_custom.
- self.frame_color_set.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=X)
+ self.frame_color_set.pack(side=TOP, padx=5, pady=5, fill=X)
frame_fg_bg_toggle.pack(side=TOP, padx=5, pady=0)
- self.highlight_sample.pack(
+ sample_frame.pack(
side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH)
self.button_set_color.pack(side=TOP, expand=TRUE, fill=X, padx=8, pady=4)
self.targetlist.pack(side=TOP, expand=TRUE, fill=X, padx=8, pady=3)
def __init__(self, master):
super().__init__(master)
+
+ self.init_validators()
self.create_page_general()
self.load_general_cfg()
+ def init_validators(self):
+ digits_or_empty_re = re.compile(r'[0-9]*')
+ def is_digits_or_empty(s):
+ "Return 's is blank or contains only digits'"
+ return digits_or_empty_re.fullmatch(s) is not None
+ self.digits_only = (self.register(is_digits_or_empty), '%P',)
+
def create_page_general(self):
"""Return frame of widgets for General tab.
Enable users to provisionally change general options. Function
- load_general_cfg intializes tk variables and helplist using
+ load_general_cfg initializes tk variables and helplist using
idleConf. Radiobuttons startup_shell_on and startup_editor_on
set var startup_edit. Radiobuttons save_ask_on and save_auto_on
set var autosave. Entry boxes win_width_int and win_height_int
frame_format: Frame
format_width_title: Label
(*)format_width_int: Entry - format_width
+ frame_line_numbers_default: Frame
+ line_numbers_default_title: Label
+ (*)line_numbers_default_bool: Checkbutton - line_numbers_default
frame_context: Frame
context_title: Label
(*)context_int: Entry - context_lines
IntVar(self), ('main', 'General', 'autosave'))
self.format_width = tracers.add(
StringVar(self), ('extensions', 'FormatParagraph', 'max-width'))
+ self.line_numbers_default = tracers.add(
+ BooleanVar(self),
+ ('main', 'EditorWindow', 'line-numbers-default'))
self.context_lines = tracers.add(
StringVar(self), ('extensions', 'CodeContext', 'maxlines'))
frame_win_size, text='Initial Window Size (in characters)')
win_width_title = Label(frame_win_size, text='Width')
self.win_width_int = Entry(
- frame_win_size, textvariable=self.win_width, width=3)
+ frame_win_size, textvariable=self.win_width, width=3,
+ validatecommand=self.digits_only, validate='key',
+ )
win_height_title = Label(frame_win_size, text='Height')
self.win_height_int = Entry(
- frame_win_size, textvariable=self.win_height, width=3)
+ frame_win_size, textvariable=self.win_height, width=3,
+ validatecommand=self.digits_only, validate='key',
+ )
frame_autocomplete = Frame(frame_window, borderwidth=0,)
auto_wait_title = Label(frame_autocomplete,
text='Completions Popup Wait (milliseconds)')
self.auto_wait_int = Entry(frame_autocomplete, width=6,
- textvariable=self.autocomplete_wait)
+ textvariable=self.autocomplete_wait,
+ validatecommand=self.digits_only,
+ validate='key',
+ )
frame_paren1 = Frame(frame_window, borderwidth=0)
paren_style_title = Label(frame_paren1, text='Paren Match Style')
format_width_title = Label(frame_format,
text='Format Paragraph Max Width')
self.format_width_int = Entry(
- frame_format, textvariable=self.format_width, width=4)
+ frame_format, textvariable=self.format_width, width=4,
+ validatecommand=self.digits_only, validate='key',
+ )
+
+ frame_line_numbers_default = Frame(frame_editor, borderwidth=0)
+ line_numbers_default_title = Label(
+ frame_line_numbers_default, text='Show line numbers in new windows')
+ self.line_numbers_default_bool = Checkbutton(
+ frame_line_numbers_default,
+ variable=self.line_numbers_default,
+ width=1)
frame_context = Frame(frame_editor, borderwidth=0)
context_title = Label(frame_context, text='Max Context Lines :')
self.context_int = Entry(
- frame_context, textvariable=self.context_lines, width=3)
+ frame_context, textvariable=self.context_lines, width=3,
+ validatecommand=self.digits_only, validate='key',
+ )
# Frame_shell.
frame_auto_squeeze_min_lines = Frame(frame_shell, borderwidth=0)
auto_squeeze_min_lines_title = Label(frame_auto_squeeze_min_lines,
text='Auto-Squeeze Min. Lines:')
self.auto_squeeze_min_lines_int = Entry(
- frame_auto_squeeze_min_lines, width=4,
- textvariable=self.auto_squeeze_min_lines)
+ frame_auto_squeeze_min_lines, width=4,
+ textvariable=self.auto_squeeze_min_lines,
+ validatecommand=self.digits_only, validate='key',
+ )
# frame_help.
frame_helplist = Frame(frame_help)
frame_format.pack(side=TOP, padx=5, pady=0, fill=X)
format_width_title.pack(side=LEFT, anchor=W, padx=5, pady=5)
self.format_width_int.pack(side=TOP, padx=10, pady=5)
+ # frame_line_numbers_default.
+ frame_line_numbers_default.pack(side=TOP, padx=5, pady=0, fill=X)
+ line_numbers_default_title.pack(side=LEFT, anchor=W, padx=5, pady=5)
+ self.line_numbers_default_bool.pack(side=LEFT, padx=5, pady=5)
# frame_context.
frame_context.pack(side=TOP, padx=5, pady=0, fill=X)
context_title.pack(side=LEFT, anchor=W, padx=5, pady=5)
'main', 'General', 'autosave', default=0, type='bool'))
self.format_width.set(idleConf.GetOption(
'extensions', 'FormatParagraph', 'max-width', type='int'))
+ self.line_numbers_default.set(idleConf.GetOption(
+ 'main', 'EditorWindow', 'line-numbers-default', type='bool'))
self.context_lines.set(idleConf.GetOption(
'extensions', 'CodeContext', 'maxlines', type='int'))
import importlib.util
import os
import platform
+import re
import string
+import sys
import tokenize
import traceback
import webbrowser
from tkinter import *
+from tkinter.font import Font
from tkinter.ttk import Scrollbar
import tkinter.simpledialog as tkSimpleDialog
import tkinter.messagebox as tkMessageBox
from idlelib import query
from idlelib import replace
from idlelib import search
+from idlelib.tree import wheel_event
from idlelib import window
# The default tab setting for a Text widget, in average-width characters.
from idlelib.autoexpand import AutoExpand
from idlelib.calltip import Calltip
from idlelib.codecontext import CodeContext
- from idlelib.paragraph import FormatParagraph
+ from idlelib.sidebar import LineNumbers
+ from idlelib.format import FormatParagraph, FormatRegion, Indents, Rstrip
from idlelib.parenmatch import ParenMatch
- from idlelib.rstrip import Rstrip
from idlelib.squeezer import Squeezer
from idlelib.zoomheight import ZoomHeight
filesystemencoding = sys.getfilesystemencoding() # for file names
help_url = None
+ allow_code_context = True
+ allow_line_numbers = True
+
def __init__(self, flist=None, filename=None, key=None, root=None):
# Delay import: runscript imports pyshell imports EditorWindow.
from idlelib.runscript import ScriptBinding
self.tkinter_vars = {} # keys: Tkinter event names
# values: Tkinter variable instances
self.top.instance_dict = {}
- self.recent_files_path = os.path.join(
+ self.recent_files_path = idleConf.userdir and os.path.join(
idleConf.userdir, 'recent-files.lst')
self.prompt_last_line = '' # Override in PyShell
self.text_frame = text_frame = Frame(top)
self.vbar = vbar = Scrollbar(text_frame, name='vbar')
- self.width = idleConf.GetOption('main', 'EditorWindow',
- 'width', type='int')
+ width = idleConf.GetOption('main', 'EditorWindow', 'width', type='int')
text_options = {
'name': 'text',
'padx': 5,
'wrap': 'none',
'highlightthickness': 0,
- 'width': self.width,
+ 'width': width,
'tabstyle': 'wordprocessor', # new in 8.5
'height': idleConf.GetOption(
'main', 'EditorWindow', 'height', type='int'),
else:
# Elsewhere, use right-click for popup menus.
text.bind("<3>",self.right_menu_event)
- text.bind('<MouseWheel>', self.mousescroll)
- text.bind('<Button-4>', self.mousescroll)
- text.bind('<Button-5>', self.mousescroll)
+
+ text.bind('<MouseWheel>', wheel_event)
+ text.bind('<Button-4>', wheel_event)
+ text.bind('<Button-5>', wheel_event)
+ text.bind('<Configure>', self.handle_winconfig)
text.bind("<<cut>>", self.cut)
text.bind("<<copy>>", self.copy)
text.bind("<<paste>>", self.paste)
text.bind("<<smart-backspace>>",self.smart_backspace_event)
text.bind("<<newline-and-indent>>",self.newline_and_indent_event)
text.bind("<<smart-indent>>",self.smart_indent_event)
- text.bind("<<indent-region>>",self.indent_region_event)
- text.bind("<<dedent-region>>",self.dedent_region_event)
- text.bind("<<comment-region>>",self.comment_region_event)
- text.bind("<<uncomment-region>>",self.uncomment_region_event)
- text.bind("<<tabify-region>>",self.tabify_region_event)
- text.bind("<<untabify-region>>",self.untabify_region_event)
- text.bind("<<toggle-tabs>>",self.toggle_tabs_event)
- text.bind("<<change-indentwidth>>",self.change_indentwidth_event)
+ self.fregion = fregion = self.FormatRegion(self)
+ # self.fregion used in smart_indent_event to access indent_region.
+ text.bind("<<indent-region>>", fregion.indent_region_event)
+ text.bind("<<dedent-region>>", fregion.dedent_region_event)
+ text.bind("<<comment-region>>", fregion.comment_region_event)
+ text.bind("<<uncomment-region>>", fregion.uncomment_region_event)
+ text.bind("<<tabify-region>>", fregion.tabify_region_event)
+ text.bind("<<untabify-region>>", fregion.untabify_region_event)
+ text.bind("<<toggle-tabs>>", self.Indents.toggle_tabs_event)
+ text.bind("<<change-indentwidth>>", self.Indents.change_indentwidth_event)
text.bind("<Left>", self.move_at_edge_if_selection(0))
text.bind("<Right>", self.move_at_edge_if_selection(1))
text.bind("<<del-word-left>>", self.del_word_left)
text.bind("<<open-turtle-demo>>", self.open_turtle_demo)
self.set_status_bar()
+ text_frame.pack(side=LEFT, fill=BOTH, expand=1)
+ text_frame.rowconfigure(1, weight=1)
+ text_frame.columnconfigure(1, weight=1)
vbar['command'] = self.handle_yview
- vbar.pack(side=RIGHT, fill=Y)
+ vbar.grid(row=1, column=2, sticky=NSEW)
text['yscrollcommand'] = vbar.set
text['font'] = idleConf.GetFont(self.root, 'main', 'EditorWindow')
- text_frame.pack(side=LEFT, fill=BOTH, expand=1)
- text.pack(side=TOP, fill=BOTH, expand=1)
+ text.grid(row=1, column=1, sticky=NSEW)
text.focus_set()
+ self.set_width()
# usetabs true -> literal tab characters are used by indent and
# dedent cmds, possibly mixed with spaces if
self.good_load = False
self.set_indentation_params(False)
self.color = None # initialized below in self.ResetColorizer
+ self.code_context = None # optionally initialized later below
+ self.line_numbers = None # optionally initialized later below
if filename:
if os.path.exists(filename) and not os.path.isdir(filename):
if io.loadfile(filename):
text.bind("<<refresh-calltip>>", ctip.refresh_calltip_event)
text.bind("<<force-open-calltip>>", ctip.force_open_calltip_event)
text.bind("<<zoom-height>>", self.ZoomHeight(self).zoom_height_event)
- text.bind("<<toggle-code-context>>",
- self.CodeContext(self).toggle_code_context_event)
+ if self.allow_code_context:
+ self.code_context = self.CodeContext(self)
+ text.bind("<<toggle-code-context>>",
+ self.code_context.toggle_code_context_event)
+ else:
+ self.update_menu_state('options', '*Code Context', 'disabled')
+ if self.allow_line_numbers:
+ self.line_numbers = self.LineNumbers(self)
+ if idleConf.GetOption('main', 'EditorWindow',
+ 'line-numbers-default', type='bool'):
+ self.toggle_line_numbers_event()
+ text.bind("<<toggle-line-numbers>>", self.toggle_line_numbers_event)
+ else:
+ self.update_menu_state('options', '*Line Numbers', 'disabled')
+
+ def handle_winconfig(self, event=None):
+ self.set_width()
+
+ def set_width(self):
+ text = self.text
+ inner_padding = sum(map(text.tk.getint, [text.cget('border'),
+ text.cget('padx')]))
+ pixel_width = text.winfo_width() - 2 * inner_padding
+
+ # Divide the width of the Text widget by the font width,
+ # which is taken to be the width of '0' (zero).
+ # http://www.tcl.tk/man/tcl8.6/TkCmd/text.htm#M21
+ zero_char_width = \
+ Font(text, font=text.cget('font')).measure('0')
+ self.width = pixel_width // zero_char_width
def _filename_to_unicode(self, filename):
"""Return filename as BMP unicode so displayable in Tk."""
self.text.yview(event, *args)
return 'break'
- def mousescroll(self, event):
- """Handle scrollwheel event.
-
- For wheel up, event.delta = 120*n on Windows, -1*n on darwin,
- where n can be > 1 if one scrolls fast. Flicking the wheel
- generates up to maybe 20 events with n up to 10 or more 1.
- Macs use wheel down (delta = 1*n) to scroll up, so positive
- delta means to scroll up on both systems.
-
- X-11 sends Control-Button-4 event instead.
- """
- up = {EventType.MouseWheel: event.delta > 0,
- EventType.Button: event.num == 4}
- lines = -5 if up[event.type] else 5
- self.text.yview_scroll(lines, 'units')
- return 'break'
-
rmenu = None
def right_menu_event(self, event):
self._addcolorizer()
EditorWindow.color_config(self.text)
+ if self.code_context is not None:
+ self.code_context.update_highlight_colors()
+
+ if self.line_numbers is not None:
+ self.line_numbers.update_colors()
+
IDENTCHARS = string.ascii_letters + string.digits + "_"
def colorize_syntax_error(self, text, pos):
"Update the text widgets' font if it is changed"
# Called from configdialog.py
- self.text['font'] = idleConf.GetFont(self.root, 'main','EditorWindow')
+ # Update the code context widget first, since its height affects
+ # the height of the text widget. This avoids double re-rendering.
+ if self.code_context is not None:
+ self.code_context.update_font()
+ # Next, update the line numbers widget, since its width affects
+ # the width of the text widget.
+ if self.line_numbers is not None:
+ self.line_numbers.update_font()
+ # Finally, update the main text widget.
+ new_font = idleConf.GetFont(self.root, 'main', 'EditorWindow')
+ self.text['font'] = new_font
+ self.set_width()
def RemoveKeybindings(self):
"Remove the keybindings before they are changed."
def update_recent_files_list(self, new_file=None):
"Load and update the recent files list and menus"
+ # TODO: move to iomenu.
rf_list = []
- if os.path.exists(self.recent_files_path):
- with open(self.recent_files_path, 'r',
+ file_path = self.recent_files_path
+ if file_path and os.path.exists(file_path):
+ with open(file_path, 'r',
encoding='utf_8', errors='replace') as rf_list_file:
rf_list = rf_list_file.readlines()
if new_file:
rf_list = [path for path in rf_list if path not in bad_paths]
ulchars = "1234567890ABCDEFGHIJK"
rf_list = rf_list[0:len(ulchars)]
- try:
- with open(self.recent_files_path, 'w',
- encoding='utf_8', errors='replace') as rf_file:
- rf_file.writelines(rf_list)
- except OSError as err:
- if not getattr(self.root, "recentfilelist_error_displayed", False):
- self.root.recentfilelist_error_displayed = True
- tkMessageBox.showwarning(title='IDLE Warning',
- message="Cannot update File menu Recent Files list. "
- "Your operating system says:\n%s\n"
- "Select OK and IDLE will continue without updating."
- % self._filename_to_unicode(str(err)),
- parent=self.text)
+ if file_path:
+ try:
+ with open(file_path, 'w',
+ encoding='utf_8', errors='replace') as rf_file:
+ rf_file.writelines(rf_list)
+ except OSError as err:
+ if not getattr(self.root, "recentfiles_message", False):
+ self.root.recentfiles_message = True
+ tkMessageBox.showwarning(title='IDLE Warning',
+ message="Cannot save Recent Files list to disk.\n"
+ f" {err}\n"
+ "Select OK to continue.",
+ parent=self.text)
# for each edit window instance, construct the recent files menu
for instance in self.top.instance_dict:
menu = instance.recent_files_menu
return self.io.maybesave()
def close(self):
- reply = self.maybesave()
- if str(reply) != "cancel":
- self._close()
- return reply
+ try:
+ reply = self.maybesave()
+ if str(reply) != "cancel":
+ self._close()
+ return reply
+ except AttributeError: # bpo-35379: close called twice
+ pass
def _close(self):
if self.io.filename:
try:
if first and last:
if index2line(first) != index2line(last):
- return self.indent_region_event(event)
+ return self.fregion.indent_region_event(event)
text.delete(first, last)
text.mark_set("insert", first)
prefix = text.get("insert linestart", "insert")
- raw, effective = classifyws(prefix, self.tabwidth)
+ raw, effective = get_line_indent(prefix, self.tabwidth)
if raw == len(prefix):
# only whitespace to the left
self.reindent_to(effective + self.indentwidth)
return _icis(_startindex + "+%dc" % offset)
return inner
- def indent_region_event(self, event):
- head, tail, chars, lines = self.get_region()
- for pos in range(len(lines)):
- line = lines[pos]
- if line:
- raw, effective = classifyws(line, self.tabwidth)
- effective = effective + self.indentwidth
- lines[pos] = self._make_blanks(effective) + line[raw:]
- self.set_region(head, tail, chars, lines)
- return "break"
-
- def dedent_region_event(self, event):
- head, tail, chars, lines = self.get_region()
- for pos in range(len(lines)):
- line = lines[pos]
- if line:
- raw, effective = classifyws(line, self.tabwidth)
- effective = max(effective - self.indentwidth, 0)
- lines[pos] = self._make_blanks(effective) + line[raw:]
- self.set_region(head, tail, chars, lines)
- return "break"
-
- def comment_region_event(self, event):
- head, tail, chars, lines = self.get_region()
- for pos in range(len(lines) - 1):
- line = lines[pos]
- lines[pos] = '##' + line
- self.set_region(head, tail, chars, lines)
- return "break"
-
- def uncomment_region_event(self, event):
- head, tail, chars, lines = self.get_region()
- for pos in range(len(lines)):
- line = lines[pos]
- if not line:
- continue
- if line[:2] == '##':
- line = line[2:]
- elif line[:1] == '#':
- line = line[1:]
- lines[pos] = line
- self.set_region(head, tail, chars, lines)
- return "break"
-
- def tabify_region_event(self, event):
- head, tail, chars, lines = self.get_region()
- tabwidth = self._asktabwidth()
- if tabwidth is None: return
- for pos in range(len(lines)):
- line = lines[pos]
- if line:
- raw, effective = classifyws(line, tabwidth)
- ntabs, nspaces = divmod(effective, tabwidth)
- lines[pos] = '\t' * ntabs + ' ' * nspaces + line[raw:]
- self.set_region(head, tail, chars, lines)
- return "break"
-
- def untabify_region_event(self, event):
- head, tail, chars, lines = self.get_region()
- tabwidth = self._asktabwidth()
- if tabwidth is None: return
- for pos in range(len(lines)):
- lines[pos] = lines[pos].expandtabs(tabwidth)
- self.set_region(head, tail, chars, lines)
- return "break"
-
- def toggle_tabs_event(self, event):
- if self.askyesno(
- "Toggle tabs",
- "Turn tabs " + ("on", "off")[self.usetabs] +
- "?\nIndent width " +
- ("will be", "remains at")[self.usetabs] + " 8." +
- "\n Note: a tab is always 8 columns",
- parent=self.text):
- self.usetabs = not self.usetabs
- # Try to prevent inconsistent indentation.
- # User must change indent width manually after using tabs.
- self.indentwidth = 8
- return "break"
-
# XXX this isn't bound to anything -- see tabwidth comments
## def change_tabwidth_event(self, event):
## new = self._asktabwidth()
## self.set_indentation_params(0, guess=0)
## return "break"
- def change_indentwidth_event(self, event):
- new = self.askinteger(
- "Indent width",
- "New indent width (2-16)\n(Always use 8 when using tabs)",
- parent=self.text,
- initialvalue=self.indentwidth,
- minvalue=2,
- maxvalue=16)
- if new and new != self.indentwidth and not self.usetabs:
- self.indentwidth = new
- return "break"
-
- def get_region(self):
- text = self.text
- first, last = self.get_selection_indices()
- if first and last:
- head = text.index(first + " linestart")
- tail = text.index(last + "-1c lineend +1c")
- else:
- head = text.index("insert linestart")
- tail = text.index("insert lineend +1c")
- chars = text.get(head, tail)
- lines = chars.split("\n")
- return head, tail, chars, lines
-
- def set_region(self, head, tail, chars, lines):
- text = self.text
- newchars = "\n".join(lines)
- if newchars == chars:
- text.bell()
- return
- text.tag_remove("sel", "1.0", "end")
- text.mark_set("insert", head)
- text.undo_block_start()
- text.delete(head, tail)
- text.insert(head, newchars)
- text.undo_block_stop()
- text.tag_add("sel", head, "insert")
-
# Make string that displays as n leading blanks.
def _make_blanks(self, n):
text.insert("insert", self._make_blanks(column))
text.undo_block_stop()
- def _asktabwidth(self):
- return self.askinteger(
- "Tab width",
- "Columns per tab? (2-16)",
- parent=self.text,
- initialvalue=self.indentwidth,
- minvalue=2,
- maxvalue=16)
-
# Guess indentwidth from text content.
# Return guessed indentwidth. This should not be believed unless
# it's in a reasonable range (e.g., it will be 0 if no indented
def guess_indent(self):
opener, indented = IndentSearcher(self.text, self.tabwidth).run()
if opener and indented:
- raw, indentsmall = classifyws(opener, self.tabwidth)
- raw, indentlarge = classifyws(indented, self.tabwidth)
+ raw, indentsmall = get_line_indent(opener, self.tabwidth)
+ raw, indentlarge = get_line_indent(indented, self.tabwidth)
else:
indentsmall = indentlarge = 0
return indentlarge - indentsmall
+ def toggle_line_numbers_event(self, event=None):
+ if self.line_numbers is None:
+ return
+
+ if self.line_numbers.is_shown:
+ self.line_numbers.hide_sidebar()
+ menu_label = "Show"
+ else:
+ self.line_numbers.show_sidebar()
+ menu_label = "Hide"
+ self.update_menu_label(menu='options', index='*Line Numbers',
+ label=f'{menu_label} Line Numbers')
+
# "line.col" -> line, as an int
def index2line(index):
return int(float(index))
-# Look at the leading whitespace in s.
-# Return pair (# of leading ws characters,
-# effective # of leading blanks after expanding
-# tabs to width tabwidth)
-
-def classifyws(s, tabwidth):
- raw = effective = 0
- for ch in s:
- if ch == ' ':
- raw = raw + 1
- effective = effective + 1
- elif ch == '\t':
- raw = raw + 1
- effective = (effective // tabwidth + 1) * tabwidth
- else:
- break
- return raw, effective
+
+_line_indent_re = re.compile(r'[ \t]*')
+def get_line_indent(line, tabwidth):
+ """Return a line's indentation as (# chars, effective # of spaces).
+
+ The effective # of spaces is the length after properly "expanding"
+ the tabs into spaces, as done by str.expandtabs(tabwidth).
+ """
+ m = _line_indent_re.match(line)
+ return m.end(), len(m.group().expandtabs(tabwidth))
class IndentSearcher(object):
--- /dev/null
+"""Format all or a selected region (line slice) of text.
+
+Region formatting options: paragraph, comment block, indent, deindent,
+comment, uncomment, tabify, and untabify.
+
+File renamed from paragraph.py with functions added from editor.py.
+"""
+import re
+from tkinter.messagebox import askyesno
+from tkinter.simpledialog import askinteger
+from idlelib.config import idleConf
+
+
+class FormatParagraph:
+ """Format a paragraph, comment block, or selection to a max width.
+
+ Does basic, standard text formatting, and also understands Python
+ comment blocks. Thus, for editing Python source code, this
+ extension is really only suitable for reformatting these comment
+ blocks or triple-quoted strings.
+
+ Known problems with comment reformatting:
+ * If there is a selection marked, and the first line of the
+ selection is not complete, the block will probably not be detected
+ as comments, and will have the normal "text formatting" rules
+ applied.
+ * If a comment block has leading whitespace that mixes tabs and
+ spaces, they will not be considered part of the same block.
+ * Fancy comments, like this bulleted list, aren't handled :-)
+ """
+ def __init__(self, editwin):
+ self.editwin = editwin
+
+ @classmethod
+ def reload(cls):
+ cls.max_width = idleConf.GetOption('extensions', 'FormatParagraph',
+ 'max-width', type='int', default=72)
+
+ def close(self):
+ self.editwin = None
+
+ def format_paragraph_event(self, event, limit=None):
+ """Formats paragraph to a max width specified in idleConf.
+
+ If text is selected, format_paragraph_event will start breaking lines
+ at the max width, starting from the beginning selection.
+
+ If no text is selected, format_paragraph_event uses the current
+ cursor location to determine the paragraph (lines of text surrounded
+ by blank lines) and formats it.
+
+ The length limit parameter is for testing with a known value.
+ """
+ limit = self.max_width if limit is None else limit
+ text = self.editwin.text
+ first, last = self.editwin.get_selection_indices()
+ if first and last:
+ data = text.get(first, last)
+ comment_header = get_comment_header(data)
+ else:
+ first, last, comment_header, data = \
+ find_paragraph(text, text.index("insert"))
+ if comment_header:
+ newdata = reformat_comment(data, limit, comment_header)
+ else:
+ newdata = reformat_paragraph(data, limit)
+ text.tag_remove("sel", "1.0", "end")
+
+ if newdata != data:
+ text.mark_set("insert", first)
+ text.undo_block_start()
+ text.delete(first, last)
+ text.insert(first, newdata)
+ text.undo_block_stop()
+ else:
+ text.mark_set("insert", last)
+ text.see("insert")
+ return "break"
+
+
+FormatParagraph.reload()
+
+def find_paragraph(text, mark):
+ """Returns the start/stop indices enclosing the paragraph that mark is in.
+
+ Also returns the comment format string, if any, and paragraph of text
+ between the start/stop indices.
+ """
+ lineno, col = map(int, mark.split("."))
+ line = text.get("%d.0" % lineno, "%d.end" % lineno)
+
+ # Look for start of next paragraph if the index passed in is a blank line
+ while text.compare("%d.0" % lineno, "<", "end") and is_all_white(line):
+ lineno = lineno + 1
+ line = text.get("%d.0" % lineno, "%d.end" % lineno)
+ first_lineno = lineno
+ comment_header = get_comment_header(line)
+ comment_header_len = len(comment_header)
+
+ # Once start line found, search for end of paragraph (a blank line)
+ while get_comment_header(line)==comment_header and \
+ not is_all_white(line[comment_header_len:]):
+ lineno = lineno + 1
+ line = text.get("%d.0" % lineno, "%d.end" % lineno)
+ last = "%d.0" % lineno
+
+ # Search back to beginning of paragraph (first blank line before)
+ lineno = first_lineno - 1
+ line = text.get("%d.0" % lineno, "%d.end" % lineno)
+ while lineno > 0 and \
+ get_comment_header(line)==comment_header and \
+ not is_all_white(line[comment_header_len:]):
+ lineno = lineno - 1
+ line = text.get("%d.0" % lineno, "%d.end" % lineno)
+ first = "%d.0" % (lineno+1)
+
+ return first, last, comment_header, text.get(first, last)
+
+# This should perhaps be replaced with textwrap.wrap
+def reformat_paragraph(data, limit):
+ """Return data reformatted to specified width (limit)."""
+ lines = data.split("\n")
+ i = 0
+ n = len(lines)
+ while i < n and is_all_white(lines[i]):
+ i = i+1
+ if i >= n:
+ return data
+ indent1 = get_indent(lines[i])
+ if i+1 < n and not is_all_white(lines[i+1]):
+ indent2 = get_indent(lines[i+1])
+ else:
+ indent2 = indent1
+ new = lines[:i]
+ partial = indent1
+ while i < n and not is_all_white(lines[i]):
+ # XXX Should take double space after period (etc.) into account
+ words = re.split(r"(\s+)", lines[i])
+ for j in range(0, len(words), 2):
+ word = words[j]
+ if not word:
+ continue # Can happen when line ends in whitespace
+ if len((partial + word).expandtabs()) > limit and \
+ partial != indent1:
+ new.append(partial.rstrip())
+ partial = indent2
+ partial = partial + word + " "
+ if j+1 < len(words) and words[j+1] != " ":
+ partial = partial + " "
+ i = i+1
+ new.append(partial.rstrip())
+ # XXX Should reformat remaining paragraphs as well
+ new.extend(lines[i:])
+ return "\n".join(new)
+
+def reformat_comment(data, limit, comment_header):
+ """Return data reformatted to specified width with comment header."""
+
+ # Remove header from the comment lines
+ lc = len(comment_header)
+ data = "\n".join(line[lc:] for line in data.split("\n"))
+ # Reformat to maxformatwidth chars or a 20 char width,
+ # whichever is greater.
+ format_width = max(limit - len(comment_header), 20)
+ newdata = reformat_paragraph(data, format_width)
+ # re-split and re-insert the comment header.
+ newdata = newdata.split("\n")
+ # If the block ends in a \n, we don't want the comment prefix
+ # inserted after it. (Im not sure it makes sense to reformat a
+ # comment block that is not made of complete lines, but whatever!)
+ # Can't think of a clean solution, so we hack away
+ block_suffix = ""
+ if not newdata[-1]:
+ block_suffix = "\n"
+ newdata = newdata[:-1]
+ return '\n'.join(comment_header+line for line in newdata) + block_suffix
+
+def is_all_white(line):
+ """Return True if line is empty or all whitespace."""
+
+ return re.match(r"^\s*$", line) is not None
+
+def get_indent(line):
+ """Return the initial space or tab indent of line."""
+ return re.match(r"^([ \t]*)", line).group()
+
+def get_comment_header(line):
+ """Return string with leading whitespace and '#' from line or ''.
+
+ A null return indicates that the line is not a comment line. A non-
+ null return, such as ' #', will be used to find the other lines of
+ a comment block with the same indent.
+ """
+ m = re.match(r"^([ \t]*#*)", line)
+ if m is None: return ""
+ return m.group(1)
+
+
+# Copied from editor.py; importing it would cause an import cycle.
+_line_indent_re = re.compile(r'[ \t]*')
+
+def get_line_indent(line, tabwidth):
+ """Return a line's indentation as (# chars, effective # of spaces).
+
+ The effective # of spaces is the length after properly "expanding"
+ the tabs into spaces, as done by str.expandtabs(tabwidth).
+ """
+ m = _line_indent_re.match(line)
+ return m.end(), len(m.group().expandtabs(tabwidth))
+
+
+class FormatRegion:
+ "Format selected text (region)."
+
+ def __init__(self, editwin):
+ self.editwin = editwin
+
+ def get_region(self):
+ """Return line information about the selected text region.
+
+ If text is selected, the first and last indices will be
+ for the selection. If there is no text selected, the
+ indices will be the current cursor location.
+
+ Return a tuple containing (first index, last index,
+ string representation of text, list of text lines).
+ """
+ text = self.editwin.text
+ first, last = self.editwin.get_selection_indices()
+ if first and last:
+ head = text.index(first + " linestart")
+ tail = text.index(last + "-1c lineend +1c")
+ else:
+ head = text.index("insert linestart")
+ tail = text.index("insert lineend +1c")
+ chars = text.get(head, tail)
+ lines = chars.split("\n")
+ return head, tail, chars, lines
+
+ def set_region(self, head, tail, chars, lines):
+ """Replace the text between the given indices.
+
+ Args:
+ head: Starting index of text to replace.
+ tail: Ending index of text to replace.
+ chars: Expected to be string of current text
+ between head and tail.
+ lines: List of new lines to insert between head
+ and tail.
+ """
+ text = self.editwin.text
+ newchars = "\n".join(lines)
+ if newchars == chars:
+ text.bell()
+ return
+ text.tag_remove("sel", "1.0", "end")
+ text.mark_set("insert", head)
+ text.undo_block_start()
+ text.delete(head, tail)
+ text.insert(head, newchars)
+ text.undo_block_stop()
+ text.tag_add("sel", head, "insert")
+
+ def indent_region_event(self, event=None):
+ "Indent region by indentwidth spaces."
+ head, tail, chars, lines = self.get_region()
+ for pos in range(len(lines)):
+ line = lines[pos]
+ if line:
+ raw, effective = get_line_indent(line, self.editwin.tabwidth)
+ effective = effective + self.editwin.indentwidth
+ lines[pos] = self.editwin._make_blanks(effective) + line[raw:]
+ self.set_region(head, tail, chars, lines)
+ return "break"
+
+ def dedent_region_event(self, event=None):
+ "Dedent region by indentwidth spaces."
+ head, tail, chars, lines = self.get_region()
+ for pos in range(len(lines)):
+ line = lines[pos]
+ if line:
+ raw, effective = get_line_indent(line, self.editwin.tabwidth)
+ effective = max(effective - self.editwin.indentwidth, 0)
+ lines[pos] = self.editwin._make_blanks(effective) + line[raw:]
+ self.set_region(head, tail, chars, lines)
+ return "break"
+
+ def comment_region_event(self, event=None):
+ """Comment out each line in region.
+
+ ## is appended to the beginning of each line to comment it out.
+ """
+ head, tail, chars, lines = self.get_region()
+ for pos in range(len(lines) - 1):
+ line = lines[pos]
+ lines[pos] = '##' + line
+ self.set_region(head, tail, chars, lines)
+ return "break"
+
+ def uncomment_region_event(self, event=None):
+ """Uncomment each line in region.
+
+ Remove ## or # in the first positions of a line. If the comment
+ is not in the beginning position, this command will have no effect.
+ """
+ head, tail, chars, lines = self.get_region()
+ for pos in range(len(lines)):
+ line = lines[pos]
+ if not line:
+ continue
+ if line[:2] == '##':
+ line = line[2:]
+ elif line[:1] == '#':
+ line = line[1:]
+ lines[pos] = line
+ self.set_region(head, tail, chars, lines)
+ return "break"
+
+ def tabify_region_event(self, event=None):
+ "Convert leading spaces to tabs for each line in selected region."
+ head, tail, chars, lines = self.get_region()
+ tabwidth = self._asktabwidth()
+ if tabwidth is None:
+ return
+ for pos in range(len(lines)):
+ line = lines[pos]
+ if line:
+ raw, effective = get_line_indent(line, tabwidth)
+ ntabs, nspaces = divmod(effective, tabwidth)
+ lines[pos] = '\t' * ntabs + ' ' * nspaces + line[raw:]
+ self.set_region(head, tail, chars, lines)
+ return "break"
+
+ def untabify_region_event(self, event=None):
+ "Expand tabs to spaces for each line in region."
+ head, tail, chars, lines = self.get_region()
+ tabwidth = self._asktabwidth()
+ if tabwidth is None:
+ return
+ for pos in range(len(lines)):
+ lines[pos] = lines[pos].expandtabs(tabwidth)
+ self.set_region(head, tail, chars, lines)
+ return "break"
+
+ def _asktabwidth(self):
+ "Return value for tab width."
+ return askinteger(
+ "Tab width",
+ "Columns per tab? (2-16)",
+ parent=self.editwin.text,
+ initialvalue=self.editwin.indentwidth,
+ minvalue=2,
+ maxvalue=16)
+
+
+# With mixed indents not allowed, these are semi-useless and not unittested.
+class Indents: # pragma: no cover
+ "Change future indents."
+
+ def __init__(self, editwin):
+ self.editwin = editwin
+
+ def toggle_tabs_event(self, event):
+ editwin = self.editwin
+ usetabs = editwin.usetabs
+ if askyesno(
+ "Toggle tabs",
+ "Turn tabs " + ("on", "off")[usetabs] +
+ "?\nIndent width " +
+ ("will be", "remains at")[usetabs] + " 8." +
+ "\n Note: a tab is always 8 columns",
+ parent=editwin.text):
+ editwin.usetabs = not usetabs
+ # Try to prevent inconsistent indentation.
+ # User must change indent width manually after using tabs.
+ editwin.indentwidth = 8
+ return "break"
+
+ def change_indentwidth_event(self, event):
+ editwin = self.editwin
+ new = askinteger(
+ "Indent width",
+ "New indent width (2-16)\n(Always use 8 when using tabs)",
+ parent=editwin.text,
+ initialvalue=editwin.indentwidth,
+ minvalue=2,
+ maxvalue=16)
+ if new and new != editwin.indentwidth and not editwin.usetabs:
+ editwin.indentwidth = new
+ return "break"
+
+
+class Rstrip: # 'Strip Trailing Whitespace" on "Format" menu.
+ def __init__(self, editwin):
+ self.editwin = editwin
+
+ def do_rstrip(self, event=None):
+ text = self.editwin.text
+ undo = self.editwin.undo
+ undo.undo_block_start()
+
+ end_line = int(float(text.index('end')))
+ for cur in range(1, end_line):
+ txt = text.get('%i.0' % cur, '%i.end' % cur)
+ raw = len(txt)
+ cut = len(txt.rstrip())
+ # Since text.delete() marks file as changed, even if not,
+ # only call it when needed to actually delete something.
+ if cut < raw:
+ text.delete('%i.%i' % (cur, cut), '%i.end' % cur)
+
+ undo.undo_block_stop()
+
+
+if __name__ == "__main__":
+ from unittest import main
+ main('idlelib.idle_test.test_format', verbosity=2, exit=False)
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
- <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <meta charset="utf-8" />
<title>IDLE — Python 3.9.0a0 documentation</title>
<link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script type="text/javascript" src="../_static/jquery.js"></script>
<script type="text/javascript" src="../_static/underscore.js"></script>
<script type="text/javascript" src="../_static/doctools.js"></script>
- <script async="async" type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
+ <script type="text/javascript" src="../_static/language_data.js"></script>
<script type="text/javascript" src="../_static/sidebar.js"></script>
<p>IDLE is Python’s Integrated Development and Learning Environment.</p>
<p>IDLE has the following features:</p>
<ul class="simple">
-<li>coded in 100% pure Python, using the <a class="reference internal" href="tkinter.html#module-tkinter" title="tkinter: Interface to Tcl/Tk for graphical user interfaces"><code class="xref py py-mod docutils literal notranslate"><span class="pre">tkinter</span></code></a> GUI toolkit</li>
-<li>cross-platform: works mostly the same on Windows, Unix, and macOS</li>
-<li>Python shell window (interactive interpreter) with colorizing
-of code input, output, and error messages</li>
-<li>multi-window text editor with multiple undo, Python colorizing,
-smart indent, call tips, auto completion, and other features</li>
-<li>search within any window, replace within editor windows, and search
-through multiple files (grep)</li>
-<li>debugger with persistent breakpoints, stepping, and viewing
-of global and local namespaces</li>
-<li>configuration, browsers, and other dialogs</li>
+<li><p>coded in 100% pure Python, using the <a class="reference internal" href="tkinter.html#module-tkinter" title="tkinter: Interface to Tcl/Tk for graphical user interfaces"><code class="xref py py-mod docutils literal notranslate"><span class="pre">tkinter</span></code></a> GUI toolkit</p></li>
+<li><p>cross-platform: works mostly the same on Windows, Unix, and macOS</p></li>
+<li><p>Python shell window (interactive interpreter) with colorizing
+of code input, output, and error messages</p></li>
+<li><p>multi-window text editor with multiple undo, Python colorizing,
+smart indent, call tips, auto completion, and other features</p></li>
+<li><p>search within any window, replace within editor windows, and search
+through multiple files (grep)</p></li>
+<li><p>debugger with persistent breakpoints, stepping, and viewing
+of global and local namespaces</p></li>
+<li><p>configuration, browsers, and other dialogs</p></li>
</ul>
<div class="section" id="menus">
<h2>Menus<a class="headerlink" href="#menus" title="Permalink to this headline">¶</a></h2>
described below are moved around to conform to Apple guidelines.</p>
<div class="section" id="file-menu-shell-and-editor">
<h3>File menu (Shell and Editor)<a class="headerlink" href="#file-menu-shell-and-editor" title="Permalink to this headline">¶</a></h3>
-<dl class="docutils">
-<dt>New File</dt>
-<dd>Create a new file editing window.</dd>
-<dt>Open…</dt>
-<dd>Open an existing file with an Open dialog.</dd>
-<dt>Recent Files</dt>
-<dd>Open a list of recent files. Click one to open it.</dd>
-<dt>Open Module…</dt>
-<dd>Open an existing module (searches sys.path).</dd>
+<dl class="simple">
+<dt>New File</dt><dd><p>Create a new file editing window.</p>
+</dd>
+<dt>Open…</dt><dd><p>Open an existing file with an Open dialog.</p>
+</dd>
+<dt>Recent Files</dt><dd><p>Open a list of recent files. Click one to open it.</p>
+</dd>
+<dt>Open Module…</dt><dd><p>Open an existing module (searches sys.path).</p>
+</dd>
</dl>
-<dl class="docutils" id="index-1">
-<dt>Class Browser</dt>
-<dd>Show functions, classes, and methods in the current Editor file in a
-tree structure. In the shell, open a module first.</dd>
-<dt>Path Browser</dt>
-<dd>Show sys.path directories, modules, functions, classes and methods in a
-tree structure.</dd>
-<dt>Save</dt>
-<dd>Save the current window to the associated file, if there is one. Windows
+<dl class="simple" id="index-1">
+<dt>Class Browser</dt><dd><p>Show functions, classes, and methods in the current Editor file in a
+tree structure. In the shell, open a module first.</p>
+</dd>
+<dt>Path Browser</dt><dd><p>Show sys.path directories, modules, functions, classes and methods in a
+tree structure.</p>
+</dd>
+<dt>Save</dt><dd><p>Save the current window to the associated file, if there is one. Windows
that have been changed since being opened or last saved have a * before
and after the window title. If there is no associated file,
-do Save As instead.</dd>
-<dt>Save As…</dt>
-<dd>Save the current window with a Save As dialog. The file saved becomes the
-new associated file for the window.</dd>
-<dt>Save Copy As…</dt>
-<dd>Save the current window to different file without changing the associated
-file.</dd>
-<dt>Print Window</dt>
-<dd>Print the current window to the default printer.</dd>
-<dt>Close</dt>
-<dd>Close the current window (ask to save if unsaved).</dd>
-<dt>Exit</dt>
-<dd>Close all windows and quit IDLE (ask to save unsaved windows).</dd>
+do Save As instead.</p>
+</dd>
+<dt>Save As…</dt><dd><p>Save the current window with a Save As dialog. The file saved becomes the
+new associated file for the window.</p>
+</dd>
+<dt>Save Copy As…</dt><dd><p>Save the current window to different file without changing the associated
+file.</p>
+</dd>
+<dt>Print Window</dt><dd><p>Print the current window to the default printer.</p>
+</dd>
+<dt>Close</dt><dd><p>Close the current window (ask to save if unsaved).</p>
+</dd>
+<dt>Exit</dt><dd><p>Close all windows and quit IDLE (ask to save unsaved windows).</p>
+</dd>
</dl>
</div>
<div class="section" id="edit-menu-shell-and-editor">
<h3>Edit menu (Shell and Editor)<a class="headerlink" href="#edit-menu-shell-and-editor" title="Permalink to this headline">¶</a></h3>
-<dl class="docutils">
-<dt>Undo</dt>
-<dd>Undo the last change to the current window. A maximum of 1000 changes may
-be undone.</dd>
-<dt>Redo</dt>
-<dd>Redo the last undone change to the current window.</dd>
-<dt>Cut</dt>
-<dd>Copy selection into the system-wide clipboard; then delete the selection.</dd>
-<dt>Copy</dt>
-<dd>Copy selection into the system-wide clipboard.</dd>
-<dt>Paste</dt>
-<dd>Insert contents of the system-wide clipboard into the current window.</dd>
+<dl class="simple">
+<dt>Undo</dt><dd><p>Undo the last change to the current window. A maximum of 1000 changes may
+be undone.</p>
+</dd>
+<dt>Redo</dt><dd><p>Redo the last undone change to the current window.</p>
+</dd>
+<dt>Cut</dt><dd><p>Copy selection into the system-wide clipboard; then delete the selection.</p>
+</dd>
+<dt>Copy</dt><dd><p>Copy selection into the system-wide clipboard.</p>
+</dd>
+<dt>Paste</dt><dd><p>Insert contents of the system-wide clipboard into the current window.</p>
+</dd>
</dl>
<p>The clipboard functions are also available in context menus.</p>
-<dl class="docutils">
-<dt>Select All</dt>
-<dd>Select the entire contents of the current window.</dd>
-<dt>Find…</dt>
-<dd>Open a search dialog with many options</dd>
-<dt>Find Again</dt>
-<dd>Repeat the last search, if there is one.</dd>
-<dt>Find Selection</dt>
-<dd>Search for the currently selected string, if there is one.</dd>
-<dt>Find in Files…</dt>
-<dd>Open a file search dialog. Put results in a new output window.</dd>
-<dt>Replace…</dt>
-<dd>Open a search-and-replace dialog.</dd>
-<dt>Go to Line</dt>
-<dd>Move cursor to the line number requested and make that line visible.</dd>
-<dt>Show Completions</dt>
-<dd>Open a scrollable list allowing selection of keywords and attributes. See
-<a class="reference internal" href="#completions"><span class="std std-ref">Completions</span></a> in the Editing and navigation section below.</dd>
-<dt>Expand Word</dt>
-<dd>Expand a prefix you have typed to match a full word in the same window;
-repeat to get a different expansion.</dd>
-<dt>Show call tip</dt>
-<dd>After an unclosed parenthesis for a function, open a small window with
+<dl class="simple">
+<dt>Select All</dt><dd><p>Select the entire contents of the current window.</p>
+</dd>
+<dt>Find…</dt><dd><p>Open a search dialog with many options</p>
+</dd>
+<dt>Find Again</dt><dd><p>Repeat the last search, if there is one.</p>
+</dd>
+<dt>Find Selection</dt><dd><p>Search for the currently selected string, if there is one.</p>
+</dd>
+<dt>Find in Files…</dt><dd><p>Open a file search dialog. Put results in a new output window.</p>
+</dd>
+<dt>Replace…</dt><dd><p>Open a search-and-replace dialog.</p>
+</dd>
+<dt>Go to Line</dt><dd><p>Move cursor to the line number requested and make that line visible.</p>
+</dd>
+<dt>Show Completions</dt><dd><p>Open a scrollable list allowing selection of keywords and attributes. See
+<a class="reference internal" href="#completions"><span class="std std-ref">Completions</span></a> in the Editing and navigation section below.</p>
+</dd>
+<dt>Expand Word</dt><dd><p>Expand a prefix you have typed to match a full word in the same window;
+repeat to get a different expansion.</p>
+</dd>
+<dt>Show call tip</dt><dd><p>After an unclosed parenthesis for a function, open a small window with
function parameter hints. See <a class="reference internal" href="#calltips"><span class="std std-ref">Calltips</span></a> in the
-Editing and navigation section below.</dd>
-<dt>Show surrounding parens</dt>
-<dd>Highlight the surrounding parenthesis.</dd>
+Editing and navigation section below.</p>
+</dd>
+<dt>Show surrounding parens</dt><dd><p>Highlight the surrounding parenthesis.</p>
+</dd>
</dl>
</div>
<div class="section" id="format-menu-editor-window-only">
<span id="format-menu"></span><h3>Format menu (Editor window only)<a class="headerlink" href="#format-menu-editor-window-only" title="Permalink to this headline">¶</a></h3>
-<dl class="docutils">
-<dt>Indent Region</dt>
-<dd>Shift selected lines right by the indent width (default 4 spaces).</dd>
-<dt>Dedent Region</dt>
-<dd>Shift selected lines left by the indent width (default 4 spaces).</dd>
-<dt>Comment Out Region</dt>
-<dd>Insert ## in front of selected lines.</dd>
-<dt>Uncomment Region</dt>
-<dd>Remove leading # or ## from selected lines.</dd>
-<dt>Tabify Region</dt>
-<dd>Turn <em>leading</em> stretches of spaces into tabs. (Note: We recommend using
-4 space blocks to indent Python code.)</dd>
-<dt>Untabify Region</dt>
-<dd>Turn <em>all</em> tabs into the correct number of spaces.</dd>
-<dt>Toggle Tabs</dt>
-<dd>Open a dialog to switch between indenting with spaces and tabs.</dd>
-<dt>New Indent Width</dt>
-<dd>Open a dialog to change indent width. The accepted default by the Python
-community is 4 spaces.</dd>
-<dt>Format Paragraph</dt>
-<dd>Reformat the current blank-line-delimited paragraph in comment block or
+<dl class="simple">
+<dt>Indent Region</dt><dd><p>Shift selected lines right by the indent width (default 4 spaces).</p>
+</dd>
+<dt>Dedent Region</dt><dd><p>Shift selected lines left by the indent width (default 4 spaces).</p>
+</dd>
+<dt>Comment Out Region</dt><dd><p>Insert ## in front of selected lines.</p>
+</dd>
+<dt>Uncomment Region</dt><dd><p>Remove leading # or ## from selected lines.</p>
+</dd>
+<dt>Tabify Region</dt><dd><p>Turn <em>leading</em> stretches of spaces into tabs. (Note: We recommend using
+4 space blocks to indent Python code.)</p>
+</dd>
+<dt>Untabify Region</dt><dd><p>Turn <em>all</em> tabs into the correct number of spaces.</p>
+</dd>
+<dt>Toggle Tabs</dt><dd><p>Open a dialog to switch between indenting with spaces and tabs.</p>
+</dd>
+<dt>New Indent Width</dt><dd><p>Open a dialog to change indent width. The accepted default by the Python
+community is 4 spaces.</p>
+</dd>
+<dt>Format Paragraph</dt><dd><p>Reformat the current blank-line-delimited paragraph in comment block or
multiline string or selected line in a string. All lines in the
-paragraph will be formatted to less than N columns, where N defaults to 72.</dd>
-<dt>Strip trailing whitespace</dt>
-<dd>Remove trailing space and other whitespace characters after the last
+paragraph will be formatted to less than N columns, where N defaults to 72.</p>
+</dd>
+<dt>Strip trailing whitespace</dt><dd><p>Remove trailing space and other whitespace characters after the last
non-whitespace character of a line by applying str.rstrip to each line,
-including lines within multiline strings.</dd>
+including lines within multiline strings.</p>
+</dd>
</dl>
</div>
<div class="section" id="run-menu-editor-window-only">
<span id="index-2"></span><h3>Run menu (Editor window only)<a class="headerlink" href="#run-menu-editor-window-only" title="Permalink to this headline">¶</a></h3>
-<dl class="docutils" id="python-shell">
-<dt>Python Shell</dt>
-<dd>Open or wake up the Python Shell window.</dd>
-</dl>
-<dl class="docutils" id="check-module">
-<dt>Check Module</dt>
-<dd>Check the syntax of the module currently open in the Editor window. If the
-module has not been saved IDLE will either prompt the user to save or
-autosave, as selected in the General tab of the Idle Settings dialog. If
-there is a syntax error, the approximate location is indicated in the
-Editor window.</dd>
-</dl>
-<dl class="docutils" id="run-module">
-<dt>Run Module</dt>
-<dd>Do <a class="reference internal" href="#check-module"><span class="std std-ref">Check Module</span></a>. If no error, restart the shell to clean the
+<dl class="simple" id="run-module">
+<dt>Run Module</dt><dd><p>Do <a class="reference internal" href="#check-module"><span class="std std-ref">Check Module</span></a>. If no error, restart the shell to clean the
environment, then execute the module. Output is displayed in the Shell
window. Note that output requires use of <code class="docutils literal notranslate"><span class="pre">print</span></code> or <code class="docutils literal notranslate"><span class="pre">write</span></code>.
When execution is complete, the Shell retains focus and displays a prompt.
At this point, one may interactively explore the result of execution.
This is similar to executing a file with <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-i</span> <span class="pre">file</span></code> at a command
-line.</dd>
+line.</p>
+</dd>
</dl>
-<dl class="docutils" id="run-custom">
-<dt>Run… Customized</dt>
-<dd>Same as <a class="reference internal" href="#run-module"><span class="std std-ref">Run Module</span></a>, but run the module with customized
+<dl class="simple" id="run-custom">
+<dt>Run… Customized</dt><dd><p>Same as <a class="reference internal" href="#run-module"><span class="std std-ref">Run Module</span></a>, but run the module with customized
settings. <em>Command Line Arguments</em> extend <a class="reference internal" href="sys.html#sys.argv" title="sys.argv"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.argv</span></code></a> as if passed
-on a command line. The module can be run in the Shell without restarting.</dd>
+on a command line. The module can be run in the Shell without restarting.</p>
+</dd>
+</dl>
+<dl class="simple" id="check-module">
+<dt>Check Module</dt><dd><p>Check the syntax of the module currently open in the Editor window. If the
+module has not been saved IDLE will either prompt the user to save or
+autosave, as selected in the General tab of the Idle Settings dialog. If
+there is a syntax error, the approximate location is indicated in the
+Editor window.</p>
+</dd>
+</dl>
+<dl class="simple" id="python-shell">
+<dt>Python Shell</dt><dd><p>Open or wake up the Python Shell window.</p>
+</dd>
</dl>
</div>
<div class="section" id="shell-menu-shell-window-only">
<h3>Shell menu (Shell window only)<a class="headerlink" href="#shell-menu-shell-window-only" title="Permalink to this headline">¶</a></h3>
-<dl class="docutils">
-<dt>View Last Restart</dt>
-<dd>Scroll the shell window to the last Shell restart.</dd>
-<dt>Restart Shell</dt>
-<dd>Restart the shell to clean the environment.</dd>
-<dt>Previous History</dt>
-<dd>Cycle through earlier commands in history which match the current entry.</dd>
-<dt>Next History</dt>
-<dd>Cycle through later commands in history which match the current entry.</dd>
-<dt>Interrupt Execution</dt>
-<dd>Stop a running program.</dd>
+<dl class="simple">
+<dt>View Last Restart</dt><dd><p>Scroll the shell window to the last Shell restart.</p>
+</dd>
+<dt>Restart Shell</dt><dd><p>Restart the shell to clean the environment.</p>
+</dd>
+<dt>Previous History</dt><dd><p>Cycle through earlier commands in history which match the current entry.</p>
+</dd>
+<dt>Next History</dt><dd><p>Cycle through later commands in history which match the current entry.</p>
+</dd>
+<dt>Interrupt Execution</dt><dd><p>Stop a running program.</p>
+</dd>
</dl>
</div>
<div class="section" id="debug-menu-shell-window-only">
<h3>Debug menu (Shell window only)<a class="headerlink" href="#debug-menu-shell-window-only" title="Permalink to this headline">¶</a></h3>
-<dl class="docutils">
-<dt>Go to File/Line</dt>
-<dd>Look on the current line. with the cursor, and the line above for a filename
+<dl class="simple">
+<dt>Go to File/Line</dt><dd><p>Look on the current line. with the cursor, and the line above for a filename
and line number. If found, open the file if not already open, and show the
line. Use this to view source lines referenced in an exception traceback
and lines found by Find in Files. Also available in the context menu of
-the Shell window and Output windows.</dd>
+the Shell window and Output windows.</p>
+</dd>
</dl>
-<dl class="docutils" id="index-3">
-<dt>Debugger (toggle)</dt>
-<dd>When activated, code entered in the Shell or run from an Editor will run
+<dl class="simple" id="index-3">
+<dt>Debugger (toggle)</dt><dd><p>When activated, code entered in the Shell or run from an Editor will run
under the debugger. In the Editor, breakpoints can be set with the context
-menu. This feature is still incomplete and somewhat experimental.</dd>
-<dt>Stack Viewer</dt>
-<dd>Show the stack traceback of the last exception in a tree widget, with
-access to locals and globals.</dd>
-<dt>Auto-open Stack Viewer</dt>
-<dd>Toggle automatically opening the stack viewer on an unhandled exception.</dd>
+menu. This feature is still incomplete and somewhat experimental.</p>
+</dd>
+<dt>Stack Viewer</dt><dd><p>Show the stack traceback of the last exception in a tree widget, with
+access to locals and globals.</p>
+</dd>
+<dt>Auto-open Stack Viewer</dt><dd><p>Toggle automatically opening the stack viewer on an unhandled exception.</p>
+</dd>
</dl>
</div>
<div class="section" id="options-menu-shell-and-editor">
<h3>Options menu (Shell and Editor)<a class="headerlink" href="#options-menu-shell-and-editor" title="Permalink to this headline">¶</a></h3>
-<dl class="docutils">
-<dt>Configure IDLE</dt>
-<dd>Open a configuration dialog and change preferences for the following:
+<dl class="simple">
+<dt>Configure IDLE</dt><dd><p>Open a configuration dialog and change preferences for the following:
fonts, indentation, keybindings, text color themes, startup windows and
-size, additional help sources, and extensions. On macOS, open the
+size, additional help sources, and extensions. On macOS, open the
configuration dialog by selecting Preferences in the application
-menu. For more, see
-<a class="reference internal" href="#preferences"><span class="std std-ref">Setting preferences</span></a> under Help and preferences.</dd>
-<dt>Show/Hide Code Context (Editor Window only)</dt>
-<dd>Open a pane at the top of the edit window which shows the block context
+menu. For more details, see
+<a class="reference internal" href="#preferences"><span class="std std-ref">Setting preferences</span></a> under Help and preferences.</p>
+</dd>
+</dl>
+<p>Most configuration options apply to all windows or all future windows.
+The option items below only apply to the active window.</p>
+<dl class="simple">
+<dt>Show/Hide Code Context (Editor Window only)</dt><dd><p>Open a pane at the top of the edit window which shows the block context
of the code which has scrolled above the top of the window. See
-<a class="reference internal" href="#code-context"><span class="std std-ref">Code Context</span></a> in the Editing and Navigation section below.</dd>
-<dt>Zoom/Restore Height</dt>
-<dd>Toggles the window between normal size and maximum height. The initial size
+<a class="reference internal" href="#code-context"><span class="std std-ref">Code Context</span></a> in the Editing and Navigation section
+below.</p>
+</dd>
+<dt>Show/Hide Line Numbers (Editor Window only)</dt><dd><p>Open a column to the left of the edit window which shows the number
+of each line of text. The default is off, which may be changed in the
+preferences (see <a class="reference internal" href="#preferences"><span class="std std-ref">Setting preferences</span></a>).</p>
+</dd>
+<dt>Zoom/Restore Height</dt><dd><p>Toggles the window between normal size and maximum height. The initial size
defaults to 40 lines by 80 chars unless changed on the General tab of the
Configure IDLE dialog. The maximum height for a screen is determined by
momentarily maximizing a window the first time one is zoomed on the screen.
-Changing screen settings may invalidate the saved height. This toogle has
-no effect when a window is maximized.</dd>
+Changing screen settings may invalidate the saved height. This toggle has
+no effect when a window is maximized.</p>
+</dd>
</dl>
</div>
<div class="section" id="window-menu-shell-and-editor">
</div>
<div class="section" id="help-menu-shell-and-editor">
<h3>Help menu (Shell and Editor)<a class="headerlink" href="#help-menu-shell-and-editor" title="Permalink to this headline">¶</a></h3>
-<dl class="docutils">
-<dt>About IDLE</dt>
-<dd>Display version, copyright, license, credits, and more.</dd>
-<dt>IDLE Help</dt>
-<dd>Display this IDLE document, detailing the menu options, basic editing and
-navigation, and other tips.</dd>
-<dt>Python Docs</dt>
-<dd>Access local Python documentation, if installed, or start a web browser
-and open docs.python.org showing the latest Python documentation.</dd>
-<dt>Turtle Demo</dt>
-<dd>Run the turtledemo module with example Python code and turtle drawings.</dd>
+<dl class="simple">
+<dt>About IDLE</dt><dd><p>Display version, copyright, license, credits, and more.</p>
+</dd>
+<dt>IDLE Help</dt><dd><p>Display this IDLE document, detailing the menu options, basic editing and
+navigation, and other tips.</p>
+</dd>
+<dt>Python Docs</dt><dd><p>Access local Python documentation, if installed, or start a web browser
+and open docs.python.org showing the latest Python documentation.</p>
+</dd>
+<dt>Turtle Demo</dt><dd><p>Run the turtledemo module with example Python code and turtle drawings.</p>
+</dd>
</dl>
<p>Additional help sources may be added here with the Configure IDLE dialog under
the General tab. See the <a class="reference internal" href="#help-sources"><span class="std std-ref">Help sources</span></a> subsection below
<span id="index-4"></span><h3>Context Menus<a class="headerlink" href="#context-menus" title="Permalink to this headline">¶</a></h3>
<p>Open a context menu by right-clicking in a window (Control-click on macOS).
Context menus have the standard clipboard functions also on the Edit menu.</p>
-<dl class="docutils">
-<dt>Cut</dt>
-<dd>Copy selection into the system-wide clipboard; then delete the selection.</dd>
-<dt>Copy</dt>
-<dd>Copy selection into the system-wide clipboard.</dd>
-<dt>Paste</dt>
-<dd>Insert contents of the system-wide clipboard into the current window.</dd>
+<dl class="simple">
+<dt>Cut</dt><dd><p>Copy selection into the system-wide clipboard; then delete the selection.</p>
+</dd>
+<dt>Copy</dt><dd><p>Copy selection into the system-wide clipboard.</p>
+</dd>
+<dt>Paste</dt><dd><p>Insert contents of the system-wide clipboard into the current window.</p>
+</dd>
</dl>
<p>Editor windows also have breakpoint functions. Lines with a breakpoint set are
specially marked. Breakpoints only have an effect when running under the
debugger. Breakpoints for a file are saved in the user’s .idlerc directory.</p>
-<dl class="docutils">
-<dt>Set Breakpoint</dt>
-<dd>Set a breakpoint on the current line.</dd>
-<dt>Clear Breakpoint</dt>
-<dd>Clear the breakpoint on that line.</dd>
+<dl class="simple">
+<dt>Set Breakpoint</dt><dd><p>Set a breakpoint on the current line.</p>
+</dd>
+<dt>Clear Breakpoint</dt><dd><p>Clear the breakpoint on that line.</p>
+</dd>
</dl>
<p>Shell and Output windows also have the following.</p>
-<dl class="docutils">
-<dt>Go to file/line</dt>
-<dd>Same as in Debug menu.</dd>
+<dl class="simple">
+<dt>Go to file/line</dt><dd><p>Same as in Debug menu.</p>
+</dd>
</dl>
<p>The Shell window also has an output squeezing facility explained in the <em>Python
Shell window</em> subsection below.</p>
-<dl class="docutils">
-<dt>Squeeze</dt>
-<dd>If the cursor is over an output line, squeeze all the output between
-the code above and the prompt below down to a ‘Squeezed text’ label.</dd>
+<dl class="simple">
+<dt>Squeeze</dt><dd><p>If the cursor is over an output line, squeeze all the output between
+the code above and the prompt below down to a ‘Squeezed text’ label.</p>
+</dd>
</dl>
</div>
</div>
<p>In this section, ‘C’ refers to the <kbd class="kbd docutils literal notranslate">Control</kbd> key on Windows and Unix and
the <kbd class="kbd docutils literal notranslate">Command</kbd> key on macOS.</p>
<ul>
-<li><p class="first"><kbd class="kbd docutils literal notranslate">Backspace</kbd> deletes to the left; <kbd class="kbd docutils literal notranslate">Del</kbd> deletes to the right</p>
-</li>
-<li><p class="first"><kbd class="kbd docutils literal notranslate">C-Backspace</kbd> delete word left; <kbd class="kbd docutils literal notranslate">C-Del</kbd> delete word to the right</p>
-</li>
-<li><p class="first">Arrow keys and <kbd class="kbd docutils literal notranslate">Page Up</kbd>/<kbd class="kbd docutils literal notranslate">Page Down</kbd> to move around</p>
-</li>
-<li><p class="first"><kbd class="kbd docutils literal notranslate">C-LeftArrow</kbd> and <kbd class="kbd docutils literal notranslate">C-RightArrow</kbd> moves by words</p>
-</li>
-<li><p class="first"><kbd class="kbd docutils literal notranslate">Home</kbd>/<kbd class="kbd docutils literal notranslate">End</kbd> go to begin/end of line</p>
-</li>
-<li><p class="first"><kbd class="kbd docutils literal notranslate">C-Home</kbd>/<kbd class="kbd docutils literal notranslate">C-End</kbd> go to begin/end of file</p>
-</li>
-<li><p class="first">Some useful Emacs bindings are inherited from Tcl/Tk:</p>
+<li><p><kbd class="kbd docutils literal notranslate">Backspace</kbd> deletes to the left; <kbd class="kbd docutils literal notranslate">Del</kbd> deletes to the right</p></li>
+<li><p><kbd class="kbd docutils literal notranslate">C-Backspace</kbd> delete word left; <kbd class="kbd docutils literal notranslate">C-Del</kbd> delete word to the right</p></li>
+<li><p>Arrow keys and <kbd class="kbd docutils literal notranslate">Page Up</kbd>/<kbd class="kbd docutils literal notranslate">Page Down</kbd> to move around</p></li>
+<li><p><kbd class="kbd docutils literal notranslate">C-LeftArrow</kbd> and <kbd class="kbd docutils literal notranslate">C-RightArrow</kbd> moves by words</p></li>
+<li><p><kbd class="kbd docutils literal notranslate">Home</kbd>/<kbd class="kbd docutils literal notranslate">End</kbd> go to begin/end of line</p></li>
+<li><p><kbd class="kbd docutils literal notranslate">C-Home</kbd>/<kbd class="kbd docutils literal notranslate">C-End</kbd> go to begin/end of file</p></li>
+<li><p>Some useful Emacs bindings are inherited from Tcl/Tk:</p>
<blockquote>
<div><ul class="simple">
-<li><kbd class="kbd docutils literal notranslate">C-a</kbd> beginning of line</li>
-<li><kbd class="kbd docutils literal notranslate">C-e</kbd> end of line</li>
-<li><kbd class="kbd docutils literal notranslate">C-k</kbd> kill line (but doesn’t put it in clipboard)</li>
-<li><kbd class="kbd docutils literal notranslate">C-l</kbd> center window around the insertion point</li>
-<li><kbd class="kbd docutils literal notranslate">C-b</kbd> go backward one character without deleting (usually you can
-also use the cursor key for this)</li>
-<li><kbd class="kbd docutils literal notranslate">C-f</kbd> go forward one character without deleting (usually you can
-also use the cursor key for this)</li>
-<li><kbd class="kbd docutils literal notranslate">C-p</kbd> go up one line (usually you can also use the cursor key for
-this)</li>
-<li><kbd class="kbd docutils literal notranslate">C-d</kbd> delete next character</li>
+<li><p><kbd class="kbd docutils literal notranslate">C-a</kbd> beginning of line</p></li>
+<li><p><kbd class="kbd docutils literal notranslate">C-e</kbd> end of line</p></li>
+<li><p><kbd class="kbd docutils literal notranslate">C-k</kbd> kill line (but doesn’t put it in clipboard)</p></li>
+<li><p><kbd class="kbd docutils literal notranslate">C-l</kbd> center window around the insertion point</p></li>
+<li><p><kbd class="kbd docutils literal notranslate">C-b</kbd> go backward one character without deleting (usually you can
+also use the cursor key for this)</p></li>
+<li><p><kbd class="kbd docutils literal notranslate">C-f</kbd> go forward one character without deleting (usually you can
+also use the cursor key for this)</p></li>
+<li><p><kbd class="kbd docutils literal notranslate">C-p</kbd> go up one line (usually you can also use the cursor key for
+this)</p></li>
+<li><p><kbd class="kbd docutils literal notranslate">C-d</kbd> delete next character</p></li>
</ul>
</div></blockquote>
</li>
<p>The editing features described in previous subsections work when entering
code interactively. IDLE’s Shell window also responds to the following keys.</p>
<ul>
-<li><p class="first"><kbd class="kbd docutils literal notranslate">C-c</kbd> interrupts executing command</p>
-</li>
-<li><p class="first"><kbd class="kbd docutils literal notranslate">C-d</kbd> sends end-of-file; closes window if typed at a <code class="docutils literal notranslate"><span class="pre">>>></span></code> prompt</p>
-</li>
-<li><p class="first"><kbd class="kbd docutils literal notranslate">Alt-/</kbd> (Expand word) is also useful to reduce typing</p>
+<li><p><kbd class="kbd docutils literal notranslate">C-c</kbd> interrupts executing command</p></li>
+<li><p><kbd class="kbd docutils literal notranslate">C-d</kbd> sends end-of-file; closes window if typed at a <code class="docutils literal notranslate"><span class="pre">>>></span></code> prompt</p></li>
+<li><p><kbd class="kbd docutils literal notranslate">Alt-/</kbd> (Expand word) is also useful to reduce typing</p>
<p>Command history</p>
<ul class="simple">
-<li><kbd class="kbd docutils literal notranslate">Alt-p</kbd> retrieves previous command matching what you have typed. On
-macOS use <kbd class="kbd docutils literal notranslate">C-p</kbd>.</li>
-<li><kbd class="kbd docutils literal notranslate">Alt-n</kbd> retrieves next. On macOS use <kbd class="kbd docutils literal notranslate">C-n</kbd>.</li>
-<li><kbd class="kbd docutils literal notranslate">Return</kbd> while on any previous command retrieves that command</li>
+<li><p><kbd class="kbd docutils literal notranslate">Alt-p</kbd> retrieves previous command matching what you have typed. On
+macOS use <kbd class="kbd docutils literal notranslate">C-p</kbd>.</p></li>
+<li><p><kbd class="kbd docutils literal notranslate">Alt-n</kbd> retrieves next. On macOS use <kbd class="kbd docutils literal notranslate">C-n</kbd>.</p></li>
+<li><p><kbd class="kbd docutils literal notranslate">Return</kbd> while on any previous command retrieves that command</p></li>
</ul>
</li>
</ul>
</div>
<p>If there are arguments:</p>
<ul class="simple">
-<li>If <code class="docutils literal notranslate"><span class="pre">-</span></code>, <code class="docutils literal notranslate"><span class="pre">-c</span></code>, or <code class="docutils literal notranslate"><span class="pre">r</span></code> is used, all arguments are placed in
+<li><p>If <code class="docutils literal notranslate"><span class="pre">-</span></code>, <code class="docutils literal notranslate"><span class="pre">-c</span></code>, or <code class="docutils literal notranslate"><span class="pre">r</span></code> is used, all arguments are placed in
<code class="docutils literal notranslate"><span class="pre">sys.argv[1:...]</span></code> and <code class="docutils literal notranslate"><span class="pre">sys.argv[0]</span></code> is set to <code class="docutils literal notranslate"><span class="pre">''</span></code>, <code class="docutils literal notranslate"><span class="pre">'-c'</span></code>,
or <code class="docutils literal notranslate"><span class="pre">'-r'</span></code>. No editor window is opened, even if that is the default
-set in the Options dialog.</li>
-<li>Otherwise, arguments are files opened for editing and
-<code class="docutils literal notranslate"><span class="pre">sys.argv</span></code> reflects the arguments passed to IDLE itself.</li>
+set in the Options dialog.</p></li>
+<li><p>Otherwise, arguments are files opened for editing and
+<code class="docutils literal notranslate"><span class="pre">sys.argv</span></code> reflects the arguments passed to IDLE itself.</p></li>
</ul>
</div>
<div class="section" id="startup-failure">
or <code class="docutils literal notranslate"><span class="pre">print</span></code> or <code class="docutils literal notranslate"><span class="pre">write</span></code> to sys.stdout or sys.stderr,
IDLE should be started in a command line window. The secondary subprocess
will then be attached to that window for input and output.</p>
+<p>The IDLE code running in the execution process adds frames to the call stack
+that would not be there otherwise. IDLE wraps <code class="docutils literal notranslate"><span class="pre">sys.getrecursionlimit</span></code> and
+<code class="docutils literal notranslate"><span class="pre">sys.setrecursionlimit</span></code> to reduce the effect of the additional stack frames.</p>
<p>If <code class="docutils literal notranslate"><span class="pre">sys</span></code> is reset by user code, such as with <code class="docutils literal notranslate"><span class="pre">importlib.reload(sys)</span></code>,
IDLE’s changes are lost and input from the keyboard and output to the screen
will not work correctly.</p>
are to take effect. For these reasons, it is preferable to run IDLE
with the default subprocess if at all possible.</p>
<div class="deprecated">
-<p><span class="versionmodified">Deprecated since version 3.4.</span></p>
+<p><span class="versionmodified deprecated">Deprecated since version 3.4.</span></p>
</div>
</div>
</div>
<h4>Previous topic</h4>
<p class="topless"><a href="tkinter.scrolledtext.html"
- title="previous chapter"><code class="docutils literal notranslate"><span class="pre">tkinter.scrolledtext</span></code> — Scrolled Text Widget</a></p>
+ title="previous chapter"><code class="xref py py-mod docutils literal notranslate"><span class="pre">tkinter.scrolledtext</span></code> — Scrolled Text Widget</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="othergui.html"
title="next chapter">Other Graphical User Interface Packages</a></p>
<br />
<br />
- Last updated on Jun 17, 2019.
+ Last updated on Sep 01, 2019.
<a href="https://docs.python.org/3/bugs.html">Found a bug</a>?
<br />
- Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.8.1.
+ Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 2.1.2.
</div>
</body>
"""
def __init__(self, text):
HTMLParser.__init__(self, convert_charrefs=True)
- self.text = text # text widget we're rendering into
- self.tags = '' # current block level text tags to apply
- self.chartags = '' # current character level text tags
- self.show = False # used so we exclude page navigation
- self.hdrlink = False # used so we don't show header links
- self.level = 0 # indentation level
- self.pre = False # displaying preformatted text
- self.hprefix = '' # prefix such as '25.5' to strip from headings
- self.nested_dl = False # if we're in a nested <dl>
- self.simplelist = False # simple list (no double spacing)
- self.toc = [] # pair headers with text indexes for toc
- self.header = '' # text within header tags for toc
+ self.text = text # Text widget we're rendering into.
+ self.tags = '' # Current block level text tags to apply.
+ self.chartags = '' # Current character level text tags.
+ self.show = False # Exclude html page navigation.
+ self.hdrlink = False # Exclude html header links.
+ self.level = 0 # Track indentation level.
+ self.pre = False # Displaying preformatted text?
+ self.hprefix = '' # Heading prefix (like '25.5'?) to remove.
+ self.nested_dl = False # In a nested <dl>?
+ self.simplelist = False # In a simple list (no double spacing)?
+ self.toc = [] # Pair headers with text indexes for toc.
+ self.header = '' # Text within header tags for toc.
+ self.prevtag = None # Previous tag info (opener?, tag).
def indent(self, amt=1):
+ "Change indent (+1, 0, -1) and tags."
self.level += amt
self.tags = '' if self.level == 0 else 'l'+str(self.level)
class_ = v
s = ''
if tag == 'div' and class_ == 'section':
- self.show = True # start of main content
+ self.show = True # Start main content.
elif tag == 'div' and class_ == 'sphinxsidebar':
- self.show = False # end of main content
- elif tag == 'p' and class_ != 'first':
- s = '\n\n'
+ self.show = False # End main content.
+ elif tag == 'p' and self.prevtag and not self.prevtag[0]:
+ # Begin a new block for <p> tags after a closed tag.
+ # Avoid extra lines, e.g. after <pre> tags.
+ lastline = self.text.get('end-1c linestart', 'end-1c')
+ s = '\n\n' if lastline and not lastline.isspace() else '\n'
elif tag == 'span' and class_ == 'pre':
self.chartags = 'pre'
elif tag == 'span' and class_ == 'versionmodified':
elif tag == 'li':
s = '\n* ' if self.simplelist else '\n\n* '
elif tag == 'dt':
- s = '\n\n' if not self.nested_dl else '\n' # avoid extra line
+ s = '\n\n' if not self.nested_dl else '\n' # Avoid extra line.
self.nested_dl = False
elif tag == 'dd':
self.indent()
self.tags = tag
if self.show:
self.text.insert('end', s, (self.tags, self.chartags))
+ self.prevtag = (True, tag)
def handle_endtag(self, tag):
"Handle endtags in help.html."
if tag in ['h1', 'h2', 'h3']:
- self.indent(0) # clear tag, reset indent
+ assert self.level == 0
if self.show:
indent = (' ' if tag == 'h3' else
' ' if tag == 'h2' else
'')
self.toc.append((indent+self.header, self.text.index('insert')))
+ self.tags = ''
elif tag in ['span', 'em']:
self.chartags = ''
elif tag == 'a':
self.pre = False
self.tags = ''
elif tag in ['ul', 'dd', 'ol']:
- self.indent(amt=-1)
+ self.indent(-1)
+ self.prevtag = (False, tag)
def handle_data(self, data):
"Handle date segments in help.html."
"Configure tags and feed file to parser."
uwide = idleConf.GetOption('main', 'EditorWindow', 'width', type='int')
uhigh = idleConf.GetOption('main', 'EditorWindow', 'height', type='int')
- uhigh = 3 * uhigh // 4 # lines average 4/3 of editor line height
+ uhigh = 3 * uhigh // 4 # Lines average 4/3 of editor line height.
Text.__init__(self, parent, wrap='word', highlightthickness=0,
padx=5, borderwidth=0, width=uwide, height=uhigh)
"Display html text, scrollbar, and toc."
def __init__(self, parent, filename):
Frame.__init__(self, parent)
- # keep references to widgets for test access.
self.text = text = HelpText(self, filename)
self['background'] = text['background']
self.toc = toc = self.toc_menu(text)
text['yscrollcommand'] = scroll.set
self.rowconfigure(0, weight=1)
- self.columnconfigure(1, weight=1) # text
+ self.columnconfigure(1, weight=1) # Only expand the text widget.
toc.grid(row=0, column=0, sticky='nw')
text.grid(row=0, column=1, sticky='nsew')
scroll.grid(row=0, column=2, sticky='ns')
same, help.html can be backported. The internal Python version
number is not displayed. If maintenance idle.rst diverges from
the master version, then instead of backporting help.html from
- master, repeat the proceedure above to generate a maintenance
+ master, repeat the procedure above to generate a maintenance
version.
"""
src = join(abspath(dirname(dirname(dirname(__file__)))),
"Create HelpWindow; called from Idle Help event handler."
filename = join(abspath(dirname(__file__)), 'help.html')
if not isfile(filename):
- # try copy_strip, present message
+ # Try copy_strip, present message.
return
HelpWindow(parent, filename, 'IDLE Help (%s)' % python_version())
return "break"
def fetch(self, reverse):
- '''Fetch statememt and replace current line in text widget.
+ '''Fetch statement and replace current line in text widget.
Set prefix and pointer as needed for successive fetches.
Reset them to None, None when returning to the start line.
import idlelib.pyshell # Set Windows DPI awareness before Tk().
from importlib import import_module
+import textwrap
import tkinter as tk
from tkinter.ttk import Scrollbar
tk.NoDefaultRoot()
CustomRun_spec = {
'file': 'query',
- 'kwds': {'title': 'Custom Run Args',
+ 'kwds': {'title': 'Customize query.py Run',
'_htest': True},
- 'msg': "Enter with <Return> or [Ok]. Print valid entry to Shell\n"
+ 'msg': "Enter with <Return> or [Run]. Print valid entry to Shell\n"
"Arguments are parsed into a list\n"
+ "Mode is currently restart True or False\n"
"Close dialog with valid entry, <Escape>, [Cancel], [X]"
}
"Check that changes were saved by opening the file elsewhere."
}
+_linenumbers_drag_scrolling_spec = {
+ 'file': 'sidebar',
+ 'kwds': {},
+ 'msg': textwrap.dedent("""\
+ 1. Click on the line numbers and drag down below the edge of the
+ window, moving the mouse a bit and then leaving it there for a while.
+ The text and line numbers should gradually scroll down, with the
+ selection updated continuously.
+
+ 2. With the lines still selected, click on a line number above the
+ selected lines. Only the line whose number was clicked should be
+ selected.
+
+ 3. Repeat step #1, dragging to above the window. The text and line
+ numbers should gradually scroll up, with the selection updated
+ continuously.
+
+ 4. Repeat step #2, clicking a line number below the selection."""),
+ }
+
_multi_call_spec = {
'file': 'multicall',
'kwds': {},
ViewWindow_spec = {
'file': 'textview',
'kwds': {'title': 'Test textview',
- 'text': 'The quick brown fox jumps over the lazy dog.\n'*35,
+ 'contents': 'The quick brown fox jumps over the lazy dog.\n'*35,
'_htest': True},
'msg': "Test for read-only property of text.\n"
"Select text, scroll window, close"
-"Test autocomplete, coverage 87%."
+"Test autocomplete, coverage 93%."
import unittest
from unittest.mock import Mock, patch
def test_init(self):
self.assertEqual(self.autocomplete.editwin, self.editor)
+ self.assertEqual(self.autocomplete.text, self.text)
def test_make_autocomplete_window(self):
testwin = self.autocomplete._make_autocomplete_window()
self.assertIsInstance(testwin, acw.AutoCompleteWindow)
def test_remove_autocomplete_window(self):
- self.autocomplete.autocompletewindow = (
- self.autocomplete._make_autocomplete_window())
- self.autocomplete._remove_autocomplete_window()
- self.assertIsNone(self.autocomplete.autocompletewindow)
+ acp = self.autocomplete
+ acp.autocompletewindow = m = Mock()
+ acp._remove_autocomplete_window()
+ m.hide_window.assert_called_once()
+ self.assertIsNone(acp.autocompletewindow)
def test_force_open_completions_event(self):
- # Test that force_open_completions_event calls _open_completions.
- o_cs = Func()
- self.autocomplete.open_completions = o_cs
- self.autocomplete.force_open_completions_event('event')
- self.assertEqual(o_cs.args, (True, False, True))
-
- def test_try_open_completions_event(self):
- Equal = self.assertEqual
- autocomplete = self.autocomplete
- trycompletions = self.autocomplete.try_open_completions_event
- o_c_l = Func()
- autocomplete._open_completions_later = o_c_l
-
- # _open_completions_later should not be called with no text in editor.
- trycompletions('event')
- Equal(o_c_l.args, None)
-
- # _open_completions_later should be called with COMPLETE_ATTRIBUTES (1).
- self.text.insert('1.0', 're.')
- trycompletions('event')
- Equal(o_c_l.args, (False, False, False, 1))
-
- # _open_completions_later should be called with COMPLETE_FILES (2).
- self.text.delete('1.0', 'end')
- self.text.insert('1.0', '"./Lib/')
- trycompletions('event')
- Equal(o_c_l.args, (False, False, False, 2))
+ # Call _open_completions and break.
+ acp = self.autocomplete
+ open_c = Func()
+ acp.open_completions = open_c
+ self.assertEqual(acp.force_open_completions_event('event'), 'break')
+ self.assertEqual(open_c.args[0], ac.FORCE)
def test_autocomplete_event(self):
Equal = self.assertEqual
- autocomplete = self.autocomplete
+ acp = self.autocomplete
- # Test that the autocomplete event is ignored if user is pressing a
- # modifier key in addition to the tab key.
+ # Result of autocomplete event: If modified tab, None.
ev = Event(mc_state=True)
- self.assertIsNone(autocomplete.autocomplete_event(ev))
+ self.assertIsNone(acp.autocomplete_event(ev))
del ev.mc_state
- # Test that tab after whitespace is ignored.
+ # If tab after whitespace, None.
self.text.insert('1.0', ' """Docstring.\n ')
- self.assertIsNone(autocomplete.autocomplete_event(ev))
+ self.assertIsNone(acp.autocomplete_event(ev))
self.text.delete('1.0', 'end')
- # If autocomplete window is open, complete() method is called.
+ # If active autocomplete window, complete() and 'break'.
self.text.insert('1.0', 're.')
- # This must call autocomplete._make_autocomplete_window().
- Equal(self.autocomplete.autocomplete_event(ev), 'break')
-
- # If autocomplete window is not active or does not exist,
- # open_completions is called. Return depends on its return.
- autocomplete._remove_autocomplete_window()
- o_cs = Func() # .result = None.
- autocomplete.open_completions = o_cs
- Equal(self.autocomplete.autocomplete_event(ev), None)
- Equal(o_cs.args, (False, True, True))
- o_cs.result = True
- Equal(self.autocomplete.autocomplete_event(ev), 'break')
- Equal(o_cs.args, (False, True, True))
-
- def test_open_completions_later(self):
- # Test that autocomplete._delayed_completion_id is set.
+ acp.autocompletewindow = mock = Mock()
+ mock.is_active = Mock(return_value=True)
+ Equal(acp.autocomplete_event(ev), 'break')
+ mock.complete.assert_called_once()
+ acp.autocompletewindow = None
+
+ # If no active autocomplete window, open_completions(), None/break.
+ open_c = Func(result=False)
+ acp.open_completions = open_c
+ Equal(acp.autocomplete_event(ev), None)
+ Equal(open_c.args[0], ac.TAB)
+ open_c.result = True
+ Equal(acp.autocomplete_event(ev), 'break')
+ Equal(open_c.args[0], ac.TAB)
+
+ def test_try_open_completions_event(self):
+ Equal = self.assertEqual
+ text = self.text
acp = self.autocomplete
+ trycompletions = acp.try_open_completions_event
+ after = Func(result='after1')
+ acp.text.after = after
+
+ # If no text or trigger, after not called.
+ trycompletions()
+ Equal(after.called, 0)
+ text.insert('1.0', 're')
+ trycompletions()
+ Equal(after.called, 0)
+
+ # Attribute needed, no existing callback.
+ text.insert('insert', ' re.')
acp._delayed_completion_id = None
- acp._open_completions_later(False, False, False, ac.COMPLETE_ATTRIBUTES)
+ trycompletions()
+ Equal(acp._delayed_completion_index, text.index('insert'))
+ Equal(after.args,
+ (acp.popupwait, acp._delayed_open_completions, ac.TRY_A))
cb1 = acp._delayed_completion_id
- self.assertTrue(cb1.startswith('after'))
-
- # Test that cb1 is cancelled and cb2 is new.
- acp._open_completions_later(False, False, False, ac.COMPLETE_FILES)
- self.assertNotIn(cb1, self.root.tk.call('after', 'info'))
- cb2 = acp._delayed_completion_id
- self.assertTrue(cb2.startswith('after') and cb2 != cb1)
- self.text.after_cancel(cb2)
+ Equal(cb1, 'after1')
+
+ # File needed, existing callback cancelled.
+ text.insert('insert', ' "./Lib/')
+ after.result = 'after2'
+ cancel = Func()
+ acp.text.after_cancel = cancel
+ trycompletions()
+ Equal(acp._delayed_completion_index, text.index('insert'))
+ Equal(cancel.args, (cb1,))
+ Equal(after.args,
+ (acp.popupwait, acp._delayed_open_completions, ac.TRY_F))
+ Equal(acp._delayed_completion_id, 'after2')
def test_delayed_open_completions(self):
- # Test that autocomplete._delayed_completion_id set to None
- # and that open_completions is not called if the index is not
- # equal to _delayed_completion_index.
+ Equal = self.assertEqual
acp = self.autocomplete
- acp.open_completions = Func()
+ open_c = Func()
+ acp.open_completions = open_c
+ self.text.insert('1.0', '"dict.')
+
+ # Set autocomplete._delayed_completion_id to None.
+ # Text index changed, don't call open_completions.
acp._delayed_completion_id = 'after'
acp._delayed_completion_index = self.text.index('insert+1c')
- acp._delayed_open_completions(1, 2, 3)
+ acp._delayed_open_completions('dummy')
self.assertIsNone(acp._delayed_completion_id)
- self.assertEqual(acp.open_completions.called, 0)
+ Equal(open_c.called, 0)
- # Test that open_completions is called if indexes match.
+ # Text index unchanged, call open_completions.
acp._delayed_completion_index = self.text.index('insert')
- acp._delayed_open_completions(1, 2, 3, ac.COMPLETE_FILES)
- self.assertEqual(acp.open_completions.args, (1, 2, 3, 2))
+ acp._delayed_open_completions((1, 2, 3, ac.FILES))
+ self.assertEqual(open_c.args[0], (1, 2, 3, ac.FILES))
+
+ def test_oc_cancel_comment(self):
+ none = self.assertIsNone
+ acp = self.autocomplete
+
+ # Comment is in neither code or string.
+ acp._delayed_completion_id = 'after'
+ after = Func(result='after')
+ acp.text.after_cancel = after
+ self.text.insert(1.0, '# comment')
+ none(acp.open_completions(ac.TAB)) # From 'else' after 'elif'.
+ none(acp._delayed_completion_id)
+
+ def test_oc_no_list(self):
+ acp = self.autocomplete
+ fetch = Func(result=([],[]))
+ acp.fetch_completions = fetch
+ self.text.insert('1.0', 'object')
+ self.assertIsNone(acp.open_completions(ac.TAB))
+ self.text.insert('insert', '.')
+ self.assertIsNone(acp.open_completions(ac.TAB))
+ self.assertEqual(fetch.called, 2)
+
+
+ def test_open_completions_none(self):
+ # Test other two None returns.
+ none = self.assertIsNone
+ acp = self.autocomplete
+
+ # No object for attributes or need call not allowed.
+ self.text.insert(1.0, '.')
+ none(acp.open_completions(ac.TAB))
+ self.text.insert('insert', ' int().')
+ none(acp.open_completions(ac.TAB))
+
+ # Blank or quote trigger 'if complete ...'.
+ self.text.delete(1.0, 'end')
+ self.assertFalse(acp.open_completions(ac.TAB))
+ self.text.insert('1.0', '"')
+ self.assertFalse(acp.open_completions(ac.TAB))
+ self.text.delete('1.0', 'end')
+
+ class dummy_acw():
+ __init__ = Func()
+ show_window = Func(result=False)
+ hide_window = Func()
def test_open_completions(self):
- # Test completions of files and attributes as well as non-completion
- # of errors.
- self.text.insert('1.0', 'pr')
- self.assertTrue(self.autocomplete.open_completions(False, True, True))
+ # Test completions of files and attributes.
+ acp = self.autocomplete
+ fetch = Func(result=(['tem'],['tem', '_tem']))
+ acp.fetch_completions = fetch
+ def make_acw(): return self.dummy_acw()
+ acp._make_autocomplete_window = make_acw
+
+ self.text.insert('1.0', 'int.')
+ acp.open_completions(ac.TAB)
+ self.assertIsInstance(acp.autocompletewindow, self.dummy_acw)
self.text.delete('1.0', 'end')
# Test files.
self.text.insert('1.0', '"t')
- #self.assertTrue(self.autocomplete.open_completions(False, True, True))
- self.text.delete('1.0', 'end')
-
- # Test with blank will fail.
- self.assertFalse(self.autocomplete.open_completions(False, True, True))
-
- # Test with only string quote will fail.
- self.text.insert('1.0', '"')
- self.assertFalse(self.autocomplete.open_completions(False, True, True))
+ self.assertTrue(acp.open_completions(ac.TAB))
self.text.delete('1.0', 'end')
def test_fetch_completions(self):
# a small list containing non-private variables.
# For file completion, a large list containing all files in the path,
# and a small list containing files that do not start with '.'.
- autocomplete = self.autocomplete
- small, large = self.autocomplete.fetch_completions(
- '', ac.COMPLETE_ATTRIBUTES)
+ acp = self.autocomplete
+ small, large = acp.fetch_completions(
+ '', ac.ATTRS)
if __main__.__file__ != ac.__file__:
self.assertNotIn('AutoComplete', small) # See issue 36405.
# Test attributes
- s, b = autocomplete.fetch_completions('', ac.COMPLETE_ATTRIBUTES)
+ s, b = acp.fetch_completions('', ac.ATTRS)
self.assertLess(len(small), len(large))
self.assertTrue(all(filter(lambda x: x.startswith('_'), s)))
self.assertTrue(any(filter(lambda x: x.startswith('_'), b)))
# Test smalll should respect to __all__.
with patch.dict('__main__.__dict__', {'__all__': ['a', 'b']}):
- s, b = autocomplete.fetch_completions('', ac.COMPLETE_ATTRIBUTES)
+ s, b = acp.fetch_completions('', ac.ATTRS)
self.assertEqual(s, ['a', 'b'])
self.assertIn('__name__', b) # From __main__.__dict__
self.assertIn('sum', b) # From __main__.__builtins__.__dict__
mock = Mock()
mock._private = Mock()
with patch.dict('__main__.__dict__', {'foo': mock}):
- s, b = autocomplete.fetch_completions('foo', ac.COMPLETE_ATTRIBUTES)
+ s, b = acp.fetch_completions('foo', ac.ATTRS)
self.assertNotIn('_private', s)
self.assertIn('_private', b)
self.assertEqual(s, [i for i in sorted(dir(mock)) if i[:1] != '_'])
return ['monty', 'python', '.hidden']
with patch.object(os, 'listdir', _listdir):
- s, b = autocomplete.fetch_completions('', ac.COMPLETE_FILES)
+ s, b = acp.fetch_completions('', ac.FILES)
self.assertEqual(s, ['bar', 'foo'])
self.assertEqual(b, ['.hidden', 'bar', 'foo'])
- s, b = autocomplete.fetch_completions('~', ac.COMPLETE_FILES)
+ s, b = acp.fetch_completions('~', ac.FILES)
self.assertEqual(s, ['monty', 'python'])
self.assertEqual(b, ['.hidden', 'monty', 'python'])
def test_get_entity(self):
# Test that a name is in the namespace of sys.modules and
# __main__.__dict__.
- autocomplete = self.autocomplete
+ acp = self.autocomplete
Equal = self.assertEqual
- Equal(self.autocomplete.get_entity('int'), int)
+ Equal(acp.get_entity('int'), int)
# Test name from sys.modules.
mock = Mock()
with patch.dict('sys.modules', {'tempfile': mock}):
- Equal(autocomplete.get_entity('tempfile'), mock)
+ Equal(acp.get_entity('tempfile'), mock)
# Test name from __main__.__dict__.
di = {'foo': 10, 'bar': 20}
with patch.dict('__main__.__dict__', {'d': di}):
- Equal(autocomplete.get_entity('d'), di)
+ Equal(acp.get_entity('d'), di)
# Test name not in namespace.
with patch.dict('__main__.__dict__', {}):
with self.assertRaises(NameError):
- autocomplete.get_entity('not_exist')
+ acp.get_entity('not_exist')
if __name__ == '__main__':
from idlelib import codecontext
import unittest
+import unittest.mock
from test.support import requires
-from tkinter import Tk, Frame, Text, TclError
+from tkinter import NSEW, Tk, Frame, Text, TclError
from unittest import mock
import re
self.text = text
self.label = ''
+ def getlineno(self, index):
+ return int(float(self.text.index(index)))
+
def update_menu_label(self, **kwargs):
self.label = kwargs['label']
text.insert('1.0', code_sample)
# Need to pack for creation of code context text widget.
frame.pack(side='left', fill='both', expand=1)
- text.pack(side='top', fill='both', expand=1)
+ text.grid(row=1, column=1, sticky=NSEW)
cls.editor = DummyEditwin(root, frame, text)
codecontext.idleConf.userCfg = testcfg
def setUp(self):
self.text.yview(0)
+ self.text['font'] = 'TkFixedFont'
self.cc = codecontext.CodeContext(self.editor)
+ self.highlight_cfg = {"background": '#abcdef',
+ "foreground": '#123456'}
+ orig_idleConf_GetHighlight = codecontext.idleConf.GetHighlight
+ def mock_idleconf_GetHighlight(theme, element):
+ if element == 'context':
+ return self.highlight_cfg
+ return orig_idleConf_GetHighlight(theme, element)
+ GetHighlight_patcher = unittest.mock.patch.object(
+ codecontext.idleConf, 'GetHighlight', mock_idleconf_GetHighlight)
+ GetHighlight_patcher.start()
+ self.addCleanup(GetHighlight_patcher.stop)
+
+ self.font_override = 'TkFixedFont'
+ def mock_idleconf_GetFont(root, configType, section):
+ return self.font_override
+ GetFont_patcher = unittest.mock.patch.object(
+ codecontext.idleConf, 'GetFont', mock_idleconf_GetFont)
+ GetFont_patcher.start()
+ self.addCleanup(GetFont_patcher.stop)
+
def tearDown(self):
if self.cc.context:
self.cc.context.destroy()
eq(cc.editwin, ed)
eq(cc.text, ed.text)
- eq(cc.textfont, ed.text['font'])
+ eq(cc.text['font'], ed.text['font'])
self.assertIsNone(cc.context)
eq(cc.info, [(0, -1, '', False)])
eq(cc.topvisible, 1)
- eq(self.root.tk.call('after', 'info', self.cc.t1)[1], 'timer')
- eq(self.root.tk.call('after', 'info', self.cc.t2)[1], 'timer')
+ self.assertIsNone(self.cc.t1)
def test_del(self):
self.cc.__del__()
- with self.assertRaises(TclError) as msg:
- self.root.tk.call('after', 'info', self.cc.t1)
- self.assertIn("doesn't exist", msg)
- with self.assertRaises(TclError) as msg:
- self.root.tk.call('after', 'info', self.cc.t2)
- self.assertIn("doesn't exist", msg)
- # For coverage on the except. Have to delete because the
- # above Tcl error is caught by after_cancel.
- del self.cc.t1, self.cc.t2
+
+ def test_del_with_timer(self):
+ timer = self.cc.t1 = self.text.after(10000, lambda: None)
self.cc.__del__()
+ with self.assertRaises(TclError) as cm:
+ self.root.tk.call('after', 'info', timer)
+ self.assertIn("doesn't exist", str(cm.exception))
def test_reload(self):
codecontext.CodeContext.reload()
- self.assertEqual(self.cc.colors, {'background': 'lightgray',
- 'foreground': '#000000'})
self.assertEqual(self.cc.context_depth, 15)
def test_toggle_code_context_event(self):
toggle()
# Toggle on.
- eq(toggle(), 'break')
+ toggle()
self.assertIsNotNone(cc.context)
- eq(cc.context['font'], cc.textfont)
- eq(cc.context['fg'], cc.colors['foreground'])
- eq(cc.context['bg'], cc.colors['background'])
+ eq(cc.context['font'], self.text['font'])
+ eq(cc.context['fg'], self.highlight_cfg['foreground'])
+ eq(cc.context['bg'], self.highlight_cfg['background'])
eq(cc.context.get('1.0', 'end-1c'), '')
eq(cc.editwin.label, 'Hide Code Context')
+ eq(self.root.tk.call('after', 'info', self.cc.t1)[1], 'timer')
# Toggle off.
- eq(toggle(), 'break')
+ toggle()
self.assertIsNone(cc.context)
eq(cc.editwin.label, 'Show Code Context')
+ self.assertIsNone(self.cc.t1)
+
+ # Scroll down and toggle back on.
+ line11_context = '\n'.join(x[2] for x in cc.get_context(11)[0])
+ cc.text.yview(11)
+ toggle()
+ eq(cc.context.get('1.0', 'end-1c'), line11_context)
+
+ # Toggle off and on again.
+ toggle()
+ toggle()
+ eq(cc.context.get('1.0', 'end-1c'), line11_context)
def test_get_context(self):
eq = self.assertEqual
(4, 4, ' def __init__(self, a, b):', 'def')])
eq(cc.topvisible, 5)
eq(cc.context.get('1.0', 'end-1c'), 'class C1():\n'
- ' def __init__(self, a, b):')
+ ' def __init__(self, a, b):')
# Scroll down to line 11. Last 'def' is removed.
cc.text.yview(11)
(10, 8, ' elif a < b:', 'elif')])
eq(cc.topvisible, 12)
eq(cc.context.get('1.0', 'end-1c'), 'class C1():\n'
- ' def compare(self):\n'
- ' if a > b:\n'
- ' elif a < b:')
+ ' def compare(self):\n'
+ ' if a > b:\n'
+ ' elif a < b:')
# No scroll. No update, even though context_depth changed.
cc.update_code_context()
(10, 8, ' elif a < b:', 'elif')])
eq(cc.topvisible, 12)
eq(cc.context.get('1.0', 'end-1c'), 'class C1():\n'
- ' def compare(self):\n'
- ' if a > b:\n'
- ' elif a < b:')
+ ' def compare(self):\n'
+ ' if a > b:\n'
+ ' elif a < b:')
# Scroll up.
cc.text.yview(5)
cc.toggle_code_context_event()
# Empty context.
- cc.text.yview(f'{2}.0')
+ cc.text.yview('2.0')
cc.update_code_context()
eq(cc.topvisible, 2)
cc.context.mark_set('insert', '1.5')
eq(cc.topvisible, 1)
# 4 lines of context showing.
- cc.text.yview(f'{12}.0')
+ cc.text.yview('12.0')
cc.update_code_context()
eq(cc.topvisible, 12)
cc.context.mark_set('insert', '3.0')
# More context lines than limit.
cc.context_depth = 2
- cc.text.yview(f'{12}.0')
+ cc.text.yview('12.0')
cc.update_code_context()
eq(cc.topvisible, 12)
cc.context.mark_set('insert', '1.0')
self.cc.timer_event()
mock_update.assert_called()
- def test_config_timer_event(self):
+ def test_font(self):
eq = self.assertEqual
cc = self.cc
- save_font = cc.text['font']
- save_colors = codecontext.CodeContext.colors
- test_font = 'FakeFont'
+
+ orig_font = cc.text['font']
+ test_font = 'TkTextFont'
+ self.assertNotEqual(orig_font, test_font)
+
+ # Ensure code context is not active.
+ if cc.context is not None:
+ cc.toggle_code_context_event()
+
+ self.font_override = test_font
+ # Nothing breaks or changes with inactive code context.
+ cc.update_font()
+
+ # Activate code context, previous font change is immediately effective.
+ cc.toggle_code_context_event()
+ eq(cc.context['font'], test_font)
+
+ # Call the font update, change is picked up.
+ self.font_override = orig_font
+ cc.update_font()
+ eq(cc.context['font'], orig_font)
+
+ def test_highlight_colors(self):
+ eq = self.assertEqual
+ cc = self.cc
+
+ orig_colors = dict(self.highlight_cfg)
test_colors = {'background': '#222222', 'foreground': '#ffff00'}
+ def assert_colors_are_equal(colors):
+ eq(cc.context['background'], colors['background'])
+ eq(cc.context['foreground'], colors['foreground'])
+
# Ensure code context is not active.
if cc.context:
cc.toggle_code_context_event()
- # Nothing updates on inactive code context.
- cc.text['font'] = test_font
- codecontext.CodeContext.colors = test_colors
- cc.config_timer_event()
- eq(cc.textfont, save_font)
- eq(cc.contextcolors, save_colors)
+ self.highlight_cfg = test_colors
+ # Nothing breaks with inactive code context.
+ cc.update_highlight_colors()
- # Activate code context, but no change to font or color.
+ # Activate code context, previous colors change is immediately effective.
cc.toggle_code_context_event()
- cc.text['font'] = save_font
- codecontext.CodeContext.colors = save_colors
- cc.config_timer_event()
- eq(cc.textfont, save_font)
- eq(cc.contextcolors, save_colors)
- eq(cc.context['font'], save_font)
- eq(cc.context['background'], save_colors['background'])
- eq(cc.context['foreground'], save_colors['foreground'])
-
- # Active code context, change font.
- cc.text['font'] = test_font
- cc.config_timer_event()
- eq(cc.textfont, test_font)
- eq(cc.contextcolors, save_colors)
- eq(cc.context['font'], test_font)
- eq(cc.context['background'], save_colors['background'])
- eq(cc.context['foreground'], save_colors['foreground'])
-
- # Active code context, change color.
- cc.text['font'] = save_font
- codecontext.CodeContext.colors = test_colors
- cc.config_timer_event()
- eq(cc.textfont, save_font)
- eq(cc.contextcolors, test_colors)
- eq(cc.context['font'], save_font)
- eq(cc.context['background'], test_colors['background'])
- eq(cc.context['foreground'], test_colors['foreground'])
- codecontext.CodeContext.colors = save_colors
- cc.config_timer_event()
+ assert_colors_are_equal(test_colors)
+
+ # Call colors update with no change to the configured colors.
+ cc.update_highlight_colors()
+ assert_colors_are_equal(test_colors)
+
+ # Call the colors update with code context active, change is picked up.
+ self.highlight_cfg = orig_colors
+ cc.update_highlight_colors()
+ assert_colors_are_equal(orig_colors)
class HelperFunctionText(unittest.TestCase):
self.assertFalse(parser.IsEmpty())
self.assertCountEqual(parser.sections(), ['Foo'])
- def test_remove_file(self):
- with tempfile.TemporaryDirectory() as tdir:
- path = os.path.join(tdir, 'test.cfg')
- parser = self.new_parser(path)
- parser.RemoveFile() # Should not raise exception.
-
- parser.AddSection('Foo')
- parser.SetOption('Foo', 'bar', 'true')
- parser.Save()
- self.assertTrue(os.path.exists(path))
- parser.RemoveFile()
- self.assertFalse(os.path.exists(path))
-
def test_save(self):
with tempfile.TemporaryDirectory() as tdir:
path = os.path.join(tdir, 'test.cfg')
@unittest.skipIf(sys.platform.startswith('win'), 'this is test for unix system')
def test_get_user_cfg_dir_unix(self):
- "Test to get user config directory under unix"
+ # Test to get user config directory under unix.
conf = self.new_config(_utest=True)
# Check normal way should success
@unittest.skipIf(not sys.platform.startswith('win'), 'this is test for Windows system')
def test_get_user_cfg_dir_windows(self):
- "Test to get user config directory under Windows"
+ # Test to get user config directory under Windows.
conf = self.new_config(_utest=True)
# Check normal way should success
self.assertIsInstance(user_parser, config.IdleUserConfParser)
# Check config path are correct
- for config_type, parser in conf.defaultCfg.items():
+ for cfg_type, parser in conf.defaultCfg.items():
self.assertEqual(parser.file,
- os.path.join(idle_dir, 'config-%s.def' % config_type))
- for config_type, parser in conf.userCfg.items():
+ os.path.join(idle_dir, f'config-{cfg_type}.def'))
+ for cfg_type, parser in conf.userCfg.items():
self.assertEqual(parser.file,
- os.path.join(conf.userdir, 'config-%s.cfg' % config_type))
+ os.path.join(conf.userdir or '#', f'config-{cfg_type}.cfg'))
def test_load_cfg_files(self):
conf = self.new_config(_utest=True)
'background': '#171717'})
def test_get_theme_dict(self):
- "XXX: NOT YET DONE"
+ # TODO: finish.
conf = self.mock_config()
# These two should be the same
self.assertEqual(func(dummy, inp), out)
+class TestGetLineIndent(unittest.TestCase):
+ def test_empty_lines(self):
+ for tabwidth in [1, 2, 4, 6, 8]:
+ for line in ['', '\n']:
+ with self.subTest(line=line, tabwidth=tabwidth):
+ self.assertEqual(
+ editor.get_line_indent(line, tabwidth=tabwidth),
+ (0, 0),
+ )
+
+ def test_tabwidth_4(self):
+ # (line, (raw, effective))
+ tests = (('no spaces', (0, 0)),
+ # Internal space isn't counted.
+ (' space test', (4, 4)),
+ ('\ttab test', (1, 4)),
+ ('\t\tdouble tabs test', (2, 8)),
+ # Different results when mixing tabs and spaces.
+ (' \tmixed test', (5, 8)),
+ (' \t mixed test', (5, 6)),
+ ('\t mixed test', (5, 8)),
+ # Spaces not divisible by tabwidth.
+ (' \tmixed test', (3, 4)),
+ (' \t mixed test', (3, 5)),
+ ('\t mixed test', (3, 6)),
+ # Only checks spaces and tabs.
+ ('\nnewline test', (0, 0)))
+
+ for line, expected in tests:
+ with self.subTest(line=line):
+ self.assertEqual(
+ editor.get_line_indent(line, tabwidth=4),
+ expected,
+ )
+
+ def test_tabwidth_8(self):
+ # (line, (raw, effective))
+ tests = (('no spaces', (0, 0)),
+ # Internal space isn't counted.
+ (' space test', (8, 8)),
+ ('\ttab test', (1, 8)),
+ ('\t\tdouble tabs test', (2, 16)),
+ # Different results when mixing tabs and spaces.
+ (' \tmixed test', (9, 16)),
+ (' \t mixed test', (9, 10)),
+ ('\t mixed test', (9, 16)),
+ # Spaces not divisible by tabwidth.
+ (' \tmixed test', (3, 8)),
+ (' \t mixed test', (3, 9)),
+ ('\t mixed test', (3, 10)),
+ # Only checks spaces and tabs.
+ ('\nnewline test', (0, 0)))
+
+ for line, expected in tests:
+ with self.subTest(line=line):
+ self.assertEqual(
+ editor.get_line_indent(line, tabwidth=8),
+ expected,
+ )
+
+
if __name__ == '__main__':
unittest.main(verbosity=2)
--- /dev/null
+"Test format, coverage 99%."
+
+from idlelib import format as ft
+import unittest
+from unittest import mock
+from test.support import requires
+from tkinter import Tk, Text
+from idlelib.editor import EditorWindow
+from idlelib.idle_test.mock_idle import Editor as MockEditor
+
+
+class Is_Get_Test(unittest.TestCase):
+ """Test the is_ and get_ functions"""
+ test_comment = '# This is a comment'
+ test_nocomment = 'This is not a comment'
+ trailingws_comment = '# This is a comment '
+ leadingws_comment = ' # This is a comment'
+ leadingws_nocomment = ' This is not a comment'
+
+ def test_is_all_white(self):
+ self.assertTrue(ft.is_all_white(''))
+ self.assertTrue(ft.is_all_white('\t\n\r\f\v'))
+ self.assertFalse(ft.is_all_white(self.test_comment))
+
+ def test_get_indent(self):
+ Equal = self.assertEqual
+ Equal(ft.get_indent(self.test_comment), '')
+ Equal(ft.get_indent(self.trailingws_comment), '')
+ Equal(ft.get_indent(self.leadingws_comment), ' ')
+ Equal(ft.get_indent(self.leadingws_nocomment), ' ')
+
+ def test_get_comment_header(self):
+ Equal = self.assertEqual
+ # Test comment strings
+ Equal(ft.get_comment_header(self.test_comment), '#')
+ Equal(ft.get_comment_header(self.trailingws_comment), '#')
+ Equal(ft.get_comment_header(self.leadingws_comment), ' #')
+ # Test non-comment strings
+ Equal(ft.get_comment_header(self.leadingws_nocomment), ' ')
+ Equal(ft.get_comment_header(self.test_nocomment), '')
+
+
+class FindTest(unittest.TestCase):
+ """Test the find_paragraph function in paragraph module.
+
+ Using the runcase() function, find_paragraph() is called with 'mark' set at
+ multiple indexes before and inside the test paragraph.
+
+ It appears that code with the same indentation as a quoted string is grouped
+ as part of the same paragraph, which is probably incorrect behavior.
+ """
+
+ @classmethod
+ def setUpClass(cls):
+ from idlelib.idle_test.mock_tk import Text
+ cls.text = Text()
+
+ def runcase(self, inserttext, stopline, expected):
+ # Check that find_paragraph returns the expected paragraph when
+ # the mark index is set to beginning, middle, end of each line
+ # up to but not including the stop line
+ text = self.text
+ text.insert('1.0', inserttext)
+ for line in range(1, stopline):
+ linelength = int(text.index("%d.end" % line).split('.')[1])
+ for col in (0, linelength//2, linelength):
+ tempindex = "%d.%d" % (line, col)
+ self.assertEqual(ft.find_paragraph(text, tempindex), expected)
+ text.delete('1.0', 'end')
+
+ def test_find_comment(self):
+ comment = (
+ "# Comment block with no blank lines before\n"
+ "# Comment line\n"
+ "\n")
+ self.runcase(comment, 3, ('1.0', '3.0', '#', comment[0:58]))
+
+ comment = (
+ "\n"
+ "# Comment block with whitespace line before and after\n"
+ "# Comment line\n"
+ "\n")
+ self.runcase(comment, 4, ('2.0', '4.0', '#', comment[1:70]))
+
+ comment = (
+ "\n"
+ " # Indented comment block with whitespace before and after\n"
+ " # Comment line\n"
+ "\n")
+ self.runcase(comment, 4, ('2.0', '4.0', ' #', comment[1:82]))
+
+ comment = (
+ "\n"
+ "# Single line comment\n"
+ "\n")
+ self.runcase(comment, 3, ('2.0', '3.0', '#', comment[1:23]))
+
+ comment = (
+ "\n"
+ " # Single line comment with leading whitespace\n"
+ "\n")
+ self.runcase(comment, 3, ('2.0', '3.0', ' #', comment[1:51]))
+
+ comment = (
+ "\n"
+ "# Comment immediately followed by code\n"
+ "x = 42\n"
+ "\n")
+ self.runcase(comment, 3, ('2.0', '3.0', '#', comment[1:40]))
+
+ comment = (
+ "\n"
+ " # Indented comment immediately followed by code\n"
+ "x = 42\n"
+ "\n")
+ self.runcase(comment, 3, ('2.0', '3.0', ' #', comment[1:53]))
+
+ comment = (
+ "\n"
+ "# Comment immediately followed by indented code\n"
+ " x = 42\n"
+ "\n")
+ self.runcase(comment, 3, ('2.0', '3.0', '#', comment[1:49]))
+
+ def test_find_paragraph(self):
+ teststring = (
+ '"""String with no blank lines before\n'
+ 'String line\n'
+ '"""\n'
+ '\n')
+ self.runcase(teststring, 4, ('1.0', '4.0', '', teststring[0:53]))
+
+ teststring = (
+ "\n"
+ '"""String with whitespace line before and after\n'
+ 'String line.\n'
+ '"""\n'
+ '\n')
+ self.runcase(teststring, 5, ('2.0', '5.0', '', teststring[1:66]))
+
+ teststring = (
+ '\n'
+ ' """Indented string with whitespace before and after\n'
+ ' Comment string.\n'
+ ' """\n'
+ '\n')
+ self.runcase(teststring, 5, ('2.0', '5.0', ' ', teststring[1:85]))
+
+ teststring = (
+ '\n'
+ '"""Single line string."""\n'
+ '\n')
+ self.runcase(teststring, 3, ('2.0', '3.0', '', teststring[1:27]))
+
+ teststring = (
+ '\n'
+ ' """Single line string with leading whitespace."""\n'
+ '\n')
+ self.runcase(teststring, 3, ('2.0', '3.0', ' ', teststring[1:55]))
+
+
+class ReformatFunctionTest(unittest.TestCase):
+ """Test the reformat_paragraph function without the editor window."""
+
+ def test_reformat_paragraph(self):
+ Equal = self.assertEqual
+ reform = ft.reformat_paragraph
+ hw = "O hello world"
+ Equal(reform(' ', 1), ' ')
+ Equal(reform("Hello world", 20), "Hello world")
+
+ # Test without leading newline
+ Equal(reform(hw, 1), "O\nhello\nworld")
+ Equal(reform(hw, 6), "O\nhello\nworld")
+ Equal(reform(hw, 7), "O hello\nworld")
+ Equal(reform(hw, 12), "O hello\nworld")
+ Equal(reform(hw, 13), "O hello world")
+
+ # Test with leading newline
+ hw = "\nO hello world"
+ Equal(reform(hw, 1), "\nO\nhello\nworld")
+ Equal(reform(hw, 6), "\nO\nhello\nworld")
+ Equal(reform(hw, 7), "\nO hello\nworld")
+ Equal(reform(hw, 12), "\nO hello\nworld")
+ Equal(reform(hw, 13), "\nO hello world")
+
+
+class ReformatCommentTest(unittest.TestCase):
+ """Test the reformat_comment function without the editor window."""
+
+ def test_reformat_comment(self):
+ Equal = self.assertEqual
+
+ # reformat_comment formats to a minimum of 20 characters
+ test_string = (
+ " \"\"\"this is a test of a reformat for a triple quoted string"
+ " will it reformat to less than 70 characters for me?\"\"\"")
+ result = ft.reformat_comment(test_string, 70, " ")
+ expected = (
+ " \"\"\"this is a test of a reformat for a triple quoted string will it\n"
+ " reformat to less than 70 characters for me?\"\"\"")
+ Equal(result, expected)
+
+ test_comment = (
+ "# this is a test of a reformat for a triple quoted string will "
+ "it reformat to less than 70 characters for me?")
+ result = ft.reformat_comment(test_comment, 70, "#")
+ expected = (
+ "# this is a test of a reformat for a triple quoted string will it\n"
+ "# reformat to less than 70 characters for me?")
+ Equal(result, expected)
+
+
+class FormatClassTest(unittest.TestCase):
+ def test_init_close(self):
+ instance = ft.FormatParagraph('editor')
+ self.assertEqual(instance.editwin, 'editor')
+ instance.close()
+ self.assertEqual(instance.editwin, None)
+
+
+# For testing format_paragraph_event, Initialize FormatParagraph with
+# a mock Editor with .text and .get_selection_indices. The text must
+# be a Text wrapper that adds two methods
+
+# A real EditorWindow creates unneeded, time-consuming baggage and
+# sometimes emits shutdown warnings like this:
+# "warning: callback failed in WindowList <class '_tkinter.TclError'>
+# : invalid command name ".55131368.windows".
+# Calling EditorWindow._close in tearDownClass prevents this but causes
+# other problems (windows left open).
+
+class TextWrapper:
+ def __init__(self, master):
+ self.text = Text(master=master)
+ def __getattr__(self, name):
+ return getattr(self.text, name)
+ def undo_block_start(self): pass
+ def undo_block_stop(self): pass
+
+class Editor:
+ def __init__(self, root):
+ self.text = TextWrapper(root)
+ get_selection_indices = EditorWindow. get_selection_indices
+
+class FormatEventTest(unittest.TestCase):
+ """Test the formatting of text inside a Text widget.
+
+ This is done with FormatParagraph.format.paragraph_event,
+ which calls functions in the module as appropriate.
+ """
+ test_string = (
+ " '''this is a test of a reformat for a triple "
+ "quoted string will it reformat to less than 70 "
+ "characters for me?'''\n")
+ multiline_test_string = (
+ " '''The first line is under the max width.\n"
+ " The second line's length is way over the max width. It goes "
+ "on and on until it is over 100 characters long.\n"
+ " Same thing with the third line. It is also way over the max "
+ "width, but FormatParagraph will fix it.\n"
+ " '''\n")
+ multiline_test_comment = (
+ "# The first line is under the max width.\n"
+ "# The second line's length is way over the max width. It goes on "
+ "and on until it is over 100 characters long.\n"
+ "# Same thing with the third line. It is also way over the max "
+ "width, but FormatParagraph will fix it.\n"
+ "# The fourth line is short like the first line.")
+
+ @classmethod
+ def setUpClass(cls):
+ requires('gui')
+ cls.root = Tk()
+ cls.root.withdraw()
+ editor = Editor(root=cls.root)
+ cls.text = editor.text.text # Test code does not need the wrapper.
+ cls.formatter = ft.FormatParagraph(editor).format_paragraph_event
+ # Sets the insert mark just after the re-wrapped and inserted text.
+
+ @classmethod
+ def tearDownClass(cls):
+ del cls.text, cls.formatter
+ cls.root.update_idletasks()
+ cls.root.destroy()
+ del cls.root
+
+ def test_short_line(self):
+ self.text.insert('1.0', "Short line\n")
+ self.formatter("Dummy")
+ self.assertEqual(self.text.get('1.0', 'insert'), "Short line\n" )
+ self.text.delete('1.0', 'end')
+
+ def test_long_line(self):
+ text = self.text
+
+ # Set cursor ('insert' mark) to '1.0', within text.
+ text.insert('1.0', self.test_string)
+ text.mark_set('insert', '1.0')
+ self.formatter('ParameterDoesNothing', limit=70)
+ result = text.get('1.0', 'insert')
+ # find function includes \n
+ expected = (
+" '''this is a test of a reformat for a triple quoted string will it\n"
+" reformat to less than 70 characters for me?'''\n") # yes
+ self.assertEqual(result, expected)
+ text.delete('1.0', 'end')
+
+ # Select from 1.11 to line end.
+ text.insert('1.0', self.test_string)
+ text.tag_add('sel', '1.11', '1.end')
+ self.formatter('ParameterDoesNothing', limit=70)
+ result = text.get('1.0', 'insert')
+ # selection excludes \n
+ expected = (
+" '''this is a test of a reformat for a triple quoted string will it reformat\n"
+" to less than 70 characters for me?'''") # no
+ self.assertEqual(result, expected)
+ text.delete('1.0', 'end')
+
+ def test_multiple_lines(self):
+ text = self.text
+ # Select 2 long lines.
+ text.insert('1.0', self.multiline_test_string)
+ text.tag_add('sel', '2.0', '4.0')
+ self.formatter('ParameterDoesNothing', limit=70)
+ result = text.get('2.0', 'insert')
+ expected = (
+" The second line's length is way over the max width. It goes on and\n"
+" on until it is over 100 characters long. Same thing with the third\n"
+" line. It is also way over the max width, but FormatParagraph will\n"
+" fix it.\n")
+ self.assertEqual(result, expected)
+ text.delete('1.0', 'end')
+
+ def test_comment_block(self):
+ text = self.text
+
+ # Set cursor ('insert') to '1.0', within block.
+ text.insert('1.0', self.multiline_test_comment)
+ self.formatter('ParameterDoesNothing', limit=70)
+ result = text.get('1.0', 'insert')
+ expected = (
+"# The first line is under the max width. The second line's length is\n"
+"# way over the max width. It goes on and on until it is over 100\n"
+"# characters long. Same thing with the third line. It is also way over\n"
+"# the max width, but FormatParagraph will fix it. The fourth line is\n"
+"# short like the first line.\n")
+ self.assertEqual(result, expected)
+ text.delete('1.0', 'end')
+
+ # Select line 2, verify line 1 unaffected.
+ text.insert('1.0', self.multiline_test_comment)
+ text.tag_add('sel', '2.0', '3.0')
+ self.formatter('ParameterDoesNothing', limit=70)
+ result = text.get('1.0', 'insert')
+ expected = (
+"# The first line is under the max width.\n"
+"# The second line's length is way over the max width. It goes on and\n"
+"# on until it is over 100 characters long.\n")
+ self.assertEqual(result, expected)
+ text.delete('1.0', 'end')
+
+# The following block worked with EditorWindow but fails with the mock.
+# Lines 2 and 3 get pasted together even though the previous block left
+# the previous line alone. More investigation is needed.
+## # Select lines 3 and 4
+## text.insert('1.0', self.multiline_test_comment)
+## text.tag_add('sel', '3.0', '5.0')
+## self.formatter('ParameterDoesNothing')
+## result = text.get('3.0', 'insert')
+## expected = (
+##"# Same thing with the third line. It is also way over the max width,\n"
+##"# but FormatParagraph will fix it. The fourth line is short like the\n"
+##"# first line.\n")
+## self.assertEqual(result, expected)
+## text.delete('1.0', 'end')
+
+
+class DummyEditwin:
+ def __init__(self, root, text):
+ self.root = root
+ self.text = text
+ self.indentwidth = 4
+ self.tabwidth = 4
+ self.usetabs = False
+ self.context_use_ps1 = True
+
+ _make_blanks = EditorWindow._make_blanks
+ get_selection_indices = EditorWindow.get_selection_indices
+
+
+class FormatRegionTest(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ requires('gui')
+ cls.root = Tk()
+ cls.root.withdraw()
+ cls.text = Text(cls.root)
+ cls.text.undo_block_start = mock.Mock()
+ cls.text.undo_block_stop = mock.Mock()
+ cls.editor = DummyEditwin(cls.root, cls.text)
+ cls.formatter = ft.FormatRegion(cls.editor)
+
+ @classmethod
+ def tearDownClass(cls):
+ del cls.text, cls.formatter, cls.editor
+ cls.root.update_idletasks()
+ cls.root.destroy()
+ del cls.root
+
+ def setUp(self):
+ self.text.insert('1.0', self.code_sample)
+
+ def tearDown(self):
+ self.text.delete('1.0', 'end')
+
+ code_sample = """\
+
+class C1():
+ # Class comment.
+ def __init__(self, a, b):
+ self.a = a
+ self.b = b
+
+ def compare(self):
+ if a > b:
+ return a
+ elif a < b:
+ return b
+ else:
+ return None
+"""
+
+ def test_get_region(self):
+ get = self.formatter.get_region
+ text = self.text
+ eq = self.assertEqual
+
+ # Add selection.
+ text.tag_add('sel', '7.0', '10.0')
+ expected_lines = ['',
+ ' def compare(self):',
+ ' if a > b:',
+ '']
+ eq(get(), ('7.0', '10.0', '\n'.join(expected_lines), expected_lines))
+
+ # Remove selection.
+ text.tag_remove('sel', '1.0', 'end')
+ eq(get(), ('15.0', '16.0', '\n', ['', '']))
+
+ def test_set_region(self):
+ set_ = self.formatter.set_region
+ text = self.text
+ eq = self.assertEqual
+
+ save_bell = text.bell
+ text.bell = mock.Mock()
+ line6 = self.code_sample.splitlines()[5]
+ line10 = self.code_sample.splitlines()[9]
+
+ text.tag_add('sel', '6.0', '11.0')
+ head, tail, chars, lines = self.formatter.get_region()
+
+ # No changes.
+ set_(head, tail, chars, lines)
+ text.bell.assert_called_once()
+ eq(text.get('6.0', '11.0'), chars)
+ eq(text.get('sel.first', 'sel.last'), chars)
+ text.tag_remove('sel', '1.0', 'end')
+
+ # Alter selected lines by changing lines and adding a newline.
+ newstring = 'added line 1\n\n\n\n'
+ newlines = newstring.split('\n')
+ set_('7.0', '10.0', chars, newlines)
+ # Selection changed.
+ eq(text.get('sel.first', 'sel.last'), newstring)
+ # Additional line added, so last index is changed.
+ eq(text.get('7.0', '11.0'), newstring)
+ # Before and after lines unchanged.
+ eq(text.get('6.0', '7.0-1c'), line6)
+ eq(text.get('11.0', '12.0-1c'), line10)
+ text.tag_remove('sel', '1.0', 'end')
+
+ text.bell = save_bell
+
+ def test_indent_region_event(self):
+ indent = self.formatter.indent_region_event
+ text = self.text
+ eq = self.assertEqual
+
+ text.tag_add('sel', '7.0', '10.0')
+ indent()
+ # Blank lines aren't affected by indent.
+ eq(text.get('7.0', '10.0'), ('\n def compare(self):\n if a > b:\n'))
+
+ def test_dedent_region_event(self):
+ dedent = self.formatter.dedent_region_event
+ text = self.text
+ eq = self.assertEqual
+
+ text.tag_add('sel', '7.0', '10.0')
+ dedent()
+ # Blank lines aren't affected by dedent.
+ eq(text.get('7.0', '10.0'), ('\ndef compare(self):\n if a > b:\n'))
+
+ def test_comment_region_event(self):
+ comment = self.formatter.comment_region_event
+ text = self.text
+ eq = self.assertEqual
+
+ text.tag_add('sel', '7.0', '10.0')
+ comment()
+ eq(text.get('7.0', '10.0'), ('##\n## def compare(self):\n## if a > b:\n'))
+
+ def test_uncomment_region_event(self):
+ comment = self.formatter.comment_region_event
+ uncomment = self.formatter.uncomment_region_event
+ text = self.text
+ eq = self.assertEqual
+
+ text.tag_add('sel', '7.0', '10.0')
+ comment()
+ uncomment()
+ eq(text.get('7.0', '10.0'), ('\n def compare(self):\n if a > b:\n'))
+
+ # Only remove comments at the beginning of a line.
+ text.tag_remove('sel', '1.0', 'end')
+ text.tag_add('sel', '3.0', '4.0')
+ uncomment()
+ eq(text.get('3.0', '3.end'), (' # Class comment.'))
+
+ self.formatter.set_region('3.0', '4.0', '', ['# Class comment.', ''])
+ uncomment()
+ eq(text.get('3.0', '3.end'), (' Class comment.'))
+
+ @mock.patch.object(ft.FormatRegion, "_asktabwidth")
+ def test_tabify_region_event(self, _asktabwidth):
+ tabify = self.formatter.tabify_region_event
+ text = self.text
+ eq = self.assertEqual
+
+ text.tag_add('sel', '7.0', '10.0')
+ # No tabwidth selected.
+ _asktabwidth.return_value = None
+ self.assertIsNone(tabify())
+
+ _asktabwidth.return_value = 3
+ self.assertIsNotNone(tabify())
+ eq(text.get('7.0', '10.0'), ('\n\t def compare(self):\n\t\t if a > b:\n'))
+
+ @mock.patch.object(ft.FormatRegion, "_asktabwidth")
+ def test_untabify_region_event(self, _asktabwidth):
+ untabify = self.formatter.untabify_region_event
+ text = self.text
+ eq = self.assertEqual
+
+ text.tag_add('sel', '7.0', '10.0')
+ # No tabwidth selected.
+ _asktabwidth.return_value = None
+ self.assertIsNone(untabify())
+
+ _asktabwidth.return_value = 2
+ self.formatter.tabify_region_event()
+ _asktabwidth.return_value = 3
+ self.assertIsNotNone(untabify())
+ eq(text.get('7.0', '10.0'), ('\n def compare(self):\n if a > b:\n'))
+
+ @mock.patch.object(ft, "askinteger")
+ def test_ask_tabwidth(self, askinteger):
+ ask = self.formatter._asktabwidth
+ askinteger.return_value = 10
+ self.assertEqual(ask(), 10)
+
+
+class rstripTest(unittest.TestCase):
+
+ def test_rstrip_line(self):
+ editor = MockEditor()
+ text = editor.text
+ do_rstrip = ft.Rstrip(editor).do_rstrip
+ eq = self.assertEqual
+
+ do_rstrip()
+ eq(text.get('1.0', 'insert'), '')
+ text.insert('1.0', ' ')
+ do_rstrip()
+ eq(text.get('1.0', 'insert'), '')
+ text.insert('1.0', ' \n')
+ do_rstrip()
+ eq(text.get('1.0', 'insert'), '\n')
+
+ def test_rstrip_multiple(self):
+ editor = MockEditor()
+ # Comment above, uncomment 3 below to test with real Editor & Text.
+ #from idlelib.editor import EditorWindow as Editor
+ #from tkinter import Tk
+ #editor = Editor(root=Tk())
+ text = editor.text
+ do_rstrip = ft.Rstrip(editor).do_rstrip
+
+ original = (
+ "Line with an ending tab \n"
+ "Line ending in 5 spaces \n"
+ "Linewithnospaces\n"
+ " indented line\n"
+ " indented line with trailing space \n"
+ " ")
+ stripped = (
+ "Line with an ending tab\n"
+ "Line ending in 5 spaces\n"
+ "Linewithnospaces\n"
+ " indented line\n"
+ " indented line with trailing space\n")
+
+ text.insert('1.0', original)
+ do_rstrip()
+ self.assertEqual(text.get('1.0', 'insert'), stripped)
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2, exit=2)
mctext = self.mc(self.root)
self.assertIsInstance(mctext._MultiCall__binders, list)
+ def test_yview(self):
+ # Added for tree.wheel_event
+ # (it depends on yview to not be overriden)
+ mc = self.mc
+ self.assertIs(mc.yview, Text.yview)
+ mctext = self.mc(self.root)
+ self.assertIs(mctext.yview.__func__, Text.yview)
+
if __name__ == '__main__':
unittest.main(verbosity=2)
+++ /dev/null
-"Test paragraph, coverage 76%."
-
-from idlelib import paragraph as pg
-import unittest
-from test.support import requires
-from tkinter import Tk, Text
-from idlelib.editor import EditorWindow
-
-
-class Is_Get_Test(unittest.TestCase):
- """Test the is_ and get_ functions"""
- test_comment = '# This is a comment'
- test_nocomment = 'This is not a comment'
- trailingws_comment = '# This is a comment '
- leadingws_comment = ' # This is a comment'
- leadingws_nocomment = ' This is not a comment'
-
- def test_is_all_white(self):
- self.assertTrue(pg.is_all_white(''))
- self.assertTrue(pg.is_all_white('\t\n\r\f\v'))
- self.assertFalse(pg.is_all_white(self.test_comment))
-
- def test_get_indent(self):
- Equal = self.assertEqual
- Equal(pg.get_indent(self.test_comment), '')
- Equal(pg.get_indent(self.trailingws_comment), '')
- Equal(pg.get_indent(self.leadingws_comment), ' ')
- Equal(pg.get_indent(self.leadingws_nocomment), ' ')
-
- def test_get_comment_header(self):
- Equal = self.assertEqual
- # Test comment strings
- Equal(pg.get_comment_header(self.test_comment), '#')
- Equal(pg.get_comment_header(self.trailingws_comment), '#')
- Equal(pg.get_comment_header(self.leadingws_comment), ' #')
- # Test non-comment strings
- Equal(pg.get_comment_header(self.leadingws_nocomment), ' ')
- Equal(pg.get_comment_header(self.test_nocomment), '')
-
-
-class FindTest(unittest.TestCase):
- """Test the find_paragraph function in paragraph module.
-
- Using the runcase() function, find_paragraph() is called with 'mark' set at
- multiple indexes before and inside the test paragraph.
-
- It appears that code with the same indentation as a quoted string is grouped
- as part of the same paragraph, which is probably incorrect behavior.
- """
-
- @classmethod
- def setUpClass(cls):
- from idlelib.idle_test.mock_tk import Text
- cls.text = Text()
-
- def runcase(self, inserttext, stopline, expected):
- # Check that find_paragraph returns the expected paragraph when
- # the mark index is set to beginning, middle, end of each line
- # up to but not including the stop line
- text = self.text
- text.insert('1.0', inserttext)
- for line in range(1, stopline):
- linelength = int(text.index("%d.end" % line).split('.')[1])
- for col in (0, linelength//2, linelength):
- tempindex = "%d.%d" % (line, col)
- self.assertEqual(pg.find_paragraph(text, tempindex), expected)
- text.delete('1.0', 'end')
-
- def test_find_comment(self):
- comment = (
- "# Comment block with no blank lines before\n"
- "# Comment line\n"
- "\n")
- self.runcase(comment, 3, ('1.0', '3.0', '#', comment[0:58]))
-
- comment = (
- "\n"
- "# Comment block with whitespace line before and after\n"
- "# Comment line\n"
- "\n")
- self.runcase(comment, 4, ('2.0', '4.0', '#', comment[1:70]))
-
- comment = (
- "\n"
- " # Indented comment block with whitespace before and after\n"
- " # Comment line\n"
- "\n")
- self.runcase(comment, 4, ('2.0', '4.0', ' #', comment[1:82]))
-
- comment = (
- "\n"
- "# Single line comment\n"
- "\n")
- self.runcase(comment, 3, ('2.0', '3.0', '#', comment[1:23]))
-
- comment = (
- "\n"
- " # Single line comment with leading whitespace\n"
- "\n")
- self.runcase(comment, 3, ('2.0', '3.0', ' #', comment[1:51]))
-
- comment = (
- "\n"
- "# Comment immediately followed by code\n"
- "x = 42\n"
- "\n")
- self.runcase(comment, 3, ('2.0', '3.0', '#', comment[1:40]))
-
- comment = (
- "\n"
- " # Indented comment immediately followed by code\n"
- "x = 42\n"
- "\n")
- self.runcase(comment, 3, ('2.0', '3.0', ' #', comment[1:53]))
-
- comment = (
- "\n"
- "# Comment immediately followed by indented code\n"
- " x = 42\n"
- "\n")
- self.runcase(comment, 3, ('2.0', '3.0', '#', comment[1:49]))
-
- def test_find_paragraph(self):
- teststring = (
- '"""String with no blank lines before\n'
- 'String line\n'
- '"""\n'
- '\n')
- self.runcase(teststring, 4, ('1.0', '4.0', '', teststring[0:53]))
-
- teststring = (
- "\n"
- '"""String with whitespace line before and after\n'
- 'String line.\n'
- '"""\n'
- '\n')
- self.runcase(teststring, 5, ('2.0', '5.0', '', teststring[1:66]))
-
- teststring = (
- '\n'
- ' """Indented string with whitespace before and after\n'
- ' Comment string.\n'
- ' """\n'
- '\n')
- self.runcase(teststring, 5, ('2.0', '5.0', ' ', teststring[1:85]))
-
- teststring = (
- '\n'
- '"""Single line string."""\n'
- '\n')
- self.runcase(teststring, 3, ('2.0', '3.0', '', teststring[1:27]))
-
- teststring = (
- '\n'
- ' """Single line string with leading whitespace."""\n'
- '\n')
- self.runcase(teststring, 3, ('2.0', '3.0', ' ', teststring[1:55]))
-
-
-class ReformatFunctionTest(unittest.TestCase):
- """Test the reformat_paragraph function without the editor window."""
-
- def test_reformat_paragraph(self):
- Equal = self.assertEqual
- reform = pg.reformat_paragraph
- hw = "O hello world"
- Equal(reform(' ', 1), ' ')
- Equal(reform("Hello world", 20), "Hello world")
-
- # Test without leading newline
- Equal(reform(hw, 1), "O\nhello\nworld")
- Equal(reform(hw, 6), "O\nhello\nworld")
- Equal(reform(hw, 7), "O hello\nworld")
- Equal(reform(hw, 12), "O hello\nworld")
- Equal(reform(hw, 13), "O hello world")
-
- # Test with leading newline
- hw = "\nO hello world"
- Equal(reform(hw, 1), "\nO\nhello\nworld")
- Equal(reform(hw, 6), "\nO\nhello\nworld")
- Equal(reform(hw, 7), "\nO hello\nworld")
- Equal(reform(hw, 12), "\nO hello\nworld")
- Equal(reform(hw, 13), "\nO hello world")
-
-
-class ReformatCommentTest(unittest.TestCase):
- """Test the reformat_comment function without the editor window."""
-
- def test_reformat_comment(self):
- Equal = self.assertEqual
-
- # reformat_comment formats to a minimum of 20 characters
- test_string = (
- " \"\"\"this is a test of a reformat for a triple quoted string"
- " will it reformat to less than 70 characters for me?\"\"\"")
- result = pg.reformat_comment(test_string, 70, " ")
- expected = (
- " \"\"\"this is a test of a reformat for a triple quoted string will it\n"
- " reformat to less than 70 characters for me?\"\"\"")
- Equal(result, expected)
-
- test_comment = (
- "# this is a test of a reformat for a triple quoted string will "
- "it reformat to less than 70 characters for me?")
- result = pg.reformat_comment(test_comment, 70, "#")
- expected = (
- "# this is a test of a reformat for a triple quoted string will it\n"
- "# reformat to less than 70 characters for me?")
- Equal(result, expected)
-
-
-class FormatClassTest(unittest.TestCase):
- def test_init_close(self):
- instance = pg.FormatParagraph('editor')
- self.assertEqual(instance.editwin, 'editor')
- instance.close()
- self.assertEqual(instance.editwin, None)
-
-
-# For testing format_paragraph_event, Initialize FormatParagraph with
-# a mock Editor with .text and .get_selection_indices. The text must
-# be a Text wrapper that adds two methods
-
-# A real EditorWindow creates unneeded, time-consuming baggage and
-# sometimes emits shutdown warnings like this:
-# "warning: callback failed in WindowList <class '_tkinter.TclError'>
-# : invalid command name ".55131368.windows".
-# Calling EditorWindow._close in tearDownClass prevents this but causes
-# other problems (windows left open).
-
-class TextWrapper:
- def __init__(self, master):
- self.text = Text(master=master)
- def __getattr__(self, name):
- return getattr(self.text, name)
- def undo_block_start(self): pass
- def undo_block_stop(self): pass
-
-class Editor:
- def __init__(self, root):
- self.text = TextWrapper(root)
- get_selection_indices = EditorWindow. get_selection_indices
-
-class FormatEventTest(unittest.TestCase):
- """Test the formatting of text inside a Text widget.
-
- This is done with FormatParagraph.format.paragraph_event,
- which calls functions in the module as appropriate.
- """
- test_string = (
- " '''this is a test of a reformat for a triple "
- "quoted string will it reformat to less than 70 "
- "characters for me?'''\n")
- multiline_test_string = (
- " '''The first line is under the max width.\n"
- " The second line's length is way over the max width. It goes "
- "on and on until it is over 100 characters long.\n"
- " Same thing with the third line. It is also way over the max "
- "width, but FormatParagraph will fix it.\n"
- " '''\n")
- multiline_test_comment = (
- "# The first line is under the max width.\n"
- "# The second line's length is way over the max width. It goes on "
- "and on until it is over 100 characters long.\n"
- "# Same thing with the third line. It is also way over the max "
- "width, but FormatParagraph will fix it.\n"
- "# The fourth line is short like the first line.")
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
- editor = Editor(root=cls.root)
- cls.text = editor.text.text # Test code does not need the wrapper.
- cls.formatter = pg.FormatParagraph(editor).format_paragraph_event
- # Sets the insert mark just after the re-wrapped and inserted text.
-
- @classmethod
- def tearDownClass(cls):
- del cls.text, cls.formatter
- cls.root.update_idletasks()
- cls.root.destroy()
- del cls.root
-
- def test_short_line(self):
- self.text.insert('1.0', "Short line\n")
- self.formatter("Dummy")
- self.assertEqual(self.text.get('1.0', 'insert'), "Short line\n" )
- self.text.delete('1.0', 'end')
-
- def test_long_line(self):
- text = self.text
-
- # Set cursor ('insert' mark) to '1.0', within text.
- text.insert('1.0', self.test_string)
- text.mark_set('insert', '1.0')
- self.formatter('ParameterDoesNothing', limit=70)
- result = text.get('1.0', 'insert')
- # find function includes \n
- expected = (
-" '''this is a test of a reformat for a triple quoted string will it\n"
-" reformat to less than 70 characters for me?'''\n") # yes
- self.assertEqual(result, expected)
- text.delete('1.0', 'end')
-
- # Select from 1.11 to line end.
- text.insert('1.0', self.test_string)
- text.tag_add('sel', '1.11', '1.end')
- self.formatter('ParameterDoesNothing', limit=70)
- result = text.get('1.0', 'insert')
- # selection excludes \n
- expected = (
-" '''this is a test of a reformat for a triple quoted string will it reformat\n"
-" to less than 70 characters for me?'''") # no
- self.assertEqual(result, expected)
- text.delete('1.0', 'end')
-
- def test_multiple_lines(self):
- text = self.text
- # Select 2 long lines.
- text.insert('1.0', self.multiline_test_string)
- text.tag_add('sel', '2.0', '4.0')
- self.formatter('ParameterDoesNothing', limit=70)
- result = text.get('2.0', 'insert')
- expected = (
-" The second line's length is way over the max width. It goes on and\n"
-" on until it is over 100 characters long. Same thing with the third\n"
-" line. It is also way over the max width, but FormatParagraph will\n"
-" fix it.\n")
- self.assertEqual(result, expected)
- text.delete('1.0', 'end')
-
- def test_comment_block(self):
- text = self.text
-
- # Set cursor ('insert') to '1.0', within block.
- text.insert('1.0', self.multiline_test_comment)
- self.formatter('ParameterDoesNothing', limit=70)
- result = text.get('1.0', 'insert')
- expected = (
-"# The first line is under the max width. The second line's length is\n"
-"# way over the max width. It goes on and on until it is over 100\n"
-"# characters long. Same thing with the third line. It is also way over\n"
-"# the max width, but FormatParagraph will fix it. The fourth line is\n"
-"# short like the first line.\n")
- self.assertEqual(result, expected)
- text.delete('1.0', 'end')
-
- # Select line 2, verify line 1 unaffected.
- text.insert('1.0', self.multiline_test_comment)
- text.tag_add('sel', '2.0', '3.0')
- self.formatter('ParameterDoesNothing', limit=70)
- result = text.get('1.0', 'insert')
- expected = (
-"# The first line is under the max width.\n"
-"# The second line's length is way over the max width. It goes on and\n"
-"# on until it is over 100 characters long.\n")
- self.assertEqual(result, expected)
- text.delete('1.0', 'end')
-
-# The following block worked with EditorWindow but fails with the mock.
-# Lines 2 and 3 get pasted together even though the previous block left
-# the previous line alone. More investigation is needed.
-## # Select lines 3 and 4
-## text.insert('1.0', self.multiline_test_comment)
-## text.tag_add('sel', '3.0', '5.0')
-## self.formatter('ParameterDoesNothing')
-## result = text.get('3.0', 'insert')
-## expected = (
-##"# Same thing with the third line. It is also way over the max width,\n"
-##"# but FormatParagraph will fix it. The fourth line is short like the\n"
-##"# first line.\n")
-## self.assertEqual(result, expected)
-## text.delete('1.0', 'end')
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2, exit=2)
'openbracket', 'bracketing'])
tests = (
TestInfo('', 0, 0, '', None, ((0, 0),)),
- TestInfo("'''This is a multiline continutation docstring.\n\n",
- 0, 49, "'", None, ((0, 0), (0, 1), (49, 0))),
+ TestInfo("'''This is a multiline continuation docstring.\n\n",
+ 0, 48, "'", None, ((0, 0), (0, 1), (48, 0))),
TestInfo(' # Comment\\\n',
0, 12, '', None, ((0, 0), (1, 1), (12, 0))),
# A comment without a space is a special case
from tkinter import Tk
+class FunctionTest(unittest.TestCase):
+ # Test stand-alone module level non-gui functions.
+
+ def test_restart_line_wide(self):
+ eq = self.assertEqual
+ for file, mul, extra in (('', 22, ''), ('finame', 21, '=')):
+ width = 60
+ bar = mul * '='
+ with self.subTest(file=file, bar=bar):
+ file = file or 'Shell'
+ line = pyshell.restart_line(width, file)
+ eq(len(line), width)
+ eq(line, f"{bar+extra} RESTART: {file} {bar}")
+
+ def test_restart_line_narrow(self):
+ expect, taglen = "= RESTART: Shell", 16
+ for width in (taglen-1, taglen, taglen+1):
+ with self.subTest(width=width):
+ self.assertEqual(pyshell.restart_line(width, ''), expect)
+ self.assertEqual(pyshell.restart_line(taglen+2, ''), expect+' =')
+
+
class PyShellFileListTest(unittest.TestCase):
@classmethod
from idlelib import query
import unittest
from test.support import requires
-from tkinter import Tk
+from tkinter import Tk, END
import sys
from unittest import mock
def test_click_args(self):
root = Tk()
root.withdraw()
- dialog = query.CustomRun(root, 'Title', _utest=True)
- dialog.entry.insert(0, 'okay')
+ dialog = query.CustomRun(root, 'Title',
+ cli_args=['a', 'b=1'], _utest=True)
+ self.assertEqual(dialog.entry.get(), 'a b=1')
+ dialog.entry.insert(END, ' c')
dialog.button_ok.invoke()
- self.assertEqual(dialog.result, (['okay'], True))
+ self.assertEqual(dialog.result, (['a', 'b=1', 'c'], True))
root.destroy()
+++ /dev/null
-"Test rstrip, coverage 100%."
-
-from idlelib import rstrip
-import unittest
-from idlelib.idle_test.mock_idle import Editor
-
-class rstripTest(unittest.TestCase):
-
- def test_rstrip_line(self):
- editor = Editor()
- text = editor.text
- do_rstrip = rstrip.Rstrip(editor).do_rstrip
-
- do_rstrip()
- self.assertEqual(text.get('1.0', 'insert'), '')
- text.insert('1.0', ' ')
- do_rstrip()
- self.assertEqual(text.get('1.0', 'insert'), '')
- text.insert('1.0', ' \n')
- do_rstrip()
- self.assertEqual(text.get('1.0', 'insert'), '\n')
-
- def test_rstrip_multiple(self):
- editor = Editor()
- # Comment above, uncomment 3 below to test with real Editor & Text.
- #from idlelib.editor import EditorWindow as Editor
- #from tkinter import Tk
- #editor = Editor(root=Tk())
- text = editor.text
- do_rstrip = rstrip.Rstrip(editor).do_rstrip
-
- original = (
- "Line with an ending tab \n"
- "Line ending in 5 spaces \n"
- "Linewithnospaces\n"
- " indented line\n"
- " indented line with trailing space \n"
- " ")
- stripped = (
- "Line with an ending tab\n"
- "Line ending in 5 spaces\n"
- "Linewithnospaces\n"
- " indented line\n"
- " indented line with trailing space\n")
-
- text.insert('1.0', original)
- do_rstrip()
- self.assertEqual(text.get('1.0', 'insert'), stripped)
-
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
from test.support import captured_stderr
import io
+import sys
+
class RunTest(unittest.TestCase):
self.assertRaises(TypeError, f.close, 1)
+class TestSysRecursionLimitWrappers(unittest.TestCase):
+
+ def test_bad_setrecursionlimit_calls(self):
+ run.install_recursionlimit_wrappers()
+ self.addCleanup(run.uninstall_recursionlimit_wrappers)
+ f = sys.setrecursionlimit
+ self.assertRaises(TypeError, f, limit=100)
+ self.assertRaises(TypeError, f, 100, 1000)
+ self.assertRaises(ValueError, f, 0)
+
+ def test_roundtrip(self):
+ run.install_recursionlimit_wrappers()
+ self.addCleanup(run.uninstall_recursionlimit_wrappers)
+
+ # check that setting the recursion limit works
+ orig_reclimit = sys.getrecursionlimit()
+ self.addCleanup(sys.setrecursionlimit, orig_reclimit)
+ sys.setrecursionlimit(orig_reclimit + 3)
+
+ # check that the new limit is returned by sys.getrecursionlimit()
+ new_reclimit = sys.getrecursionlimit()
+ self.assertEqual(new_reclimit, orig_reclimit + 3)
+
+ def test_default_recursion_limit_preserved(self):
+ orig_reclimit = sys.getrecursionlimit()
+ run.install_recursionlimit_wrappers()
+ self.addCleanup(run.uninstall_recursionlimit_wrappers)
+ new_reclimit = sys.getrecursionlimit()
+ self.assertEqual(new_reclimit, orig_reclimit)
+
+ def test_fixdoc(self):
+ def func(): "docstring"
+ run.fixdoc(func, "more")
+ self.assertEqual(func.__doc__, "docstring\n\nmore")
+ func.__doc__ = None
+ run.fixdoc(func, "more")
+ self.assertEqual(func.__doc__, "more")
+
+
if __name__ == '__main__':
unittest.main(verbosity=2)
--- /dev/null
+"""Test sidebar, coverage 93%"""
+import idlelib.sidebar
+from sys import platform
+from itertools import chain
+import unittest
+import unittest.mock
+from test.support import requires
+import tkinter as tk
+
+from idlelib.delegator import Delegator
+from idlelib.percolator import Percolator
+
+
+class Dummy_editwin:
+ def __init__(self, text):
+ self.text = text
+ self.text_frame = self.text.master
+ self.per = Percolator(text)
+ self.undo = Delegator()
+ self.per.insertfilter(self.undo)
+
+ def setvar(self, name, value):
+ pass
+
+ def getlineno(self, index):
+ return int(float(self.text.index(index)))
+
+
+class LineNumbersTest(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ requires('gui')
+ cls.root = tk.Tk()
+
+ cls.text_frame = tk.Frame(cls.root)
+ cls.text_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
+ cls.text_frame.rowconfigure(1, weight=1)
+ cls.text_frame.columnconfigure(1, weight=1)
+
+ cls.text = tk.Text(cls.text_frame, width=80, height=24, wrap=tk.NONE)
+ cls.text.grid(row=1, column=1, sticky=tk.NSEW)
+
+ cls.editwin = Dummy_editwin(cls.text)
+ cls.editwin.vbar = tk.Scrollbar(cls.text_frame)
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.editwin.per.close()
+ cls.root.update()
+ cls.root.destroy()
+ del cls.text, cls.text_frame, cls.editwin, cls.root
+
+ def setUp(self):
+ self.linenumber = idlelib.sidebar.LineNumbers(self.editwin)
+
+ self.highlight_cfg = {"background": '#abcdef',
+ "foreground": '#123456'}
+ orig_idleConf_GetHighlight = idlelib.sidebar.idleConf.GetHighlight
+ def mock_idleconf_GetHighlight(theme, element):
+ if element == 'linenumber':
+ return self.highlight_cfg
+ return orig_idleConf_GetHighlight(theme, element)
+ GetHighlight_patcher = unittest.mock.patch.object(
+ idlelib.sidebar.idleConf, 'GetHighlight', mock_idleconf_GetHighlight)
+ GetHighlight_patcher.start()
+ self.addCleanup(GetHighlight_patcher.stop)
+
+ self.font_override = 'TkFixedFont'
+ def mock_idleconf_GetFont(root, configType, section):
+ return self.font_override
+ GetFont_patcher = unittest.mock.patch.object(
+ idlelib.sidebar.idleConf, 'GetFont', mock_idleconf_GetFont)
+ GetFont_patcher.start()
+ self.addCleanup(GetFont_patcher.stop)
+
+ def tearDown(self):
+ self.text.delete('1.0', 'end')
+
+ def get_selection(self):
+ return tuple(map(str, self.text.tag_ranges('sel')))
+
+ def get_line_screen_position(self, line):
+ bbox = self.linenumber.sidebar_text.bbox(f'{line}.end -1c')
+ x = bbox[0] + 2
+ y = bbox[1] + 2
+ return x, y
+
+ def assert_state_disabled(self):
+ state = self.linenumber.sidebar_text.config()['state']
+ self.assertEqual(state[-1], tk.DISABLED)
+
+ def get_sidebar_text_contents(self):
+ return self.linenumber.sidebar_text.get('1.0', tk.END)
+
+ def assert_sidebar_n_lines(self, n_lines):
+ expected = '\n'.join(chain(map(str, range(1, n_lines + 1)), ['']))
+ self.assertEqual(self.get_sidebar_text_contents(), expected)
+
+ def assert_text_equals(self, expected):
+ return self.assertEqual(self.text.get('1.0', 'end'), expected)
+
+ def test_init_empty(self):
+ self.assert_sidebar_n_lines(1)
+
+ def test_init_not_empty(self):
+ self.text.insert('insert', 'foo bar\n'*3)
+ self.assert_text_equals('foo bar\n'*3 + '\n')
+ self.assert_sidebar_n_lines(4)
+
+ def test_toggle_linenumbering(self):
+ self.assertEqual(self.linenumber.is_shown, False)
+ self.linenumber.show_sidebar()
+ self.assertEqual(self.linenumber.is_shown, True)
+ self.linenumber.hide_sidebar()
+ self.assertEqual(self.linenumber.is_shown, False)
+ self.linenumber.hide_sidebar()
+ self.assertEqual(self.linenumber.is_shown, False)
+ self.linenumber.show_sidebar()
+ self.assertEqual(self.linenumber.is_shown, True)
+ self.linenumber.show_sidebar()
+ self.assertEqual(self.linenumber.is_shown, True)
+
+ def test_insert(self):
+ self.text.insert('insert', 'foobar')
+ self.assert_text_equals('foobar\n')
+ self.assert_sidebar_n_lines(1)
+ self.assert_state_disabled()
+
+ self.text.insert('insert', '\nfoo')
+ self.assert_text_equals('foobar\nfoo\n')
+ self.assert_sidebar_n_lines(2)
+ self.assert_state_disabled()
+
+ self.text.insert('insert', 'hello\n'*2)
+ self.assert_text_equals('foobar\nfoohello\nhello\n\n')
+ self.assert_sidebar_n_lines(4)
+ self.assert_state_disabled()
+
+ self.text.insert('insert', '\nworld')
+ self.assert_text_equals('foobar\nfoohello\nhello\n\nworld\n')
+ self.assert_sidebar_n_lines(5)
+ self.assert_state_disabled()
+
+ def test_delete(self):
+ self.text.insert('insert', 'foobar')
+ self.assert_text_equals('foobar\n')
+ self.text.delete('1.1', '1.3')
+ self.assert_text_equals('fbar\n')
+ self.assert_sidebar_n_lines(1)
+ self.assert_state_disabled()
+
+ self.text.insert('insert', 'foo\n'*2)
+ self.assert_text_equals('fbarfoo\nfoo\n\n')
+ self.assert_sidebar_n_lines(3)
+ self.assert_state_disabled()
+
+ # Note: deleting up to "2.end" doesn't delete the final newline.
+ self.text.delete('2.0', '2.end')
+ self.assert_text_equals('fbarfoo\n\n\n')
+ self.assert_sidebar_n_lines(3)
+ self.assert_state_disabled()
+
+ self.text.delete('1.3', 'end')
+ self.assert_text_equals('fba\n')
+ self.assert_sidebar_n_lines(1)
+ self.assert_state_disabled()
+
+ # Note: Text widgets always keep a single '\n' character at the end.
+ self.text.delete('1.0', 'end')
+ self.assert_text_equals('\n')
+ self.assert_sidebar_n_lines(1)
+ self.assert_state_disabled()
+
+ def test_sidebar_text_width(self):
+ """
+ Test that linenumber text widget is always at the minimum
+ width
+ """
+ def get_width():
+ return self.linenumber.sidebar_text.config()['width'][-1]
+
+ self.assert_sidebar_n_lines(1)
+ self.assertEqual(get_width(), 1)
+
+ self.text.insert('insert', 'foo')
+ self.assert_sidebar_n_lines(1)
+ self.assertEqual(get_width(), 1)
+
+ self.text.insert('insert', 'foo\n'*8)
+ self.assert_sidebar_n_lines(9)
+ self.assertEqual(get_width(), 1)
+
+ self.text.insert('insert', 'foo\n')
+ self.assert_sidebar_n_lines(10)
+ self.assertEqual(get_width(), 2)
+
+ self.text.insert('insert', 'foo\n')
+ self.assert_sidebar_n_lines(11)
+ self.assertEqual(get_width(), 2)
+
+ self.text.delete('insert -1l linestart', 'insert linestart')
+ self.assert_sidebar_n_lines(10)
+ self.assertEqual(get_width(), 2)
+
+ self.text.delete('insert -1l linestart', 'insert linestart')
+ self.assert_sidebar_n_lines(9)
+ self.assertEqual(get_width(), 1)
+
+ self.text.insert('insert', 'foo\n'*90)
+ self.assert_sidebar_n_lines(99)
+ self.assertEqual(get_width(), 2)
+
+ self.text.insert('insert', 'foo\n')
+ self.assert_sidebar_n_lines(100)
+ self.assertEqual(get_width(), 3)
+
+ self.text.insert('insert', 'foo\n')
+ self.assert_sidebar_n_lines(101)
+ self.assertEqual(get_width(), 3)
+
+ self.text.delete('insert -1l linestart', 'insert linestart')
+ self.assert_sidebar_n_lines(100)
+ self.assertEqual(get_width(), 3)
+
+ self.text.delete('insert -1l linestart', 'insert linestart')
+ self.assert_sidebar_n_lines(99)
+ self.assertEqual(get_width(), 2)
+
+ self.text.delete('50.0 -1c', 'end -1c')
+ self.assert_sidebar_n_lines(49)
+ self.assertEqual(get_width(), 2)
+
+ self.text.delete('5.0 -1c', 'end -1c')
+ self.assert_sidebar_n_lines(4)
+ self.assertEqual(get_width(), 1)
+
+ # Note: Text widgets always keep a single '\n' character at the end.
+ self.text.delete('1.0', 'end -1c')
+ self.assert_sidebar_n_lines(1)
+ self.assertEqual(get_width(), 1)
+
+ def test_click_selection(self):
+ self.linenumber.show_sidebar()
+ self.text.insert('1.0', 'one\ntwo\nthree\nfour\n')
+ self.root.update()
+
+ # Click on the second line.
+ x, y = self.get_line_screen_position(2)
+ self.linenumber.sidebar_text.event_generate('<Button-1>', x=x, y=y)
+ self.linenumber.sidebar_text.update()
+ self.root.update()
+
+ self.assertEqual(self.get_selection(), ('2.0', '3.0'))
+
+ def simulate_drag(self, start_line, end_line):
+ start_x, start_y = self.get_line_screen_position(start_line)
+ end_x, end_y = self.get_line_screen_position(end_line)
+
+ self.linenumber.sidebar_text.event_generate('<Button-1>',
+ x=start_x, y=start_y)
+ self.root.update()
+
+ def lerp(a, b, steps):
+ """linearly interpolate from a to b (inclusive) in equal steps"""
+ last_step = steps - 1
+ for i in range(steps):
+ yield ((last_step - i) / last_step) * a + (i / last_step) * b
+
+ for x, y in zip(
+ map(int, lerp(start_x, end_x, steps=11)),
+ map(int, lerp(start_y, end_y, steps=11)),
+ ):
+ self.linenumber.sidebar_text.event_generate('<B1-Motion>', x=x, y=y)
+ self.root.update()
+
+ self.linenumber.sidebar_text.event_generate('<ButtonRelease-1>',
+ x=end_x, y=end_y)
+ self.root.update()
+
+ def test_drag_selection_down(self):
+ self.linenumber.show_sidebar()
+ self.text.insert('1.0', 'one\ntwo\nthree\nfour\nfive\n')
+ self.root.update()
+
+ # Drag from the second line to the fourth line.
+ self.simulate_drag(2, 4)
+ self.assertEqual(self.get_selection(), ('2.0', '5.0'))
+
+ def test_drag_selection_up(self):
+ self.linenumber.show_sidebar()
+ self.text.insert('1.0', 'one\ntwo\nthree\nfour\nfive\n')
+ self.root.update()
+
+ # Drag from the fourth line to the second line.
+ self.simulate_drag(4, 2)
+ self.assertEqual(self.get_selection(), ('2.0', '5.0'))
+
+ def test_scroll(self):
+ self.linenumber.show_sidebar()
+ self.text.insert('1.0', 'line\n' * 100)
+ self.root.update()
+
+ # Scroll down 10 lines.
+ self.text.yview_scroll(10, 'unit')
+ self.root.update()
+ self.assertEqual(self.text.index('@0,0'), '11.0')
+ self.assertEqual(self.linenumber.sidebar_text.index('@0,0'), '11.0')
+
+ # Generate a mouse-wheel event and make sure it scrolled up or down.
+ # The meaning of the "delta" is OS-dependant, so this just checks for
+ # any change.
+ self.linenumber.sidebar_text.event_generate('<MouseWheel>',
+ x=0, y=0,
+ delta=10)
+ self.root.update()
+ self.assertNotEqual(self.text.index('@0,0'), '11.0')
+ self.assertNotEqual(self.linenumber.sidebar_text.index('@0,0'), '11.0')
+
+ def test_font(self):
+ ln = self.linenumber
+
+ orig_font = ln.sidebar_text['font']
+ test_font = 'TkTextFont'
+ self.assertNotEqual(orig_font, test_font)
+
+ # Ensure line numbers aren't shown.
+ ln.hide_sidebar()
+
+ self.font_override = test_font
+ # Nothing breaks when line numbers aren't shown.
+ ln.update_font()
+
+ # Activate line numbers, previous font change is immediately effective.
+ ln.show_sidebar()
+ self.assertEqual(ln.sidebar_text['font'], test_font)
+
+ # Call the font update with line numbers shown, change is picked up.
+ self.font_override = orig_font
+ ln.update_font()
+ self.assertEqual(ln.sidebar_text['font'], orig_font)
+
+ def test_highlight_colors(self):
+ ln = self.linenumber
+
+ orig_colors = dict(self.highlight_cfg)
+ test_colors = {'background': '#222222', 'foreground': '#ffff00'}
+
+ def assert_colors_are_equal(colors):
+ self.assertEqual(ln.sidebar_text['background'], colors['background'])
+ self.assertEqual(ln.sidebar_text['foreground'], colors['foreground'])
+
+ # Ensure line numbers aren't shown.
+ ln.hide_sidebar()
+
+ self.highlight_cfg = test_colors
+ # Nothing breaks with inactive code context.
+ ln.update_colors()
+
+ # Show line numbers, previous colors change is immediately effective.
+ ln.show_sidebar()
+ assert_colors_are_equal(test_colors)
+
+ # Call colors update with no change to the configured colors.
+ ln.update_colors()
+ assert_colors_are_equal(test_colors)
+
+ # Call the colors update with line numbers shown, change is picked up.
+ self.highlight_cfg = orig_colors
+ ln.update_colors()
+ assert_colors_are_equal(orig_colors)
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
class SqueezerTest(unittest.TestCase):
"""Tests for the Squeezer class."""
- def tearDown(self):
- # Clean up the Squeezer class's reference to its instance,
- # to avoid side-effects from one test case upon another.
- if Squeezer._instance_weakref is not None:
- Squeezer._instance_weakref = None
-
def make_mock_editor_window(self, with_text_widget=False):
"""Create a mock EditorWindow instance."""
editwin = NonCallableMagicMock()
- # isinstance(editwin, PyShell) must be true for Squeezer to enable
- # auto-squeezing; in practice this will always be true.
- editwin.__class__ = PyShell
+ editwin.width = 80
if with_text_widget:
editwin.root = get_test_tk_root(self)
if editor_window is None:
editor_window = self.make_mock_editor_window()
squeezer = Squeezer(editor_window)
- squeezer.get_line_width = Mock(return_value=80)
return squeezer
def make_text_widget(self, root=None):
line_width=line_width,
expected=expected):
text = eval(text_code)
- squeezer.get_line_width.return_value = line_width
- self.assertEqual(squeezer.count_lines(text), expected)
+ with patch.object(editwin, 'width', line_width):
+ self.assertEqual(squeezer.count_lines(text), expected)
def test_init(self):
"""Test the creation of Squeezer instances."""
"""Test the reload() class-method."""
editwin = self.make_mock_editor_window(with_text_widget=True)
squeezer = self.make_squeezer_instance(editwin)
- squeezer.load_font = Mock()
orig_auto_squeeze_min_lines = squeezer.auto_squeeze_min_lines
Squeezer.reload()
self.assertEqual(squeezer.auto_squeeze_min_lines,
new_auto_squeeze_min_lines)
- squeezer.load_font.assert_called()
def test_reload_no_squeezer_instances(self):
"""Test that Squeezer.reload() runs without any instances existing."""
information about calls.
"""
from idlelib import textview as tv
-import unittest
from test.support import requires
requires('gui')
import os
-from tkinter import Tk
+import unittest
+from tkinter import Tk, TclError, CHAR, NONE, WORD
from tkinter.ttk import Button
from idlelib.idle_test.mock_idle import Func
from idlelib.idle_test.mock_tk import Mbox_func
view.destroy()
-class TextFrameTest(unittest.TestCase):
+class AutoHideScrollbarTest(unittest.TestCase):
+ # Method set is tested in ScrollableTextFrameTest
+ def test_forbidden_geometry(self):
+ scroll = tv.AutoHideScrollbar(root)
+ self.assertRaises(TclError, scroll.pack)
+ self.assertRaises(TclError, scroll.place)
+
+
+class ScrollableTextFrameTest(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.root = root = Tk()
+ root.withdraw()
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.root.update_idletasks()
+ cls.root.destroy()
+ del cls.root
+
+ def make_frame(self, wrap=NONE, **kwargs):
+ frame = tv.ScrollableTextFrame(self.root, wrap=wrap, **kwargs)
+ def cleanup_frame():
+ frame.update_idletasks()
+ frame.destroy()
+ self.addCleanup(cleanup_frame)
+ return frame
+
+ def test_line1(self):
+ frame = self.make_frame()
+ frame.text.insert('1.0', 'test text')
+ self.assertEqual(frame.text.get('1.0', '1.end'), 'test text')
+
+ def test_horiz_scrollbar(self):
+ # The horizontal scrollbar should be shown/hidden according to
+ # the 'wrap' setting: It should only be shown when 'wrap' is
+ # set to NONE.
+
+ # wrap = NONE -> with horizontal scrolling
+ frame = self.make_frame(wrap=NONE)
+ self.assertEqual(frame.text.cget('wrap'), NONE)
+ self.assertIsNotNone(frame.xscroll)
+
+ # wrap != NONE -> no horizontal scrolling
+ for wrap in [CHAR, WORD]:
+ with self.subTest(wrap=wrap):
+ frame = self.make_frame(wrap=wrap)
+ self.assertEqual(frame.text.cget('wrap'), wrap)
+ self.assertIsNone(frame.xscroll)
+
+
+class ViewFrameTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.root = root = Tk()
root.withdraw()
- cls.frame = tv.TextFrame(root, 'test text')
+ cls.frame = tv.ViewFrame(root, 'test text')
@classmethod
def tearDownClass(cls):
+"""Test tooltip, coverage 100%.
+
+Coverage is 100% after excluding 6 lines with "# pragma: no cover".
+They involve TclErrors that either should or should not happen in a
+particular situation, and which are 'pass'ed if they do.
+"""
+
from idlelib.tooltip import TooltipBase, Hovertip
from test.support import requires
requires('gui')
global root
root = Tk()
-def root_update():
- global root
- root.update()
-
def tearDownModule():
global root
root.update_idletasks()
root.destroy()
del root
+
def add_call_counting(func):
@wraps(func)
def wrapped_func(*args, **kwargs):
def setUp(self):
self.top, self.button = _make_top_and_button(self)
+ def is_tipwindow_shown(self, tooltip):
+ return tooltip.tipwindow and tooltip.tipwindow.winfo_viewable()
+
def test_showtip(self):
tooltip = Hovertip(self.button, 'ToolTip text')
self.addCleanup(tooltip.hidetip)
- self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
+ self.assertFalse(self.is_tipwindow_shown(tooltip))
tooltip.showtip()
- self.assertTrue(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
+ self.assertTrue(self.is_tipwindow_shown(tooltip))
def test_showtip_twice(self):
tooltip = Hovertip(self.button, 'ToolTip text')
self.addCleanup(tooltip.hidetip)
- self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
+ self.assertFalse(self.is_tipwindow_shown(tooltip))
tooltip.showtip()
- self.assertTrue(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
+ self.assertTrue(self.is_tipwindow_shown(tooltip))
orig_tipwindow = tooltip.tipwindow
tooltip.showtip()
- self.assertTrue(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
+ self.assertTrue(self.is_tipwindow_shown(tooltip))
self.assertIs(tooltip.tipwindow, orig_tipwindow)
def test_hidetip(self):
self.addCleanup(tooltip.hidetip)
tooltip.showtip()
tooltip.hidetip()
- self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
+ self.assertFalse(self.is_tipwindow_shown(tooltip))
def test_showtip_on_mouse_enter_no_delay(self):
tooltip = Hovertip(self.button, 'ToolTip text', hover_delay=None)
self.addCleanup(tooltip.hidetip)
tooltip.showtip = add_call_counting(tooltip.showtip)
- root_update()
- self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
+ root.update()
+ self.assertFalse(self.is_tipwindow_shown(tooltip))
self.button.event_generate('<Enter>', x=0, y=0)
- root_update()
- self.assertTrue(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
+ root.update()
+ self.assertTrue(self.is_tipwindow_shown(tooltip))
self.assertGreater(len(tooltip.showtip.call_args_list), 0)
- def test_showtip_on_mouse_enter_hover_delay(self):
- tooltip = Hovertip(self.button, 'ToolTip text', hover_delay=50)
- self.addCleanup(tooltip.hidetip)
- tooltip.showtip = add_call_counting(tooltip.showtip)
- root_update()
- self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
+ def test_hover_with_delay(self):
+ # Run multiple tests requiring an actual delay simultaneously.
+
+ # Test #1: A hover tip with a non-zero delay appears after the delay.
+ tooltip1 = Hovertip(self.button, 'ToolTip text', hover_delay=100)
+ self.addCleanup(tooltip1.hidetip)
+ tooltip1.showtip = add_call_counting(tooltip1.showtip)
+ root.update()
+ self.assertFalse(self.is_tipwindow_shown(tooltip1))
self.button.event_generate('<Enter>', x=0, y=0)
- root_update()
- self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
- time.sleep(0.1)
- root_update()
- self.assertTrue(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
- self.assertGreater(len(tooltip.showtip.call_args_list), 0)
+ root.update()
+ self.assertFalse(self.is_tipwindow_shown(tooltip1))
+
+ # Test #2: A hover tip with a non-zero delay doesn't appear when
+ # the mouse stops hovering over the base widget before the delay
+ # expires.
+ tooltip2 = Hovertip(self.button, 'ToolTip text', hover_delay=100)
+ self.addCleanup(tooltip2.hidetip)
+ tooltip2.showtip = add_call_counting(tooltip2.showtip)
+ root.update()
+ self.button.event_generate('<Enter>', x=0, y=0)
+ root.update()
+ self.button.event_generate('<Leave>', x=0, y=0)
+ root.update()
+
+ time.sleep(0.15)
+ root.update()
+
+ # Test #1 assertions.
+ self.assertTrue(self.is_tipwindow_shown(tooltip1))
+ self.assertGreater(len(tooltip1.showtip.call_args_list), 0)
+
+ # Test #2 assertions.
+ self.assertFalse(self.is_tipwindow_shown(tooltip2))
+ self.assertEqual(tooltip2.showtip.call_args_list, [])
def test_hidetip_on_mouse_leave(self):
tooltip = Hovertip(self.button, 'ToolTip text', hover_delay=None)
self.addCleanup(tooltip.hidetip)
tooltip.showtip = add_call_counting(tooltip.showtip)
- root_update()
+ root.update()
self.button.event_generate('<Enter>', x=0, y=0)
- root_update()
+ root.update()
self.button.event_generate('<Leave>', x=0, y=0)
- root_update()
- self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
+ root.update()
+ self.assertFalse(self.is_tipwindow_shown(tooltip))
self.assertGreater(len(tooltip.showtip.call_args_list), 0)
- def test_dont_show_on_mouse_leave_before_delay(self):
- tooltip = Hovertip(self.button, 'ToolTip text', hover_delay=50)
- self.addCleanup(tooltip.hidetip)
- tooltip.showtip = add_call_counting(tooltip.showtip)
- root_update()
- self.button.event_generate('<Enter>', x=0, y=0)
- root_update()
- self.button.event_generate('<Leave>', x=0, y=0)
- root_update()
- time.sleep(0.1)
- root_update()
- self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
- self.assertEqual(tooltip.showtip.call_args_list, [])
-
if __name__ == '__main__':
unittest.main(verbosity=2)
import unittest
from test.support import requires
requires('gui')
-from tkinter import Tk
+from tkinter import Tk, EventType, SCROLL
class TreeTest(unittest.TestCase):
node.expand()
+class TestScrollEvent(unittest.TestCase):
+
+ def test_wheel_event(self):
+ # Fake widget class containing `yview` only.
+ class _Widget:
+ def __init__(widget, *expected):
+ widget.expected = expected
+ def yview(widget, *args):
+ self.assertTupleEqual(widget.expected, args)
+ # Fake event class
+ class _Event:
+ pass
+ # (type, delta, num, amount)
+ tests = ((EventType.MouseWheel, 120, -1, -5),
+ (EventType.MouseWheel, -120, -1, 5),
+ (EventType.ButtonPress, -1, 4, -5),
+ (EventType.ButtonPress, -1, 5, 5))
+
+ event = _Event()
+ for ty, delta, num, amount in tests:
+ event.type = ty
+ event.delta = delta
+ event.num = num
+ res = tree.wheel_event(event, _Widget(SCROLL, amount, "units"))
+ self.assertEqual(res, "break")
+
+
if __name__ == '__main__':
unittest.main(verbosity=2)
]),
('format', [
+ ('F_ormat Paragraph', '<<format-paragraph>>'),
('_Indent Region', '<<indent-region>>'),
('_Dedent Region', '<<dedent-region>>'),
('Comment _Out Region', '<<comment-region>>'),
('Untabify Region', '<<untabify-region>>'),
('Toggle Tabs', '<<toggle-tabs>>'),
('New Indent Width', '<<change-indentwidth>>'),
- ('F_ormat Paragraph', '<<format-paragraph>>'),
('S_trip Trailing Whitespace', '<<do-rstrip>>'),
]),
('run', [
- ('Python Shell', '<<open-python-shell>>'),
- ('C_heck Module', '<<check-module>>'),
('R_un Module', '<<run-module>>'),
('Run... _Customized', '<<run-custom>>'),
+ ('C_heck Module', '<<check-module>>'),
+ ('Python Shell', '<<open-python-shell>>'),
]),
('shell', [
('Configure _IDLE', '<<open-config-dialog>>'),
None,
('Show _Code Context', '<<toggle-code-context>>'),
- ('Zoom Height', '<<zoom-height>>'),
+ ('Show _Line Numbers', '<<toggle-line-numbers>>'),
+ ('_Zoom Height', '<<zoom-height>>'),
]),
('window', [
("Go to file/line", "<<goto-file-line>>", None),
]
+ allow_code_context = False
+
def __init__(self, *args):
EditorWindow.__init__(self, *args)
self.text.bind("<<goto-file-line>>", self.goto_file_line)
- self.text.unbind("<<toggle-code-context>>")
- self.update_menu_state('options', '*Code Context', 'disabled')
# Customize EditorWindow
def ispythonsource(self, filename):
+++ /dev/null
-"""Format a paragraph, comment block, or selection to a max width.
-
-Does basic, standard text formatting, and also understands Python
-comment blocks. Thus, for editing Python source code, this
-extension is really only suitable for reformatting these comment
-blocks or triple-quoted strings.
-
-Known problems with comment reformatting:
-* If there is a selection marked, and the first line of the
- selection is not complete, the block will probably not be detected
- as comments, and will have the normal "text formatting" rules
- applied.
-* If a comment block has leading whitespace that mixes tabs and
- spaces, they will not be considered part of the same block.
-* Fancy comments, like this bulleted list, aren't handled :-)
-"""
-import re
-
-from idlelib.config import idleConf
-
-
-class FormatParagraph:
-
- def __init__(self, editwin):
- self.editwin = editwin
-
- @classmethod
- def reload(cls):
- cls.max_width = idleConf.GetOption('extensions', 'FormatParagraph',
- 'max-width', type='int', default=72)
-
- def close(self):
- self.editwin = None
-
- def format_paragraph_event(self, event, limit=None):
- """Formats paragraph to a max width specified in idleConf.
-
- If text is selected, format_paragraph_event will start breaking lines
- at the max width, starting from the beginning selection.
-
- If no text is selected, format_paragraph_event uses the current
- cursor location to determine the paragraph (lines of text surrounded
- by blank lines) and formats it.
-
- The length limit parameter is for testing with a known value.
- """
- limit = self.max_width if limit is None else limit
- text = self.editwin.text
- first, last = self.editwin.get_selection_indices()
- if first and last:
- data = text.get(first, last)
- comment_header = get_comment_header(data)
- else:
- first, last, comment_header, data = \
- find_paragraph(text, text.index("insert"))
- if comment_header:
- newdata = reformat_comment(data, limit, comment_header)
- else:
- newdata = reformat_paragraph(data, limit)
- text.tag_remove("sel", "1.0", "end")
-
- if newdata != data:
- text.mark_set("insert", first)
- text.undo_block_start()
- text.delete(first, last)
- text.insert(first, newdata)
- text.undo_block_stop()
- else:
- text.mark_set("insert", last)
- text.see("insert")
- return "break"
-
-
-FormatParagraph.reload()
-
-def find_paragraph(text, mark):
- """Returns the start/stop indices enclosing the paragraph that mark is in.
-
- Also returns the comment format string, if any, and paragraph of text
- between the start/stop indices.
- """
- lineno, col = map(int, mark.split("."))
- line = text.get("%d.0" % lineno, "%d.end" % lineno)
-
- # Look for start of next paragraph if the index passed in is a blank line
- while text.compare("%d.0" % lineno, "<", "end") and is_all_white(line):
- lineno = lineno + 1
- line = text.get("%d.0" % lineno, "%d.end" % lineno)
- first_lineno = lineno
- comment_header = get_comment_header(line)
- comment_header_len = len(comment_header)
-
- # Once start line found, search for end of paragraph (a blank line)
- while get_comment_header(line)==comment_header and \
- not is_all_white(line[comment_header_len:]):
- lineno = lineno + 1
- line = text.get("%d.0" % lineno, "%d.end" % lineno)
- last = "%d.0" % lineno
-
- # Search back to beginning of paragraph (first blank line before)
- lineno = first_lineno - 1
- line = text.get("%d.0" % lineno, "%d.end" % lineno)
- while lineno > 0 and \
- get_comment_header(line)==comment_header and \
- not is_all_white(line[comment_header_len:]):
- lineno = lineno - 1
- line = text.get("%d.0" % lineno, "%d.end" % lineno)
- first = "%d.0" % (lineno+1)
-
- return first, last, comment_header, text.get(first, last)
-
-# This should perhaps be replaced with textwrap.wrap
-def reformat_paragraph(data, limit):
- """Return data reformatted to specified width (limit)."""
- lines = data.split("\n")
- i = 0
- n = len(lines)
- while i < n and is_all_white(lines[i]):
- i = i+1
- if i >= n:
- return data
- indent1 = get_indent(lines[i])
- if i+1 < n and not is_all_white(lines[i+1]):
- indent2 = get_indent(lines[i+1])
- else:
- indent2 = indent1
- new = lines[:i]
- partial = indent1
- while i < n and not is_all_white(lines[i]):
- # XXX Should take double space after period (etc.) into account
- words = re.split(r"(\s+)", lines[i])
- for j in range(0, len(words), 2):
- word = words[j]
- if not word:
- continue # Can happen when line ends in whitespace
- if len((partial + word).expandtabs()) > limit and \
- partial != indent1:
- new.append(partial.rstrip())
- partial = indent2
- partial = partial + word + " "
- if j+1 < len(words) and words[j+1] != " ":
- partial = partial + " "
- i = i+1
- new.append(partial.rstrip())
- # XXX Should reformat remaining paragraphs as well
- new.extend(lines[i:])
- return "\n".join(new)
-
-def reformat_comment(data, limit, comment_header):
- """Return data reformatted to specified width with comment header."""
-
- # Remove header from the comment lines
- lc = len(comment_header)
- data = "\n".join(line[lc:] for line in data.split("\n"))
- # Reformat to maxformatwidth chars or a 20 char width,
- # whichever is greater.
- format_width = max(limit - len(comment_header), 20)
- newdata = reformat_paragraph(data, format_width)
- # re-split and re-insert the comment header.
- newdata = newdata.split("\n")
- # If the block ends in a \n, we don't want the comment prefix
- # inserted after it. (Im not sure it makes sense to reformat a
- # comment block that is not made of complete lines, but whatever!)
- # Can't think of a clean solution, so we hack away
- block_suffix = ""
- if not newdata[-1]:
- block_suffix = "\n"
- newdata = newdata[:-1]
- return '\n'.join(comment_header+line for line in newdata) + block_suffix
-
-def is_all_white(line):
- """Return True if line is empty or all whitespace."""
-
- return re.match(r"^\s*$", line) is not None
-
-def get_indent(line):
- """Return the initial space or tab indent of line."""
- return re.match(r"^([ \t]*)", line).group()
-
-def get_comment_header(line):
- """Return string with leading whitespace and '#' from line or ''.
-
- A null return indicates that the line is not a comment line. A non-
- null return, such as ' #', will be used to find the other lines of
- a comment block with the same indent.
- """
- m = re.match(r"^([ \t]*#*)", line)
- if m is None: return ""
- return m.group(1)
-
-
-if __name__ == "__main__":
- from unittest import main
- main('idlelib.idle_test.test_paragraph', verbosity=2, exit=False)
return code[i:j]
def is_block_opener(self):
- "Return True if the last interesting statemtent opens a block."
+ "Return True if the last interesting statement opens a block."
self._study2()
return self.lastch == ':'
self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
self.text.bind("<<open-python-shell>>", self.flist.open_shell)
+ #TODO: don't read/write this from/to .idlerc when testing
self.breakpointPath = os.path.join(
idleConf.userdir, 'breakpoints.lst')
# whenever a file is changed, restore breakpoints
"Override the base class - just re-raise EOFError"
raise EOFError
+def restart_line(width, filename): # See bpo-38141.
+ """Return width long restart line formatted with filename.
+
+ Fill line with balanced '='s, with any extras and at least one at
+ the beginning. Do not end with a trailing space.
+ """
+ tag = f"= RESTART: {filename or 'Shell'} ="
+ if width >= len(tag):
+ div, mod = divmod((width -len(tag)), 2)
+ return f"{(div+mod)*'='}{tag}{div*'='}"
+ else:
+ return tag[:-2] # Remove ' ='.
+
class ModifiedInterpreter(InteractiveInterpreter):
self.tkconsole = tkconsole
locals = sys.modules['__main__'].__dict__
InteractiveInterpreter.__init__(self, locals=locals)
- self.save_warnings_filters = None
self.restarting = False
self.subprocess_arglist = None
self.port = PORT
console.stop_readline()
# annotate restart in shell window and mark it
console.text.delete("iomark", "end-1c")
- tag = 'RESTART: ' + (filename if filename else 'Shell')
- halfbar = ((int(console.width) -len(tag) - 4) // 2) * '='
- console.write("\n{0} {1} {0}".format(halfbar, tag))
+ console.write('\n')
+ console.write(restart_line(console.width, filename))
console.text.mark_set("restart", "end-1c")
console.text.mark_gravity("restart", "left")
if not filename:
"Extend base class method: Stuff the source in the line cache first"
filename = self.stuffsource(source)
self.more = 0
- self.save_warnings_filters = warnings.filters[:]
- warnings.filterwarnings(action="error", category=SyntaxWarning)
# at the moment, InteractiveInterpreter expects str
assert isinstance(source, str)
#if isinstance(source, str):
# self.tkconsole.resetoutput()
# self.write("Unsupported characters in input\n")
# return
- try:
- # InteractiveInterpreter.runsource() calls its runcode() method,
- # which is overridden (see below)
- return InteractiveInterpreter.runsource(self, source, filename)
- finally:
- if self.save_warnings_filters is not None:
- warnings.filters[:] = self.save_warnings_filters
- self.save_warnings_filters = None
+ # InteractiveInterpreter.runsource() calls its runcode() method,
+ # which is overridden (see below)
+ return InteractiveInterpreter.runsource(self, source, filename)
def stuffsource(self, source):
"Stuff source in the filename cache"
if self.tkconsole.executing:
self.interp.restart_subprocess()
self.checklinecache()
- if self.save_warnings_filters is not None:
- warnings.filters[:] = self.save_warnings_filters
- self.save_warnings_filters = None
debugger = self.debugger
try:
self.tkconsole.beginexecuting()
("Squeeze", "<<squeeze-current-text>>"),
]
+ allow_line_numbers = False
+
# New classes
from idlelib.history import History
"""
def __init__(self, parent, title, message, *, text0='', used_names={},
_htest=False, _utest=False):
- """Create popup, do not return until tk widget destroyed.
+ """Create modal popup, return when destroyed.
- Additional subclass init must be done before calling this
- unless _utest=True is passed to suppress wait_window().
+ Additional subclass init must be done before this unless
+ _utest=True is passed to suppress wait_window().
title - string, title of popup dialog
message - string, informational message to display
_htest - bool, change box location when running htest
_utest - bool, leave window hidden and not modal
"""
- Toplevel.__init__(self, parent)
- self.withdraw() # Hide while configuring, especially geometry.
- self.parent = parent
- self.title(title)
+ self.parent = parent # Needed for Font call.
self.message = message
self.text0 = text0
self.used_names = used_names
+
+ Toplevel.__init__(self, parent)
+ self.withdraw() # Hide while configuring, especially geometry.
+ self.title(title)
self.transient(parent)
self.grab_set()
+
windowingsystem = self.tk.call('tk', 'windowingsystem')
if windowingsystem == 'aqua':
try:
self.protocol("WM_DELETE_WINDOW", self.cancel)
self.bind('<Key-Return>', self.ok)
self.bind("<KP_Enter>", self.ok)
- self.resizable(height=False, width=False)
+
self.create_widgets()
- self.update_idletasks() # Needed here for winfo_reqwidth below.
+ self.update_idletasks() # Need here for winfo_reqwidth below.
self.geometry( # Center dialog over parent (or below htest box).
"+%d+%d" % (
parent.winfo_rootx() +
((parent.winfo_height()/2 - self.winfo_reqheight()/2)
if not _htest else 150)
) )
+ self.resizable(height=False, width=False)
+
if not _utest:
self.deiconify() # Unhide now that geometry set.
self.wait_window()
- def create_widgets(self, ok_text='OK'): # Call from override, if any.
- # Bind to self widgets needed for entry_ok or unittest.
+ def create_widgets(self, ok_text='OK'): # Do not replace.
+ """Create entry (rows, extras, buttons.
+
+ Entry stuff on rows 0-2, spanning cols 0-2.
+ Buttons on row 99, cols 1, 2.
+ """
+ # Bind to self the widgets needed for entry_ok or unittest.
self.frame = frame = Frame(self, padding=10)
frame.grid(column=0, row=0, sticky='news')
frame.grid_columnconfigure(0, weight=1)
exists=True, root=self.parent)
self.entry_error = Label(frame, text=' ', foreground='red',
font=self.error_font)
- self.button_ok = Button(
- frame, text=ok_text, default='active', command=self.ok)
- self.button_cancel = Button(
- frame, text='Cancel', command=self.cancel)
-
entrylabel.grid(column=0, row=0, columnspan=3, padx=5, sticky=W)
self.entry.grid(column=0, row=1, columnspan=3, padx=5, sticky=W+E,
pady=[10,0])
self.entry_error.grid(column=0, row=2, columnspan=3, padx=5,
sticky=W+E)
+
+ self.create_extra()
+
+ self.button_ok = Button(
+ frame, text=ok_text, default='active', command=self.ok)
+ self.button_cancel = Button(
+ frame, text='Cancel', command=self.cancel)
+
self.button_ok.grid(column=1, row=99, padx=5)
self.button_cancel.grid(column=2, row=99, padx=5)
+ def create_extra(self): pass # Override to add widgets.
+
def showerror(self, message, widget=None):
#self.bell(displayof=self)
(widget or self.entry_error)['text'] = 'ERROR: ' + message
parent, title, message, text0=menuitem,
used_names=used_names, _htest=_htest, _utest=_utest)
- def create_widgets(self):
- super().create_widgets()
+ def create_extra(self):
+ "Add path widjets to rows 10-12."
frame = self.frame
pathlabel = Label(frame, anchor='w', justify='left',
text='Help File Path: Enter URL or browse for file')
"""
# Used in runscript.run_custom_event
- def __init__(self, parent, title, *, cli_args='',
+ def __init__(self, parent, title, *, cli_args=[],
_htest=False, _utest=False):
- # TODO Use cli_args to pre-populate entry.
+ """cli_args is a list of strings.
+
+ The list is assigned to the default Entry StringVar.
+ The strings are displayed joined by ' ' for display.
+ """
message = 'Command Line Arguments for sys.argv:'
super().__init__(
parent, title, message, text0=cli_args,
_htest=_htest, _utest=_utest)
- def create_widgets(self):
- super().create_widgets(ok_text='Run')
+ def create_extra(self):
+ "Add run mode on rows 10-12."
frame = self.frame
self.restartvar = BooleanVar(self, value=True)
restart = Checkbutton(frame, variable=self.restartvar, onvalue=True,
self.args_error = Label(frame, text=' ', foreground='red',
font=self.error_font)
- restart.grid(column=0, row=4, columnspan=3, padx=5, sticky='w')
+ restart.grid(column=0, row=10, columnspan=3, padx=5, sticky='w')
self.args_error.grid(column=0, row=12, columnspan=3, padx=5,
sticky='we')
+++ /dev/null
-'Provides "Strip trailing whitespace" under the "Format" menu.'
-
-class Rstrip:
-
- def __init__(self, editwin):
- self.editwin = editwin
-
- def do_rstrip(self, event=None):
-
- text = self.editwin.text
- undo = self.editwin.undo
-
- undo.undo_block_start()
-
- end_line = int(float(text.index('end')))
- for cur in range(1, end_line):
- txt = text.get('%i.0' % cur, '%i.end' % cur)
- raw = len(txt)
- cut = len(txt.rstrip())
- # Since text.delete() marks file as changed, even if not,
- # only call it when needed to actually delete something.
- if cut < raw:
- text.delete('%i.%i' % (cur, cut), '%i.end' % cur)
-
- undo.undo_block_stop()
-
-if __name__ == "__main__":
- from unittest import main
- main('idlelib.idle_test.test_rstrip', verbosity=2,)
f'''{sys.executable} -c "__import__('idlelib.run').run.main()"'''
'.run' is needed because __import__ returns idlelib, not idlelib.run.
"""
+import functools
import io
import linecache
import queue
import sys
+import textwrap
import time
import traceback
import _thread as thread
font['size'] = round(-0.75*size)
+def fixdoc(fun, text):
+ tem = (fun.__doc__ + '\n\n') if fun.__doc__ is not None else ''
+ fun.__doc__ = tem + textwrap.fill(textwrap.dedent(text))
+
+RECURSIONLIMIT_DELTA = 30
+
+def install_recursionlimit_wrappers():
+ """Install wrappers to always add 30 to the recursion limit."""
+ # see: bpo-26806
+
+ @functools.wraps(sys.setrecursionlimit)
+ def setrecursionlimit(*args, **kwargs):
+ # mimic the original sys.setrecursionlimit()'s input handling
+ if kwargs:
+ raise TypeError(
+ "setrecursionlimit() takes no keyword arguments")
+ try:
+ limit, = args
+ except ValueError:
+ raise TypeError(f"setrecursionlimit() takes exactly one "
+ f"argument ({len(args)} given)")
+ if not limit > 0:
+ raise ValueError(
+ "recursion limit must be greater or equal than 1")
+
+ return setrecursionlimit.__wrapped__(limit + RECURSIONLIMIT_DELTA)
+
+ fixdoc(setrecursionlimit, f"""\
+ This IDLE wrapper adds {RECURSIONLIMIT_DELTA} to prevent possible
+ uninterruptible loops.""")
+
+ @functools.wraps(sys.getrecursionlimit)
+ def getrecursionlimit():
+ return getrecursionlimit.__wrapped__() - RECURSIONLIMIT_DELTA
+
+ fixdoc(getrecursionlimit, f"""\
+ This IDLE wrapper subtracts {RECURSIONLIMIT_DELTA} to compensate
+ for the {RECURSIONLIMIT_DELTA} IDLE adds when setting the limit.""")
+
+ # add the delta to the default recursion limit, to compensate
+ sys.setrecursionlimit(sys.getrecursionlimit() + RECURSIONLIMIT_DELTA)
+
+ sys.setrecursionlimit = setrecursionlimit
+ sys.getrecursionlimit = getrecursionlimit
+
+
+def uninstall_recursionlimit_wrappers():
+ """Uninstall the recursion limit wrappers from the sys module.
+
+ IDLE only uses this for tests. Users can import run and call
+ this to remove the wrapping.
+ """
+ if (
+ getattr(sys.setrecursionlimit, '__wrapped__', None) and
+ getattr(sys.getrecursionlimit, '__wrapped__', None)
+ ):
+ sys.setrecursionlimit = sys.setrecursionlimit.__wrapped__
+ sys.getrecursionlimit = sys.getrecursionlimit.__wrapped__
+ sys.setrecursionlimit(sys.getrecursionlimit() - RECURSIONLIMIT_DELTA)
+
+
class MyRPCServer(rpc.RPCServer):
def handle_error(self, request, client_address):
# sys.stdin gets changed from within IDLE's shell. See issue17838.
self._keep_stdin = sys.stdin
+ install_recursionlimit_wrappers()
+
self.interp = self.get_remote_proxy("interp")
rpc.RPCHandler.getresponse(self, myseq=None, wait=0.05)
# XXX This should be done differently
self.flist = self.editwin.flist
self.root = self.editwin.root
+ # cli_args is list of strings that extends sys.argv
+ self.cli_args = []
if macosx.isCocoaTk():
self.editwin.text_frame.bind('<<run-module-event-2>>', self._run_module_event)
return 'break'
if customize:
title = f"Customize {self.editwin.short_title()} Run"
- run_args = CustomRun(self.shell.text, title).result
+ run_args = CustomRun(self.shell.text, title,
+ cli_args=self.cli_args).result
if not run_args: # User cancelled.
return 'break'
- cli_args, restart = run_args if customize else ([], True)
+ self.cli_args, restart = run_args if customize else ([], True)
interp = self.shell.interp
if pyshell.use_subprocess and restart:
interp.restart_subprocess(
self.editwin._filename_to_unicode(filename))
dirname = os.path.dirname(filename)
argv = [filename]
- if cli_args:
- argv += cli_args
+ if self.cli_args:
+ argv += self.cli_args
interp.runcommand(f"""if 1:
__file__ = {filename!r}
import sys as _sys
_sys.argv = argv
import os as _os
_os.chdir({dirname!r})
- del _sys, _basename, _os
+ del _sys, argv, _basename, _os
\n""")
interp.prepend_syspath(filename)
# XXX KBK 03Jul04 When run w/o subprocess, runtime warnings still
--- /dev/null
+"""Line numbering implementation for IDLE as an extension.
+Includes BaseSideBar which can be extended for other sidebar based extensions
+"""
+import functools
+import itertools
+
+import tkinter as tk
+from idlelib.config import idleConf
+from idlelib.delegator import Delegator
+
+
+def get_end_linenumber(text):
+ """Utility to get the last line's number in a Tk text widget."""
+ return int(float(text.index('end-1c')))
+
+
+def get_widget_padding(widget):
+ """Get the total padding of a Tk widget, including its border."""
+ # TODO: use also in codecontext.py
+ manager = widget.winfo_manager()
+ if manager == 'pack':
+ info = widget.pack_info()
+ elif manager == 'grid':
+ info = widget.grid_info()
+ else:
+ raise ValueError(f"Unsupported geometry manager: {manager}")
+
+ # All values are passed through getint(), since some
+ # values may be pixel objects, which can't simply be added to ints.
+ padx = sum(map(widget.tk.getint, [
+ info['padx'],
+ widget.cget('padx'),
+ widget.cget('border'),
+ ]))
+ pady = sum(map(widget.tk.getint, [
+ info['pady'],
+ widget.cget('pady'),
+ widget.cget('border'),
+ ]))
+ return padx, pady
+
+
+class BaseSideBar:
+ """
+ The base class for extensions which require a sidebar.
+ """
+ def __init__(self, editwin):
+ self.editwin = editwin
+ self.parent = editwin.text_frame
+ self.text = editwin.text
+
+ _padx, pady = get_widget_padding(self.text)
+ self.sidebar_text = tk.Text(self.parent, width=1, wrap=tk.NONE,
+ padx=2, pady=pady,
+ borderwidth=0, highlightthickness=0)
+ self.sidebar_text.config(state=tk.DISABLED)
+ self.text['yscrollcommand'] = self.redirect_yscroll_event
+ self.update_font()
+ self.update_colors()
+
+ self.is_shown = False
+
+ def update_font(self):
+ """Update the sidebar text font, usually after config changes."""
+ font = idleConf.GetFont(self.text, 'main', 'EditorWindow')
+ self._update_font(font)
+
+ def _update_font(self, font):
+ self.sidebar_text['font'] = font
+
+ def update_colors(self):
+ """Update the sidebar text colors, usually after config changes."""
+ colors = idleConf.GetHighlight(idleConf.CurrentTheme(), 'normal')
+ self._update_colors(foreground=colors['foreground'],
+ background=colors['background'])
+
+ def _update_colors(self, foreground, background):
+ self.sidebar_text.config(
+ fg=foreground, bg=background,
+ selectforeground=foreground, selectbackground=background,
+ inactiveselectbackground=background,
+ )
+
+ def show_sidebar(self):
+ if not self.is_shown:
+ self.sidebar_text.grid(row=1, column=0, sticky=tk.NSEW)
+ self.is_shown = True
+
+ def hide_sidebar(self):
+ if self.is_shown:
+ self.sidebar_text.grid_forget()
+ self.is_shown = False
+
+ def redirect_yscroll_event(self, *args, **kwargs):
+ """Redirect vertical scrolling to the main editor text widget.
+
+ The scroll bar is also updated.
+ """
+ self.editwin.vbar.set(*args)
+ self.sidebar_text.yview_moveto(args[0])
+ return 'break'
+
+ def redirect_focusin_event(self, event):
+ """Redirect focus-in events to the main editor text widget."""
+ self.text.focus_set()
+ return 'break'
+
+ def redirect_mousebutton_event(self, event, event_name):
+ """Redirect mouse button events to the main editor text widget."""
+ self.text.focus_set()
+ self.text.event_generate(event_name, x=0, y=event.y)
+ return 'break'
+
+ def redirect_mousewheel_event(self, event):
+ """Redirect mouse wheel events to the editwin text widget."""
+ self.text.event_generate('<MouseWheel>',
+ x=0, y=event.y, delta=event.delta)
+ return 'break'
+
+
+class EndLineDelegator(Delegator):
+ """Generate callbacks with the current end line number after
+ insert or delete operations"""
+ def __init__(self, changed_callback):
+ """
+ changed_callback - Callable, will be called after insert
+ or delete operations with the current
+ end line number.
+ """
+ Delegator.__init__(self)
+ self.changed_callback = changed_callback
+
+ def insert(self, index, chars, tags=None):
+ self.delegate.insert(index, chars, tags)
+ self.changed_callback(get_end_linenumber(self.delegate))
+
+ def delete(self, index1, index2=None):
+ self.delegate.delete(index1, index2)
+ self.changed_callback(get_end_linenumber(self.delegate))
+
+
+class LineNumbers(BaseSideBar):
+ """Line numbers support for editor windows."""
+ def __init__(self, editwin):
+ BaseSideBar.__init__(self, editwin)
+ self.prev_end = 1
+ self._sidebar_width_type = type(self.sidebar_text['width'])
+ self.sidebar_text.config(state=tk.NORMAL)
+ self.sidebar_text.insert('insert', '1', 'linenumber')
+ self.sidebar_text.config(state=tk.DISABLED)
+ self.sidebar_text.config(takefocus=False, exportselection=False)
+ self.sidebar_text.tag_config('linenumber', justify=tk.RIGHT)
+
+ self.bind_events()
+
+ end = get_end_linenumber(self.text)
+ self.update_sidebar_text(end)
+
+ end_line_delegator = EndLineDelegator(self.update_sidebar_text)
+ # Insert the delegator after the undo delegator, so that line numbers
+ # are properly updated after undo and redo actions.
+ end_line_delegator.setdelegate(self.editwin.undo.delegate)
+ self.editwin.undo.setdelegate(end_line_delegator)
+ # Reset the delegator caches of the delegators "above" the
+ # end line delegator we just inserted.
+ delegator = self.editwin.per.top
+ while delegator is not end_line_delegator:
+ delegator.resetcache()
+ delegator = delegator.delegate
+
+ self.is_shown = False
+
+ def bind_events(self):
+ # Ensure focus is always redirected to the main editor text widget.
+ self.sidebar_text.bind('<FocusIn>', self.redirect_focusin_event)
+
+ # Redirect mouse scrolling to the main editor text widget.
+ #
+ # Note that without this, scrolling with the mouse only scrolls
+ # the line numbers.
+ self.sidebar_text.bind('<MouseWheel>', self.redirect_mousewheel_event)
+
+ # Redirect mouse button events to the main editor text widget,
+ # except for the left mouse button (1).
+ #
+ # Note: X-11 sends Button-4 and Button-5 events for the scroll wheel.
+ def bind_mouse_event(event_name, target_event_name):
+ handler = functools.partial(self.redirect_mousebutton_event,
+ event_name=target_event_name)
+ self.sidebar_text.bind(event_name, handler)
+
+ for button in [2, 3, 4, 5]:
+ for event_name in (f'<Button-{button}>',
+ f'<ButtonRelease-{button}>',
+ f'<B{button}-Motion>',
+ ):
+ bind_mouse_event(event_name, target_event_name=event_name)
+
+ # Convert double- and triple-click events to normal click events,
+ # since event_generate() doesn't allow generating such events.
+ for event_name in (f'<Double-Button-{button}>',
+ f'<Triple-Button-{button}>',
+ ):
+ bind_mouse_event(event_name,
+ target_event_name=f'<Button-{button}>')
+
+ # This is set by b1_mousedown_handler() and read by
+ # drag_update_selection_and_insert_mark(), to know where dragging
+ # began.
+ start_line = None
+ # These are set by b1_motion_handler() and read by selection_handler().
+ # last_y is passed this way since the mouse Y-coordinate is not
+ # available on selection event objects. last_yview is passed this way
+ # to recognize scrolling while the mouse isn't moving.
+ last_y = last_yview = None
+
+ def b1_mousedown_handler(event):
+ # select the entire line
+ lineno = int(float(self.sidebar_text.index(f"@0,{event.y}")))
+ self.text.tag_remove("sel", "1.0", "end")
+ self.text.tag_add("sel", f"{lineno}.0", f"{lineno+1}.0")
+ self.text.mark_set("insert", f"{lineno+1}.0")
+
+ # remember this line in case this is the beginning of dragging
+ nonlocal start_line
+ start_line = lineno
+ self.sidebar_text.bind('<Button-1>', b1_mousedown_handler)
+
+ def b1_mouseup_handler(event):
+ # On mouse up, we're no longer dragging. Set the shared persistent
+ # variables to None to represent this.
+ nonlocal start_line
+ nonlocal last_y
+ nonlocal last_yview
+ start_line = None
+ last_y = None
+ last_yview = None
+ self.sidebar_text.bind('<ButtonRelease-1>', b1_mouseup_handler)
+
+ def drag_update_selection_and_insert_mark(y_coord):
+ """Helper function for drag and selection event handlers."""
+ lineno = int(float(self.sidebar_text.index(f"@0,{y_coord}")))
+ a, b = sorted([start_line, lineno])
+ self.text.tag_remove("sel", "1.0", "end")
+ self.text.tag_add("sel", f"{a}.0", f"{b+1}.0")
+ self.text.mark_set("insert",
+ f"{lineno if lineno == a else lineno + 1}.0")
+
+ # Special handling of dragging with mouse button 1. In "normal" text
+ # widgets this selects text, but the line numbers text widget has
+ # selection disabled. Still, dragging triggers some selection-related
+ # functionality under the hood. Specifically, dragging to above or
+ # below the text widget triggers scrolling, in a way that bypasses the
+ # other scrolling synchronization mechanisms.i
+ def b1_drag_handler(event, *args):
+ nonlocal last_y
+ nonlocal last_yview
+ last_y = event.y
+ last_yview = self.sidebar_text.yview()
+ if not 0 <= last_y <= self.sidebar_text.winfo_height():
+ self.text.yview_moveto(last_yview[0])
+ drag_update_selection_and_insert_mark(event.y)
+ self.sidebar_text.bind('<B1-Motion>', b1_drag_handler)
+
+ # With mouse-drag scrolling fixed by the above, there is still an edge-
+ # case we need to handle: When drag-scrolling, scrolling can continue
+ # while the mouse isn't moving, leading to the above fix not scrolling
+ # properly.
+ def selection_handler(event):
+ if last_yview is None:
+ # This logic is only needed while dragging.
+ return
+ yview = self.sidebar_text.yview()
+ if yview != last_yview:
+ self.text.yview_moveto(yview[0])
+ drag_update_selection_and_insert_mark(last_y)
+ self.sidebar_text.bind('<<Selection>>', selection_handler)
+
+ def update_colors(self):
+ """Update the sidebar text colors, usually after config changes."""
+ colors = idleConf.GetHighlight(idleConf.CurrentTheme(), 'linenumber')
+ self._update_colors(foreground=colors['foreground'],
+ background=colors['background'])
+
+ def update_sidebar_text(self, end):
+ """
+ Perform the following action:
+ Each line sidebar_text contains the linenumber for that line
+ Synchronize with editwin.text so that both sidebar_text and
+ editwin.text contain the same number of lines"""
+ if end == self.prev_end:
+ return
+
+ width_difference = len(str(end)) - len(str(self.prev_end))
+ if width_difference:
+ cur_width = int(float(self.sidebar_text['width']))
+ new_width = cur_width + width_difference
+ self.sidebar_text['width'] = self._sidebar_width_type(new_width)
+
+ self.sidebar_text.config(state=tk.NORMAL)
+ if end > self.prev_end:
+ new_text = '\n'.join(itertools.chain(
+ [''],
+ map(str, range(self.prev_end + 1, end + 1)),
+ ))
+ self.sidebar_text.insert(f'end -1c', new_text, 'linenumber')
+ else:
+ self.sidebar_text.delete(f'{end+1}.0 -1c', 'end -1c')
+ self.sidebar_text.config(state=tk.DISABLED)
+
+ self.prev_end = end
+
+
+def _linenumbers_drag_scrolling(parent): # htest #
+ from idlelib.idle_test.test_sidebar import Dummy_editwin
+
+ toplevel = tk.Toplevel(parent)
+ text_frame = tk.Frame(toplevel)
+ text_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
+ text_frame.rowconfigure(1, weight=1)
+ text_frame.columnconfigure(1, weight=1)
+
+ font = idleConf.GetFont(toplevel, 'main', 'EditorWindow')
+ text = tk.Text(text_frame, width=80, height=24, wrap=tk.NONE, font=font)
+ text.grid(row=1, column=1, sticky=tk.NSEW)
+
+ editwin = Dummy_editwin(text)
+ editwin.vbar = tk.Scrollbar(text_frame)
+
+ linenumbers = LineNumbers(editwin)
+ linenumbers.show_sidebar()
+
+ text.insert('1.0', '\n'.join('a'*i for i in range(1, 101)))
+
+
+if __name__ == '__main__':
+ from unittest import main
+ main('idlelib.idle_test.test_sidebar', verbosity=2, exit=False)
+
+ from idlelib.idle_test.htest import run
+ run(_linenumbers_drag_scrolling)
messages and their tracebacks.
"""
import re
-import weakref
import tkinter as tk
-from tkinter.font import Font
import tkinter.messagebox as tkMessageBox
from idlelib.config import idleConf
This avoids IDLE's shell slowing down considerably, and even becoming
completely unresponsive, when very long outputs are written.
"""
- _instance_weakref = None
-
@classmethod
def reload(cls):
"""Load class variables from config."""
type="int", default=50,
)
- # Loading the font info requires a Tk root. IDLE doesn't rely
- # on Tkinter's "default root", so the instance will reload
- # font info using its editor windows's Tk root.
- if cls._instance_weakref is not None:
- instance = cls._instance_weakref()
- if instance is not None:
- instance.load_font()
-
def __init__(self, editwin):
"""Initialize settings for Squeezer.
# however, needs to make such changes.
self.base_text = editwin.per.bottom
- Squeezer._instance_weakref = weakref.ref(self)
- self.load_font()
-
# Twice the text widget's border width and internal padding;
# pre-calculated here for the get_line_width() method.
self.window_width_delta = 2 * (
Tabs are considered tabwidth characters long.
"""
- linewidth = self.get_line_width()
- return count_lines_with_wrapping(s, linewidth)
-
- def get_line_width(self):
- # The maximum line length in pixels: The width of the text
- # widget, minus twice the border width and internal padding.
- linewidth_pixels = \
- self.base_text.winfo_width() - self.window_width_delta
-
- # Divide the width of the Text widget by the font width,
- # which is taken to be the width of '0' (zero).
- # http://www.tcl.tk/man/tcl8.6/TkCmd/text.htm#M21
- return linewidth_pixels // self.zero_char_width
-
- def load_font(self):
- text = self.base_text
- self.zero_char_width = \
- Font(text, font=text.cget('font')).measure('0')
+ return count_lines_with_wrapping(s, self.editwin.width)
def squeeze_current_text_event(self, event):
"""squeeze-current-text event handler
"""
from tkinter import Toplevel, Text, TclError,\
- HORIZONTAL, VERTICAL, N, S, E, W
+ HORIZONTAL, VERTICAL, NS, EW, NSEW, NONE, WORD, SUNKEN
from tkinter.ttk import Frame, Scrollbar, Button
from tkinter.messagebox import showerror
+from functools import update_wrapper
from idlelib.colorizer import color_config
-class AutoHiddenScrollbar(Scrollbar):
+class AutoHideScrollbar(Scrollbar):
"""A scrollbar that is automatically hidden when not needed.
Only the grid geometry manager is supported.
raise TclError(f'{self.__class__.__name__} does not support "place"')
-class TextFrame(Frame):
- "Display text with scrollbar."
+class ScrollableTextFrame(Frame):
+ """Display text with scrollbar(s)."""
- def __init__(self, parent, rawtext, wrap='word'):
+ def __init__(self, master, wrap=NONE, **kwargs):
"""Create a frame for Textview.
- parent - parent widget for this frame
- rawtext - text to display
+ master - master widget for this frame
+ wrap - type of text wrapping to use ('word', 'char' or 'none')
+
+ All parameters except for 'wrap' are passed to Frame.__init__().
+
+ The Text widget is accessible via the 'text' attribute.
+
+ Note: Changing the wrapping mode of the text widget after
+ instantiation is not supported.
"""
- super().__init__(parent)
- self['relief'] = 'sunken'
- self['height'] = 700
+ super().__init__(master, **kwargs)
- self.text = text = Text(self, wrap=wrap, highlightthickness=0)
- color_config(text)
- text.grid(row=0, column=0, sticky=N+S+E+W)
+ text = self.text = Text(self, wrap=wrap)
+ text.grid(row=0, column=0, sticky=NSEW)
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
- text.insert(0.0, rawtext)
- text['state'] = 'disabled'
- text.focus_set()
# vertical scrollbar
- self.yscroll = yscroll = AutoHiddenScrollbar(self, orient=VERTICAL,
- takefocus=False,
- command=text.yview)
- text['yscrollcommand'] = yscroll.set
- yscroll.grid(row=0, column=1, sticky=N+S)
-
- if wrap == 'none':
- # horizontal scrollbar
- self.xscroll = xscroll = AutoHiddenScrollbar(self, orient=HORIZONTAL,
- takefocus=False,
- command=text.xview)
- text['xscrollcommand'] = xscroll.set
- xscroll.grid(row=1, column=0, sticky=E+W)
+ self.yscroll = AutoHideScrollbar(self, orient=VERTICAL,
+ takefocus=False,
+ command=text.yview)
+ self.yscroll.grid(row=0, column=1, sticky=NS)
+ text['yscrollcommand'] = self.yscroll.set
+
+ # horizontal scrollbar - only when wrap is set to NONE
+ if wrap == NONE:
+ self.xscroll = AutoHideScrollbar(self, orient=HORIZONTAL,
+ takefocus=False,
+ command=text.xview)
+ self.xscroll.grid(row=1, column=0, sticky=EW)
+ text['xscrollcommand'] = self.xscroll.set
+ else:
+ self.xscroll = None
class ViewFrame(Frame):
"Display TextFrame and Close button."
- def __init__(self, parent, text, wrap='word'):
+ def __init__(self, parent, contents, wrap='word'):
+ """Create a frame for viewing text with a "Close" button.
+
+ parent - parent widget for this frame
+ contents - text to display
+ wrap - type of text wrapping to use ('word', 'char' or 'none')
+
+ The Text widget is accessible via the 'text' attribute.
+ """
super().__init__(parent)
self.parent = parent
self.bind('<Return>', self.ok)
self.bind('<Escape>', self.ok)
- self.textframe = TextFrame(self, text, wrap=wrap)
+ self.textframe = ScrollableTextFrame(self, relief=SUNKEN, height=700)
+
+ text = self.text = self.textframe.text
+ text.insert('1.0', contents)
+ text.configure(wrap=wrap, highlightthickness=0, state='disabled')
+ color_config(text)
+ text.focus_set()
+
self.button_ok = button_ok = Button(
self, text='Close', command=self.ok, takefocus=False)
self.textframe.pack(side='top', expand=True, fill='both')
class ViewWindow(Toplevel):
"A simple text viewer dialog for IDLE."
- def __init__(self, parent, title, text, modal=True, wrap='word',
+ def __init__(self, parent, title, contents, modal=True, wrap=WORD,
*, _htest=False, _utest=False):
"""Show the given text in a scrollable window with a 'close' button.
parent - parent of this dialog
title - string which is title of popup dialog
- text - text to display in dialog
+ contents - text to display in dialog
wrap - type of text wrapping to use ('word', 'char' or 'none')
_htest - bool; change box location when running htest.
_utest - bool; don't wait_window when running unittest.
self.geometry(f'=750x500+{x}+{y}')
self.title(title)
- self.viewframe = ViewFrame(self, text, wrap=wrap)
+ self.viewframe = ViewFrame(self, contents, wrap=wrap)
self.protocol("WM_DELETE_WINDOW", self.ok)
self.button_ok = button_ok = Button(self, text='Close',
command=self.ok, takefocus=False)
self.destroy()
-def view_text(parent, title, text, modal=True, wrap='word', _utest=False):
+def view_text(parent, title, contents, modal=True, wrap='word', _utest=False):
"""Create text viewer for given text.
parent - parent of this dialog
title - string which is the title of popup dialog
- text - text to display in this dialog
+ contents - text to display in this dialog
wrap - type of text wrapping to use ('word', 'char' or 'none')
modal - controls if users can interact with other windows while this
dialog is displayed
_utest - bool; controls wait_window on unittest
"""
- return ViewWindow(parent, title, text, modal, wrap=wrap, _utest=_utest)
+ return ViewWindow(parent, title, contents, modal, wrap=wrap, _utest=_utest)
def view_file(parent, title, filename, encoding, modal=True, wrap='word',
if tw:
try:
tw.destroy()
- except TclError:
+ except TclError: # pragma: no cover
pass
def __del__(self):
try:
self.anchor_widget.unbind("<Enter>", self._id1)
- self.anchor_widget.unbind("<Leave>", self._id2)
- self.anchor_widget.unbind("<Button>", self._id3)
+ self.anchor_widget.unbind("<Leave>", self._id2) # pragma: no cover
+ self.anchor_widget.unbind("<Button>", self._id3) # pragma: no cover
except TclError:
pass
super(OnHoverTooltipBase, self).__del__()
"""hide the tooltip"""
try:
self.unschedule()
- except TclError:
+ except TclError: # pragma: no cover
pass
super(OnHoverTooltipBase, self).hidetip()
column = 0
root.images = images
+def wheel_event(event, widget=None):
+ """Handle scrollwheel event.
+
+ For wheel up, event.delta = 120*n on Windows, -1*n on darwin,
+ where n can be > 1 if one scrolls fast. Flicking the wheel
+ generates up to maybe 20 events with n up to 10 or more 1.
+ Macs use wheel down (delta = 1*n) to scroll up, so positive
+ delta means to scroll up on both systems.
+
+ X-11 sends Control-Button-4,5 events instead.
+
+ The widget parameter is needed so browser label bindings can pass
+ the underlying canvas.
+
+ This function depends on widget.yview to not be overridden by
+ a subclass.
+ """
+ up = {EventType.MouseWheel: event.delta > 0,
+ EventType.ButtonPress: event.num == 4}
+ lines = -5 if up[event.type] else 5
+ widget = event.widget if widget is None else widget
+ widget.yview(SCROLL, lines, 'units')
+ return 'break'
+
class TreeNode:
anchor="nw", window=self.label)
self.label.bind("<1>", self.select_or_edit)
self.label.bind("<Double-1>", self.flip)
+ self.label.bind("<MouseWheel>", lambda e: wheel_event(e, self.canvas))
+ self.label.bind("<Button-4>", lambda e: wheel_event(e, self.canvas))
+ self.label.bind("<Button-5>", lambda e: wheel_event(e, self.canvas))
self.text_id = id
def select_or_edit(self, event=None):
# A canvas widget with scroll bars and some useful bindings
class ScrolledCanvas:
+
def __init__(self, master, **opts):
if 'yscrollincrement' not in opts:
opts['yscrollincrement'] = 17
self.canvas.bind("<Key-Next>", self.page_down)
self.canvas.bind("<Key-Up>", self.unit_up)
self.canvas.bind("<Key-Down>", self.unit_down)
+ self.canvas.bind("<MouseWheel>", wheel_event)
+ self.canvas.bind("<Button-4>", wheel_event)
+ self.canvas.bind("<Button-5>", wheel_event)
#if isinstance(master, Toplevel) or isinstance(master, Tk):
self.canvas.bind("<Alt-Key-2>", self.zoom_height)
self.canvas.focus_set()
# Python 3.7a2 3391 (update GET_AITER #31709)
# Python 3.7a4 3392 (PEP 552: Deterministic pycs #31650)
# Python 3.7b1 3393 (remove STORE_ANNOTATION opcode #32550)
-# Python 3.7b5 3394 (restored docstring as the firts stmt in the body;
+# Python 3.7b5 3394 (restored docstring as the first stmt in the body;
# this might affected the first line number #32911)
#
# MAGIC must change whenever the bytecode emitted by the compiler may no
if (obj.__init__ is object.__init__ and
obj.__new__ is object.__new__):
# Return a signature of 'object' builtin.
- return signature(object)
+ return sigcls.from_callable(object)
else:
raise ValueError(
'no signature found for builtin type {!r}'.format(obj))
type(exc).__name__,
exc)
print(msg, file=sys.stderr)
- exit(2)
+ sys.exit(2)
if has_attrs:
parts = attrs.split(".")
if module.__name__ in sys.builtin_module_names:
print("Can't get info for builtin modules.", file=sys.stderr)
- exit(1)
+ sys.exit(1)
if args.details:
print('Target: {}'.format(target))
except ValueError:
cls._report_invalid_netmask(ip_str)
+ @classmethod
+ def _split_addr_prefix(cls, address):
+ """Helper function to parse address of Network/Interface.
+
+ Arg:
+ address: Argument of Network/Interface.
+
+ Returns:
+ (addr, prefix) tuple.
+ """
+ # a packed address or integer
+ if isinstance(address, (bytes, int)):
+ return address, cls._max_prefixlen
+
+ if not isinstance(address, tuple):
+ # Assume input argument to be string or any object representation
+ # which converts into a formatted IP prefix string.
+ address = _split_optional_netmask(address)
+
+ # Constructing from a tuple (addr, [mask])
+ if len(address) > 1:
+ return address
+ return address[0], cls._max_prefixlen
+
def __reduce__(self):
return self.__class__, (str(self),)
class IPv4Interface(IPv4Address):
def __init__(self, address):
- if isinstance(address, (bytes, int)):
- IPv4Address.__init__(self, address)
- self.network = IPv4Network(self._ip)
- self._prefixlen = self._max_prefixlen
- return
-
- if isinstance(address, tuple):
- IPv4Address.__init__(self, address[0])
- if len(address) > 1:
- self._prefixlen = int(address[1])
- else:
- self._prefixlen = self._max_prefixlen
-
- self.network = IPv4Network(address, strict=False)
- self.netmask = self.network.netmask
- self.hostmask = self.network.hostmask
- return
-
- addr = _split_optional_netmask(address)
- IPv4Address.__init__(self, addr[0])
-
- self.network = IPv4Network(address, strict=False)
- self._prefixlen = self.network._prefixlen
+ addr, mask = self._split_addr_prefix(address)
+ IPv4Address.__init__(self, addr)
+ self.network = IPv4Network((addr, mask), strict=False)
self.netmask = self.network.netmask
self.hostmask = self.network.hostmask
+ self._prefixlen = self.network._prefixlen
def __str__(self):
return '%s/%d' % (self._string_from_ip_int(self._ip),
an IPv4 address.
ValueError: If strict is True and a network address is not
supplied.
-
"""
_BaseNetwork.__init__(self, address)
-
- # Constructing from a packed address or integer
- if isinstance(address, (int, bytes)):
- addr = address
- mask = self._max_prefixlen
- # Constructing from a tuple (addr, [mask])
- elif isinstance(address, tuple):
- addr = address[0]
- mask = address[1] if len(address) > 1 else self._max_prefixlen
- # Assume input argument to be string or any object representation
- # which converts into a formatted IP prefix string.
- else:
- args = _split_optional_netmask(address)
- addr = self._ip_int_from_string(args[0])
- mask = args[1] if len(args) == 2 else self._max_prefixlen
+ addr, mask = self._split_addr_prefix(address)
self.network_address = IPv4Address(addr)
self.netmask, self._prefixlen = self._make_netmask(mask)
class IPv6Interface(IPv6Address):
def __init__(self, address):
- if isinstance(address, (bytes, int)):
- IPv6Address.__init__(self, address)
- self.network = IPv6Network(self._ip)
- self._prefixlen = self._max_prefixlen
- return
- if isinstance(address, tuple):
- IPv6Address.__init__(self, address[0])
- if len(address) > 1:
- self._prefixlen = int(address[1])
- else:
- self._prefixlen = self._max_prefixlen
- self.network = IPv6Network(address, strict=False)
- self.netmask = self.network.netmask
- self.hostmask = self.network.hostmask
- return
+ addr, mask = self._split_addr_prefix(address)
- addr = _split_optional_netmask(address)
- IPv6Address.__init__(self, addr[0])
- self.network = IPv6Network(address, strict=False)
+ IPv6Address.__init__(self, addr)
+ self.network = IPv6Network((addr, mask), strict=False)
self.netmask = self.network.netmask
- self._prefixlen = self.network._prefixlen
self.hostmask = self.network.hostmask
+ self._prefixlen = self.network._prefixlen
def __str__(self):
return '%s/%d' % (self._string_from_ip_int(self._ip),
an IPv6 address.
ValueError: If strict was True and a network address was not
supplied.
-
"""
_BaseNetwork.__init__(self, address)
-
- # Constructing from a packed address or integer
- if isinstance(address, (int, bytes)):
- addr = address
- mask = self._max_prefixlen
- # Constructing from a tuple (addr, [mask])
- elif isinstance(address, tuple):
- addr = address[0]
- mask = address[1] if len(address) > 1 else self._max_prefixlen
- # Assume input argument to be string or any object representation
- # which converts into a formatted IP prefix string.
- else:
- args = _split_optional_netmask(address)
- addr = self._ip_int_from_string(args[0])
- mask = args[1] if len(args) == 2 else self._max_prefixlen
+ addr, mask = self._split_addr_prefix(address)
self.network_address = IPv6Address(addr)
self.netmask, self._prefixlen = self._make_netmask(mask)
# Python imports
import io
import os
+import pkgutil
import sys
import logging
import operator
def get_all_fix_names(fixer_pkg, remove_prefix=True):
"""Return a sorted list of all available fix names in the given package."""
pkg = __import__(fixer_pkg, [], [], ["*"])
- fixer_dir = os.path.dirname(pkg.__file__)
fix_names = []
- for name in sorted(os.listdir(fixer_dir)):
- if name.startswith("fix_") and name.endswith(".py"):
+ for finder, name, ispkg in pkgutil.iter_modules(pkg.__path__):
+ if name.startswith("fix_"):
if remove_prefix:
name = name[4:]
- fix_names.append(name[:-3])
+ fix_names.append(name)
return fix_names
return tuple(code.split('.')[:2])
elif code == 'C':
return None, None
+ elif code == 'UTF-8':
+ # On macOS "LC_CTYPE=UTF-8" is a valid locale setting
+ # for getting UTF-8 handling for text.
+ return None, 'UTF-8'
raise ValueError('unknown locale: %s' % localename)
def _build_localename(localetuple):
-# Copyright 2001-2016 by Vinay Sajip. All Rights Reserved.
+# Copyright 2001-2019 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
is based on PEP 282 and comments thereto in comp.lang.python, and influenced
by Apache's log4j system.
-Copyright (C) 2001-2016 Vinay Sajip. All Rights Reserved.
+Copyright (C) 2001-2019 Vinay Sajip. All Rights Reserved.
To use, simply 'import logging' and log away!
"""
for log in existing:
logger = root.manager.loggerDict[log]
if log in child_loggers:
- logger.level = logging.NOTSET
- logger.handlers = []
- logger.propagate = True
+ if not isinstance(logger, logging.PlaceHolder):
+ logger.setLevel(logging.NOTSET)
+ logger.handlers = []
+ logger.propagate = True
else:
logger.disabled = disable_existing
def __init__(self, filenames=(), strict=True):
if not inited:
init()
- self.encodings_map = encodings_map.copy()
- self.suffix_map = suffix_map.copy()
+ self.encodings_map = _encodings_map_default.copy()
+ self.suffix_map = _suffix_map_default.copy()
self.types_map = ({}, {}) # dict for (non-strict, strict)
self.types_map_inv = ({}, {})
- for (ext, type) in types_map.items():
+ for (ext, type) in _types_map_default.items():
self.add_type(type, ext, True)
- for (ext, type) in common_types.items():
+ for (ext, type) in _common_types_default.items():
self.add_type(type, ext, False)
for name in filenames:
self.read(name, strict)
Optional `strict' argument when False adds a bunch of commonly found,
but non-standard types.
"""
+ url = os.fspath(url)
scheme, url = urllib.parse.splittype(url)
if scheme == 'data':
# syntax of data URLs:
global suffix_map, types_map, encodings_map, common_types
global inited, _db
inited = True # so that MimeTypes.__init__() doesn't call us again
- db = MimeTypes()
- if files is None:
+
+ if files is None or _db is None:
+ db = MimeTypes()
if _winreg:
db.read_windows_registry()
- files = knownfiles
+
+ if files is None:
+ files = knownfiles
+ else:
+ files = knownfiles + list(files)
+ else:
+ db = _db
+
for file in files:
if os.path.isfile(file):
db.read(file)
def _default_mime_types():
- global suffix_map
- global encodings_map
- global types_map
- global common_types
+ global suffix_map, _suffix_map_default
+ global encodings_map, _encodings_map_default
+ global types_map, _types_map_default
+ global common_types, _common_types_default
- suffix_map = {
+ suffix_map = _suffix_map_default = {
'.svgz': '.svg.gz',
'.tgz': '.tar.gz',
'.taz': '.tar.gz',
'.txz': '.tar.xz',
}
- encodings_map = {
+ encodings_map = _encodings_map_default = {
'.gz': 'gzip',
'.Z': 'compress',
'.bz2': 'bzip2',
# at http://www.iana.org/assignments/media-types
# or extensions, i.e. using the x- prefix
- # If you add to these, please keep them sorted!
- types_map = {
+ # If you add to these, please keep them sorted by mime type.
+ # Make sure the entry with the preferred file extension for a particular mime type
+ # appears before any others of the same mimetype.
+ types_map = _types_map_default = {
+ '.js' : 'application/javascript',
+ '.mjs' : 'application/javascript',
+ '.json' : 'application/json',
+ '.doc' : 'application/msword',
+ '.dot' : 'application/msword',
+ '.wiz' : 'application/msword',
+ '.bin' : 'application/octet-stream',
'.a' : 'application/octet-stream',
+ '.dll' : 'application/octet-stream',
+ '.exe' : 'application/octet-stream',
+ '.o' : 'application/octet-stream',
+ '.obj' : 'application/octet-stream',
+ '.so' : 'application/octet-stream',
+ '.oda' : 'application/oda',
+ '.pdf' : 'application/pdf',
+ '.p7c' : 'application/pkcs7-mime',
+ '.ps' : 'application/postscript',
'.ai' : 'application/postscript',
- '.aif' : 'audio/x-aiff',
- '.aifc' : 'audio/x-aiff',
- '.aiff' : 'audio/x-aiff',
- '.au' : 'audio/basic',
- '.avi' : 'video/x-msvideo',
- '.bat' : 'text/plain',
+ '.eps' : 'application/postscript',
+ '.m3u' : 'application/vnd.apple.mpegurl',
+ '.m3u8' : 'application/vnd.apple.mpegurl',
+ '.xls' : 'application/vnd.ms-excel',
+ '.xlb' : 'application/vnd.ms-excel',
+ '.ppt' : 'application/vnd.ms-powerpoint',
+ '.pot' : 'application/vnd.ms-powerpoint',
+ '.ppa' : 'application/vnd.ms-powerpoint',
+ '.pps' : 'application/vnd.ms-powerpoint',
+ '.pwz' : 'application/vnd.ms-powerpoint',
+ '.wasm' : 'application/wasm',
'.bcpio' : 'application/x-bcpio',
- '.bin' : 'application/octet-stream',
- '.bmp' : 'image/bmp',
- '.c' : 'text/plain',
- '.cdf' : 'application/x-netcdf',
'.cpio' : 'application/x-cpio',
'.csh' : 'application/x-csh',
- '.css' : 'text/css',
- '.csv' : 'text/csv',
- '.dll' : 'application/octet-stream',
- '.doc' : 'application/msword',
- '.dot' : 'application/msword',
'.dvi' : 'application/x-dvi',
- '.eml' : 'message/rfc822',
- '.eps' : 'application/postscript',
- '.etx' : 'text/x-setext',
- '.exe' : 'application/octet-stream',
- '.gif' : 'image/gif',
'.gtar' : 'application/x-gtar',
- '.h' : 'text/plain',
'.hdf' : 'application/x-hdf',
- '.htm' : 'text/html',
- '.html' : 'text/html',
- '.ico' : 'image/vnd.microsoft.icon',
- '.ief' : 'image/ief',
- '.jpe' : 'image/jpeg',
- '.jpeg' : 'image/jpeg',
- '.jpg' : 'image/jpeg',
- '.js' : 'application/javascript',
- '.json' : 'application/json',
- '.ksh' : 'text/plain',
'.latex' : 'application/x-latex',
- '.m1v' : 'video/mpeg',
- '.m3u' : 'application/vnd.apple.mpegurl',
- '.m3u8' : 'application/vnd.apple.mpegurl',
- '.man' : 'application/x-troff-man',
- '.me' : 'application/x-troff-me',
- '.mht' : 'message/rfc822',
- '.mhtml' : 'message/rfc822',
'.mif' : 'application/x-mif',
- '.mjs' : 'application/javascript',
- '.mov' : 'video/quicktime',
- '.movie' : 'video/x-sgi-movie',
- '.mp2' : 'audio/mpeg',
- '.mp3' : 'audio/mpeg',
- '.mp4' : 'video/mp4',
- '.mpa' : 'video/mpeg',
- '.mpe' : 'video/mpeg',
- '.mpeg' : 'video/mpeg',
- '.mpg' : 'video/mpeg',
- '.ms' : 'application/x-troff-ms',
+ '.cdf' : 'application/x-netcdf',
'.nc' : 'application/x-netcdf',
- '.nws' : 'message/rfc822',
- '.o' : 'application/octet-stream',
- '.obj' : 'application/octet-stream',
- '.oda' : 'application/oda',
'.p12' : 'application/x-pkcs12',
- '.p7c' : 'application/pkcs7-mime',
- '.pbm' : 'image/x-portable-bitmap',
- '.pdf' : 'application/pdf',
'.pfx' : 'application/x-pkcs12',
- '.pgm' : 'image/x-portable-graymap',
- '.pl' : 'text/plain',
- '.png' : 'image/png',
- '.pnm' : 'image/x-portable-anymap',
- '.pot' : 'application/vnd.ms-powerpoint',
- '.ppa' : 'application/vnd.ms-powerpoint',
- '.ppm' : 'image/x-portable-pixmap',
- '.pps' : 'application/vnd.ms-powerpoint',
- '.ppt' : 'application/vnd.ms-powerpoint',
- '.ps' : 'application/postscript',
- '.pwz' : 'application/vnd.ms-powerpoint',
- '.py' : 'text/x-python',
+ '.ram' : 'application/x-pn-realaudio',
'.pyc' : 'application/x-python-code',
'.pyo' : 'application/x-python-code',
- '.qt' : 'video/quicktime',
- '.ra' : 'audio/x-pn-realaudio',
- '.ram' : 'application/x-pn-realaudio',
- '.ras' : 'image/x-cmu-raster',
- '.rdf' : 'application/xml',
- '.rgb' : 'image/x-rgb',
- '.roff' : 'application/x-troff',
- '.rtx' : 'text/richtext',
- '.sgm' : 'text/x-sgml',
- '.sgml' : 'text/x-sgml',
'.sh' : 'application/x-sh',
'.shar' : 'application/x-shar',
- '.snd' : 'audio/basic',
- '.so' : 'application/octet-stream',
- '.src' : 'application/x-wais-source',
+ '.swf' : 'application/x-shockwave-flash',
'.sv4cpio': 'application/x-sv4cpio',
'.sv4crc' : 'application/x-sv4crc',
- '.svg' : 'image/svg+xml',
- '.swf' : 'application/x-shockwave-flash',
- '.t' : 'application/x-troff',
'.tar' : 'application/x-tar',
'.tcl' : 'application/x-tcl',
'.tex' : 'application/x-tex',
'.texi' : 'application/x-texinfo',
'.texinfo': 'application/x-texinfo',
- '.tif' : 'image/tiff',
- '.tiff' : 'image/tiff',
+ '.roff' : 'application/x-troff',
+ '.t' : 'application/x-troff',
'.tr' : 'application/x-troff',
- '.tsv' : 'text/tab-separated-values',
- '.txt' : 'text/plain',
+ '.man' : 'application/x-troff-man',
+ '.me' : 'application/x-troff-me',
+ '.ms' : 'application/x-troff-ms',
'.ustar' : 'application/x-ustar',
- '.vcf' : 'text/x-vcard',
- '.wav' : 'audio/x-wav',
- '.webm' : 'video/webm',
- '.wiz' : 'application/msword',
+ '.src' : 'application/x-wais-source',
+ '.xsl' : 'application/xml',
+ '.rdf' : 'application/xml',
'.wsdl' : 'application/xml',
- '.xbm' : 'image/x-xbitmap',
- '.xlb' : 'application/vnd.ms-excel',
- '.xls' : 'application/vnd.ms-excel',
- '.xml' : 'text/xml',
'.xpdl' : 'application/xml',
+ '.zip' : 'application/zip',
+ '.au' : 'audio/basic',
+ '.snd' : 'audio/basic',
+ '.mp3' : 'audio/mpeg',
+ '.mp2' : 'audio/mpeg',
+ '.aif' : 'audio/x-aiff',
+ '.aifc' : 'audio/x-aiff',
+ '.aiff' : 'audio/x-aiff',
+ '.ra' : 'audio/x-pn-realaudio',
+ '.wav' : 'audio/x-wav',
+ '.bmp' : 'image/bmp',
+ '.gif' : 'image/gif',
+ '.ief' : 'image/ief',
+ '.jpg' : 'image/jpeg',
+ '.jpe' : 'image/jpeg',
+ '.jpeg' : 'image/jpeg',
+ '.png' : 'image/png',
+ '.svg' : 'image/svg+xml',
+ '.tiff' : 'image/tiff',
+ '.tif' : 'image/tiff',
+ '.ico' : 'image/vnd.microsoft.icon',
+ '.ras' : 'image/x-cmu-raster',
+ '.bmp' : 'image/x-ms-bmp',
+ '.pnm' : 'image/x-portable-anymap',
+ '.pbm' : 'image/x-portable-bitmap',
+ '.pgm' : 'image/x-portable-graymap',
+ '.ppm' : 'image/x-portable-pixmap',
+ '.rgb' : 'image/x-rgb',
+ '.xbm' : 'image/x-xbitmap',
'.xpm' : 'image/x-xpixmap',
- '.xsl' : 'application/xml',
'.xwd' : 'image/x-xwindowdump',
- '.zip' : 'application/zip',
+ '.eml' : 'message/rfc822',
+ '.mht' : 'message/rfc822',
+ '.mhtml' : 'message/rfc822',
+ '.nws' : 'message/rfc822',
+ '.css' : 'text/css',
+ '.csv' : 'text/csv',
+ '.html' : 'text/html',
+ '.htm' : 'text/html',
+ '.txt' : 'text/plain',
+ '.bat' : 'text/plain',
+ '.c' : 'text/plain',
+ '.h' : 'text/plain',
+ '.ksh' : 'text/plain',
+ '.pl' : 'text/plain',
+ '.rtx' : 'text/richtext',
+ '.tsv' : 'text/tab-separated-values',
+ '.py' : 'text/x-python',
+ '.etx' : 'text/x-setext',
+ '.sgm' : 'text/x-sgml',
+ '.sgml' : 'text/x-sgml',
+ '.vcf' : 'text/x-vcard',
+ '.xml' : 'text/xml',
+ '.mp4' : 'video/mp4',
+ '.mpeg' : 'video/mpeg',
+ '.m1v' : 'video/mpeg',
+ '.mpa' : 'video/mpeg',
+ '.mpe' : 'video/mpeg',
+ '.mpg' : 'video/mpeg',
+ '.mov' : 'video/quicktime',
+ '.qt' : 'video/quicktime',
+ '.webm' : 'video/webm',
+ '.avi' : 'video/x-msvideo',
+ '.movie' : 'video/x-sgi-movie',
}
# These are non-standard types, commonly found in the wild. They will
# only match if strict=0 flag is given to the API methods.
# Please sort these too
- common_types = {
- '.jpg' : 'image/jpg',
- '.mid' : 'audio/midi',
+ common_types = _common_types_default = {
+ '.rtf' : 'application/rtf',
'.midi': 'audio/midi',
+ '.mid' : 'audio/midi',
+ '.jpg' : 'image/jpg',
+ '.pict': 'image/pict',
'.pct' : 'image/pict',
'.pic' : 'image/pict',
- '.pict': 'image/pict',
- '.rtf' : 'application/rtf',
- '.xul' : 'text/xul'
+ '.xul' : 'text/xul',
}
# Function returning a temp directory which will be removed on exit
#
+def _remove_temp_dir(rmtree, tempdir):
+ rmtree(tempdir)
+
+ current_process = process.current_process()
+ # current_process() can be None if the finalizer is called
+ # late during Python finalization
+ if current_process is not None:
+ current_process._config['tempdir'] = None
+
def get_temp_dir():
# get name of a temp directory which will be automatically cleaned up
tempdir = process.current_process()._config.get('tempdir')
import shutil, tempfile
tempdir = tempfile.mkdtemp(prefix='pymp-')
info('created temp directory %s', tempdir)
- Finalize(None, shutil.rmtree, args=[tempdir], exitpriority=-100)
+ # keep a strong reference to shutil.rmtree(), since the finalizer
+ # can be called late during Python shutdown
+ Finalize(None, _remove_temp_dir, args=(shutil.rmtree, tempdir),
+ exitpriority=-100)
process.current_process()._config['tempdir'] = tempdir
return tempdir
(e.g., via del or slice assignment), and walk will only recurse into the
subdirectories whose names remain in dirnames; this can be used to prune the
search, or to impose a specific order of visiting. Modifying dirnames when
- topdown is false is ineffective, since the directories in dirnames have
- already been generated by the time dirnames itself is generated. No matter
- the value of topdown, the list of subdirectories is retrieved before the
- tuples for the directory and its subdirectories are generated.
+ topdown is false has no effect on the behavior of os.walk(), since the
+ directories in dirnames have already been generated by the time dirnames
+ itself is generated. No matter the value of topdown, the list of
+ subdirectories is retrieved before the tuples for the directory and its
+ subdirectories are generated.
By default errors from the os.scandir() call are ignored. If
optional arg 'onerror' is specified, it should be a function; it
"""execvpe(file, args, env)
Execute the executable file (which is searched for along $PATH)
- with argument list args and environment env , replacing the
+ with argument list args and environment env, replacing the
current process.
args may be a list or tuple of strings. """
_execvpe(file, args, env)
self.allow_kbdint = False
self.nosigint = nosigint
- # Read $HOME/.pdbrc and ./.pdbrc
+ # Read ~/.pdbrc and ./.pdbrc
self.rcLines = []
if readrc:
- if 'HOME' in os.environ:
- envHome = os.environ['HOME']
- try:
- with open(os.path.join(envHome, ".pdbrc")) as rcFile:
- self.rcLines.extend(rcFile)
- except OSError:
- pass
+ try:
+ with open(os.path.expanduser('~/.pdbrc')) as rcFile:
+ self.rcLines.extend(rcFile)
+ except OSError:
+ pass
try:
with open(".pdbrc") as rcFile:
self.rcLines.extend(rcFile)
def main():
import getopt
- opts, args = getopt.getopt(sys.argv[1:], 'mhc:', ['--help', '--command='])
+ opts, args = getopt.getopt(sys.argv[1:], 'mhc:', ['help', 'command='])
if not args:
print(_usage)
def load(fp, *, fmt=None, use_builtin_types=True, dict_type=dict):
- """Read a .plist file. 'fp' should be (readable) file object.
+ """Read a .plist file. 'fp' should be a readable and binary file object.
Return the unpacked root object (which usually is a dictionary).
"""
if fmt is None:
def dump(value, fp, *, fmt=FMT_XML, sort_keys=True, skipkeys=False):
- """Write 'value' to a .plist file. 'fp' should be a (writable)
- file object.
+ """Write 'value' to a .plist file. 'fp' should be a writable,
+ binary file object.
"""
if fmt not in _FORMATS:
raise ValueError("Unsupported format: %r"%(fmt,))
# -*- coding: utf-8 -*-
-# Autogenerated by Sphinx on Tue Jun 18 16:49:39 2019
+# Autogenerated by Sphinx on Mon Oct 14 18:26:58 2019
topics = {'assert': 'The "assert" statement\n'
'**********************\n'
'\n'
' | | significand, and the decimal point is also '
'removed if |\n'
' | | there are no remaining digits following '
- 'it. Positive and |\n'
- ' | | negative infinity, positive and negative '
- 'zero, and nans, |\n'
- ' | | are formatted as "inf", "-inf", "0", "-0" '
- 'and "nan" |\n'
- ' | | respectively, regardless of the '
- 'precision. A precision of |\n'
- ' | | "0" is treated as equivalent to a '
- 'precision of "1". The |\n'
- ' | | default precision is '
- '"6". |\n'
+ 'it, unless the |\n'
+ ' | | "\'#\'" option is used. Positive and '
+ 'negative infinity, |\n'
+ ' | | positive and negative zero, and nans, are '
+ 'formatted as |\n'
+ ' | | "inf", "-inf", "0", "-0" and "nan" '
+ 'respectively, |\n'
+ ' | | regardless of the precision. A precision '
+ 'of "0" is |\n'
+ ' | | treated as equivalent to a precision of '
+ '"1". The default |\n'
+ ' | | precision is '
+ '"6". |\n'
' '
'+-----------+------------------------------------------------------------+\n'
' | "\'G\'" | General format. Same as "\'g\'" except '
'| "x(arguments...)", "x.attribute" | '
'attribute reference |\n'
'+-------------------------------------------------+---------------------------------------+\n'
- '| "(expressions...)", "[expressions...]", "{key: | '
- 'Binding or tuple display, list |\n'
- '| value...}", "{expressions...}" | '
- 'display, dictionary display, set |\n'
+ '| "(expressions...)", "[expressions...]", "{key: | '
+ 'Binding or parenthesized expression, |\n'
+ '| value...}", "{expressions...}" | list '
+ 'display, dictionary display, set |\n'
'| | '
'display |\n'
'+-------------------------------------------------+---------------------------------------+\n'
' estimated length for the object (which may be greater '
'or less than\n'
' the actual length). The length must be an integer ">=" '
- '0. This\n'
+ '0. The\n'
+ ' return value may also be "NotImplemented", which is '
+ 'treated the\n'
+ ' same as if the "__length_hint__" method didn’t exist at '
+ 'all. This\n'
' method is purely an optimization and is never required '
'for\n'
' correctness.\n'
' estimated length for the object (which may be greater or '
'less than\n'
' the actual length). The length must be an integer ">=" 0. '
- 'This\n'
+ 'The\n'
+ ' return value may also be "NotImplemented", which is '
+ 'treated the\n'
+ ' same as if the "__length_hint__" method didn’t exist at '
+ 'all. This\n'
' method is purely an optimization and is never required '
'for\n'
' correctness.\n'
'\n'
' Return true if there are only whitespace characters in '
'the string\n'
- ' and there is at least one character, false otherwise. '
- 'Whitespace\n'
- ' characters are those characters defined in the Unicode '
- 'character\n'
- ' database as “Other” or “Separator” and those with '
- 'bidirectional\n'
- ' property being one of “WS”, “B”, or “S”.\n'
+ ' and there is at least one character, false otherwise.\n'
+ '\n'
+ ' A character is *whitespace* if in the Unicode character '
+ 'database\n'
+ ' (see "unicodedata"), either its general category is '
+ '"Zs"\n'
+ ' (“Separator, space”), or its bidirectional class is one '
+ 'of "WS",\n'
+ ' "B", or "S".\n'
'\n'
'str.istitle()\n'
'\n'
'therefore,\n'
' custom mapping types should support too):\n'
'\n'
+ ' list(d)\n'
+ '\n'
+ ' Return a list of all the keys used in the dictionary '
+ '*d*.\n'
+ '\n'
' len(d)\n'
'\n'
' Return the number of items in the dictionary *d*.\n'
'the\n'
' documentation of view objects.\n'
'\n'
+ ' An equality comparison between one "dict.values()" '
+ 'view and\n'
+ ' another will always return "False". This also applies '
+ 'when\n'
+ ' comparing "dict.values()" to itself:\n'
+ '\n'
+ " >>> d = {'a': 1}\n"
+ ' >>> d.values() == d.values()\n'
+ ' False\n'
+ '\n'
' Dictionaries compare equal if and only if they have the '
'same "(key,\n'
- ' value)" pairs. Order comparisons (‘<’, ‘<=’, ‘>=’, ‘>’) '
- 'raise\n'
- ' "TypeError".\n'
+ ' value)" pairs (regardless of ordering). Order comparisons '
+ '(‘<’,\n'
+ ' ‘<=’, ‘>=’, ‘>’) raise "TypeError".\n'
'\n'
' Dictionaries preserve insertion order. Note that '
'updating a key\n'
punctuation_chars = ''
elif punctuation_chars is True:
punctuation_chars = '();<>|&'
- self.punctuation_chars = punctuation_chars
+ self._punctuation_chars = punctuation_chars
if punctuation_chars:
# _pushback_chars is a push back queue used by lookahead logic
self._pushback_chars = deque()
t = self.wordchars.maketrans(dict.fromkeys(punctuation_chars))
self.wordchars = self.wordchars.translate(t)
+ @property
+ def punctuation_chars(self):
+ return self._punctuation_chars
+
def push_token(self, tok):
"Push a token onto the stack popped by the get_token method"
if self.debug >= 1:
def CheckSqliteRowIndex(self):
self.con.row_factory = sqlite.Row
- row = self.con.execute("select 1 as a, 2 as b").fetchone()
+ row = self.con.execute("select 1 as a_1, 2 as b").fetchone()
self.assertIsInstance(row, sqlite.Row)
- col1, col2 = row["a"], row["b"]
- self.assertEqual(col1, 1, "by name: wrong result for column 'a'")
- self.assertEqual(col2, 2, "by name: wrong result for column 'a'")
+ self.assertEqual(row["a_1"], 1, "by name: wrong result for column 'a_1'")
+ self.assertEqual(row["b"], 2, "by name: wrong result for column 'b'")
- col1, col2 = row["A"], row["B"]
- self.assertEqual(col1, 1, "by name: wrong result for column 'A'")
- self.assertEqual(col2, 2, "by name: wrong result for column 'B'")
+ self.assertEqual(row["A_1"], 1, "by name: wrong result for column 'A_1'")
+ self.assertEqual(row["B"], 2, "by name: wrong result for column 'B'")
self.assertEqual(row[0], 1, "by index: wrong result for column 0")
self.assertEqual(row[1], 2, "by index: wrong result for column 1")
with self.assertRaises(IndexError):
row['c']
+ with self.assertRaises(IndexError):
+ row['a_\x11']
+ with self.assertRaises(IndexError):
+ row['a\x7f1']
with self.assertRaises(IndexError):
row[2]
with self.assertRaises(IndexError):
with self.assertRaises(IndexError):
row[2**1000]
+ def CheckSqliteRowIndexUnicode(self):
+ self.con.row_factory = sqlite.Row
+ row = self.con.execute("select 1 as \xff").fetchone()
+ self.assertEqual(row["\xff"], 1)
+ with self.assertRaises(IndexError):
+ row['\u0178']
+ with self.assertRaises(IndexError):
+ row['\xdf']
+
def CheckSqliteRowSlice(self):
# A sqlite.Row can be sliced like a list.
self.con.row_factory = sqlite.Row
row_1 = self.con.execute("select 1 as a, 2 as b").fetchone()
row_2 = self.con.execute("select 1 as a, 2 as b").fetchone()
row_3 = self.con.execute("select 1 as a, 3 as b").fetchone()
+ row_4 = self.con.execute("select 1 as b, 2 as a").fetchone()
+ row_5 = self.con.execute("select 2 as b, 1 as a").fetchone()
- self.assertEqual(row_1, row_1)
- self.assertEqual(row_1, row_2)
- self.assertTrue(row_2 != row_3)
+ self.assertTrue(row_1 == row_1)
+ self.assertTrue(row_1 == row_2)
+ self.assertFalse(row_1 == row_3)
+ self.assertFalse(row_1 == row_4)
+ self.assertFalse(row_1 == row_5)
+ self.assertFalse(row_1 == object())
self.assertFalse(row_1 != row_1)
self.assertFalse(row_1 != row_2)
- self.assertFalse(row_2 == row_3)
+ self.assertTrue(row_1 != row_3)
+ self.assertTrue(row_1 != row_4)
+ self.assertTrue(row_1 != row_5)
+ self.assertTrue(row_1 != object())
+
+ with self.assertRaises(TypeError):
+ row_1 > row_2
+ with self.assertRaises(TypeError):
+ row_1 < row_2
+ with self.assertRaises(TypeError):
+ row_1 >= row_2
+ with self.assertRaises(TypeError):
+ row_1 <= row_2
- self.assertEqual(row_1, row_2)
self.assertEqual(hash(row_1), hash(row_2))
- self.assertNotEqual(row_1, row_3)
- self.assertNotEqual(hash(row_1), hash(row_3))
def CheckSqliteRowAsSequence(self):
""" Checks if the row object can act like a sequence """
raise source.error("bad escape %s" % escape, len(escape))
def _uniq(items):
- if len(set(items)) == len(items):
- return items
- newitems = []
- for item in items:
- if item not in newitems:
- newitems.append(item)
- return newitems
+ return list(dict.fromkeys(items))
def _parse_sub(source, state, verbose, nested):
# parse an alternation: a|b|c
__str__ = __repr__
-# This lists holds Popen instances for which the underlying process had not
-# exited at the time its __del__ method got called: those processes are wait()ed
-# for synchronously from _cleanup() when a new Popen object is created, to avoid
-# zombie processes.
-_active = []
-
-def _cleanup():
- for inst in _active[:]:
- res = inst._internal_poll(_deadstate=sys.maxsize)
- if res is not None:
- try:
- _active.remove(inst)
- except ValueError:
- # This can happen if two threads create a new Popen instance.
- # It's harmless that it was already removed, so ignore.
- pass
+if _mswindows:
+ # On Windows we just need to close `Popen._handle` when we no longer need
+ # it, so that the kernel can free it. `Popen._handle` gets closed
+ # implicitly when the `Popen` instance is finalized (see `Handle.__del__`,
+ # which is calling `CloseHandle` as requested in [1]), so there is nothing
+ # for `_cleanup` to do.
+ #
+ # [1] https://docs.microsoft.com/en-us/windows/desktop/ProcThread/
+ # creating-processes
+ _active = None
+
+ def _cleanup():
+ pass
+else:
+ # This lists holds Popen instances for which the underlying process had not
+ # exited at the time its __del__ method got called: those processes are
+ # wait()ed for synchronously from _cleanup() when a new Popen object is
+ # created, to avoid zombie processes.
+ _active = []
+
+ def _cleanup():
+ if _active is None:
+ return
+ for inst in _active[:]:
+ res = inst._internal_poll(_deadstate=sys.maxsize)
+ if res is not None:
+ try:
+ _active.remove(inst)
+ except ValueError:
+ # This can happen if two threads create a new Popen instance.
+ # It's harmless that it was already removed, so ignore.
+ pass
PIPE = -1
STDOUT = -2
b'when in the course of barman events\n'
By default, all communication is in bytes, and therefore any "input"
- should be bytes, and the return value wil be bytes. If in text mode,
+ should be bytes, and the return value will be bytes. If in text mode,
any "input" should be a string, and the return value will be a string
decoded according to locale encoding, or by "encoding" if set. Text mode
is triggered by setting any of text, encoding, errors or universal_newlines.
with Popen(*popenargs, **kwargs) as process:
try:
stdout, stderr = process.communicate(input, timeout=timeout)
- except TimeoutExpired:
+ except TimeoutExpired as exc:
process.kill()
- stdout, stderr = process.communicate()
- raise TimeoutExpired(process.args, timeout, output=stdout,
- stderr=stderr)
+ if _mswindows:
+ # Windows accumulates the output in a single blocking
+ # read() call run on child threads, with the timeout
+ # being done in a join() on those threads. communicate()
+ # _after_ kill() is required to collect that and add it
+ # to the exception.
+ exc.stdout, exc.stderr = process.communicate()
+ else:
+ # POSIX _communicate already populated the output so
+ # far into the TimeoutExpired exception.
+ process.wait()
+ raise
except: # Including KeyboardInterrupt, communicate handled that.
process.kill()
# We don't call process.wait() as .__exit__ does that for us.
return endtime - _time()
- def _check_timeout(self, endtime, orig_timeout):
+ def _check_timeout(self, endtime, orig_timeout, stdout_seq, stderr_seq,
+ skip_check_and_raise=False):
"""Convenience for checking if a timeout has expired."""
if endtime is None:
return
- if _time() > endtime:
- raise TimeoutExpired(self.args, orig_timeout)
+ if skip_check_and_raise or _time() > endtime:
+ raise TimeoutExpired(
+ self.args, orig_timeout,
+ output=b''.join(stdout_seq) if stdout_seq else None,
+ stderr=b''.join(stderr_seq) if stderr_seq else None)
def wait(self, timeout=None):
while selector.get_map():
timeout = self._remaining_time(endtime)
if timeout is not None and timeout < 0:
- raise TimeoutExpired(self.args, orig_timeout)
+ self._check_timeout(endtime, orig_timeout,
+ stdout, stderr,
+ skip_check_and_raise=True)
+ raise RuntimeError( # Impossible :)
+ '_check_timeout(..., skip_check_and_raise=True) '
+ 'failed to raise TimeoutExpired.')
ready = selector.select(timeout)
- self._check_timeout(endtime, orig_timeout)
+ self._check_timeout(endtime, orig_timeout, stdout, stderr)
# XXX Rewrite these to use non-blocking I/O on the file
# objects; they are no longer using C stdio!
q = self.Queue()
q.put(NotSerializable())
q.put(True)
- # bpo-30595: use a timeout of 1 second for slow buildbots
- self.assertTrue(q.get(timeout=1.0))
+ self.assertTrue(q.get(timeout=TIMEOUT))
close_queue(q)
with test.support.captured_stderr():
self.common(manager)
manager.shutdown()
- # If the manager process exited cleanly then the exitcode
- # will be zero. Otherwise (after a short timeout)
- # terminate() is used, resulting in an exitcode of -SIGTERM.
- self.assertEqual(manager._process.exitcode, 0)
+ # bpo-30356: BaseManager._finalize_manager() sends SIGTERM
+ # to the manager process if it takes longer than 1 second to stop,
+ # which happens on slow buildbots.
+ self.assertIn(manager._process.exitcode, (0, -signal.SIGTERM))
def test_mymanager_context(self):
with MyManager() as manager:
self.common(manager)
# bpo-30356: BaseManager._finalize_manager() sends SIGTERM
- # to the manager process if it takes longer than 1 second to stop.
+ # to the manager process if it takes longer than 1 second to stop,
+ # which happens on slow buildbots.
self.assertIn(manager._process.exitcode, (0, -signal.SIGTERM))
def test_mymanager_context_prestarted(self):
See http://www.zope.org/Members/fdrake/DateTimeWiki/TestCases
"""
-from test.support import is_resource_enabled
-
import itertools
import bisect
-
import copy
import decimal
import sys
from operator import lt, le, gt, ge, eq, ne, truediv, floordiv, mod
from test import support
+from test.support import is_resource_enabled, ALWAYS_EQ, LARGEST, SMALLEST
import datetime as datetime_module
from datetime import MINYEAR, MAXYEAR
INF = float("inf")
NAN = float("nan")
+
#############################################################################
# module tests
self.assertTrue(timezone(ZERO) != None)
self.assertFalse(timezone(ZERO) == None)
+ tz = timezone(ZERO)
+ self.assertTrue(tz == ALWAYS_EQ)
+ self.assertFalse(tz != ALWAYS_EQ)
+ self.assertTrue(tz < LARGEST)
+ self.assertFalse(tz > LARGEST)
+ self.assertTrue(tz <= LARGEST)
+ self.assertFalse(tz >= LARGEST)
+ self.assertFalse(tz < SMALLEST)
+ self.assertTrue(tz > SMALLEST)
+ self.assertFalse(tz <= SMALLEST)
+ self.assertTrue(tz >= SMALLEST)
+
def test_aware_datetime(self):
# test that timezone instances can be used by datetime
t = datetime(1, 1, 1)
tz_copy = copy.deepcopy(tz)
self.assertIs(tz_copy, tz)
+ def test_offset_boundaries(self):
+ # Test timedeltas close to the boundaries
+ time_deltas = [
+ timedelta(hours=23, minutes=59),
+ timedelta(hours=23, minutes=59, seconds=59),
+ timedelta(hours=23, minutes=59, seconds=59, microseconds=999999),
+ ]
+ time_deltas.extend([-delta for delta in time_deltas])
+
+ for delta in time_deltas:
+ with self.subTest(test_type='good', delta=delta):
+ timezone(delta)
+
+ # Test timedeltas on and outside the boundaries
+ bad_time_deltas = [
+ timedelta(hours=24),
+ timedelta(hours=24, microseconds=1),
+ ]
+ bad_time_deltas.extend([-delta for delta in bad_time_deltas])
+
+ for delta in bad_time_deltas:
+ with self.subTest(test_type='bad', delta=delta):
+ with self.assertRaises(ValueError):
+ timezone(delta)
+
+ def test_comparison_with_tzinfo(self):
+ # Constructing tzinfo objects directly should not be done by users
+ # and serves only to check the bug described in bpo-37915
+ self.assertNotEqual(timezone.utc, tzinfo())
+ self.assertNotEqual(timezone(timedelta(hours=1)), tzinfo())
#############################################################################
# Base class for testing a particular aspect of timedelta, time, date and
self.assertIn(me, [1, 20, [], me])
self.assertIn([], [me, 1, 20, []])
+ # Comparison to objects of unsupported types should return
+ # NotImplemented which falls back to the right hand side's __eq__
+ # method. In this case, ALWAYS_EQ.__eq__ always returns True.
+ # ALWAYS_EQ.__ne__ always returns False.
+ self.assertTrue(me == ALWAYS_EQ)
+ self.assertFalse(me != ALWAYS_EQ)
+
+ # If the other class explicitly defines ordering
+ # relative to our class, it is allowed to do so
+ self.assertTrue(me < LARGEST)
+ self.assertFalse(me > LARGEST)
+ self.assertTrue(me <= LARGEST)
+ self.assertFalse(me >= LARGEST)
+ self.assertFalse(me < SMALLEST)
+ self.assertTrue(me > SMALLEST)
+ self.assertFalse(me <= SMALLEST)
+ self.assertTrue(me >= SMALLEST)
+
def test_harmful_mixed_comparison(self):
me = self.theclass(1, 1, 1)
t.strftime("%f")
def test_strftime_trailing_percent(self):
- # bpo-35066: make sure trailing '%' doesn't cause
- # datetime's strftime to complain
+ # bpo-35066: Make sure trailing '%' doesn't cause datetime's strftime to
+ # complain. Different libcs have different handling of trailing
+ # percents, so we simply check datetime's strftime acts the same as
+ # time.strftime.
t = self.theclass(2005, 3, 2)
try:
_time.strftime('%')
except ValueError:
self.skipTest('time module does not support trailing %')
- self.assertEqual(t.strftime('%'), '%')
- self.assertEqual(t.strftime("m:%m d:%d y:%y %"), "m:03 d:02 y:05 %")
+ self.assertEqual(t.strftime('%'), _time.strftime('%', t.timetuple()))
+ self.assertEqual(
+ t.strftime("m:%m d:%d y:%y %"),
+ _time.strftime("m:03 d:02 y:05 %", t.timetuple()),
+ )
def test_format(self):
dt = self.theclass(2007, 9, 10)
self.assertRaises(TypeError, lambda: our < their)
self.assertRaises(TypeError, lambda: their < our)
- # However, if the other class explicitly defines ordering
- # relative to our class, it is allowed to do so
-
- class LargerThanAnything:
- def __lt__(self, other):
- return False
- def __le__(self, other):
- return isinstance(other, LargerThanAnything)
- def __eq__(self, other):
- return isinstance(other, LargerThanAnything)
- def __gt__(self, other):
- return not isinstance(other, LargerThanAnything)
- def __ge__(self, other):
- return True
-
- their = LargerThanAnything()
- self.assertEqual(our == their, False)
- self.assertEqual(their == our, False)
- self.assertEqual(our != their, True)
- self.assertEqual(their != our, True)
- self.assertEqual(our < their, True)
- self.assertEqual(their < our, False)
-
def test_bool(self):
# All dates are considered true.
self.assertTrue(self.theclass.min)
def test_compat_unpickle(self):
tests = [
- b"cdatetime\ntime\n(S'\\x14;\\x10\\x00\\x10\\x00'\ntR.",
- b'cdatetime\ntime\n(U\x06\x14;\x10\x00\x10\x00tR.',
- b'\x80\x02cdatetime\ntime\nU\x06\x14;\x10\x00\x10\x00\x85R.',
+ (b"cdatetime\ntime\n(S'\\x14;\\x10\\x00\\x10\\x00'\ntR.",
+ (20, 59, 16, 64**2)),
+ (b'cdatetime\ntime\n(U\x06\x14;\x10\x00\x10\x00tR.',
+ (20, 59, 16, 64**2)),
+ (b'\x80\x02cdatetime\ntime\nU\x06\x14;\x10\x00\x10\x00\x85R.',
+ (20, 59, 16, 64**2)),
+ (b"cdatetime\ntime\n(S'\\x14;\\x19\\x00\\x10\\x00'\ntR.",
+ (20, 59, 25, 64**2)),
+ (b'cdatetime\ntime\n(U\x06\x14;\x19\x00\x10\x00tR.',
+ (20, 59, 25, 64**2)),
+ (b'\x80\x02cdatetime\ntime\nU\x06\x14;\x19\x00\x10\x00\x85R.',
+ (20, 59, 25, 64**2)),
]
- args = 20, 59, 16, 64**2
- expected = self.theclass(*args)
- for data in tests:
- for loads in pickle_loads:
- derived = loads(data, encoding='latin1')
- self.assertEqual(derived, expected)
+ for i, (data, args) in enumerate(tests):
+ with self.subTest(i=i):
+ expected = self.theclass(*args)
+ for loads in pickle_loads:
+ derived = loads(data, encoding='latin1')
+ self.assertEqual(derived, expected)
def test_bool(self):
# time is always True.
self.assertRaises(ValueError, base.replace, microsecond=1000000)
def test_mixed_compare(self):
- t1 = time(1, 2, 3)
- t2 = time(1, 2, 3)
+ t1 = self.theclass(1, 2, 3)
+ t2 = self.theclass(1, 2, 3)
self.assertEqual(t1, t2)
t2 = t2.replace(tzinfo=None)
self.assertEqual(t1, t2)
------BEGIN RSA PRIVATE KEY-----
-Proc-Type: 4,ENCRYPTED
-DEK-Info: DES-EDE3-CBC,D134E931C96D9DEC
-
-nuGFEej7vIjkYWSMz5OJeVTNntDRQi6ZM4DBm3g8T7i/0odr3WFqGMMKZcIhLYQf
-rgRq7RSKtrJ1y5taVucMV+EuCjyfzDo0TsYt+ZrXv/D08eZhjRmkhoHnGVF0TqQm
-nQEXM/ERT4J2RM78dnG+homMkI76qOqxgGbRqQqJo6AiVRcAZ45y8s96bru2TAB8
-+pWjO/v0Je7AFVdwSU52N8OOY6uoSAygW+0UY1WVxbVGJF2XfRsNpPX+YQHYl6e+
-3xM5XBVCgr6kmdAyub5qUJ38X3TpdVGoR0i+CVS9GTr2pSRib1zURAeeHnlqiUZM
-4m0Gn9s72nJevU1wxED8pwOhR8fnHEmMKGD2HPhKoOCbzDhwwBZO27TNa1uWeM3f
-M5oixKDi2PqMn3y2cDx1NjJtP661688EcJ5a2Ih9BgO9xpnhSyzBWEKcAn0tJB0H
-/56M0FW6cdOOIzMveGGL7sHW5E+iOdI1n5e7C6KJUzew78Y9qJnhS53EdI6qTz9R
-wsIsj1i070Fk6RbPo6zpLlF6w7Zj8GlZaZA7OZZv9wo5VEV/0ST8gmiiBOBc4C6Y
-u9hyLIIu4dFEBKyQHRvBnQSLNpKx6or1OGFDVBay2In9Yh2BHh1+vOj/OIz/wq48
-EHOIV27fRJxLu4jeK5LIGDhuPnMJ8AJYQ0bQOUP6fd7p+TxWkAQZPB/Dx/cs3hxr
-nFEdzx+eO+IAsObx/b1EGZyEJyETBslu4GwYX7/KK3HsJhDJ1bdZ//28jOCaoir6
-ZOMT72GRwmVoQTJ0XpccfjHfKJDRLT7C1xvzo4Eibth0hpTZkA75IUYUp6qK/PuJ
-kH/qdiC7QIkRKtsrawW4vEDna3YtxIYhQqz9+KwO6u/0gzooZtv1RU4U3ifMDB5u
-5P5GAzACRqlY8QYBkM869lvWqzQPHvybC4ak9Yx6/heMO9ddjdIW9BaK8BLxvN/6
-UCD936Y4fWltt09jHZIoxWFykouBwmd7bXooNYXmDRNmjTdVhKJuOEOQw8hDzx7e
-pWFJ9Z/V4Qm1tvXbCD7QFqMCDoY3qFvVG8DBqXpmxe1yPfz21FWrT7IuqDXAD3ns
-vxfN/2a+Cy04U9FBNVCvWqWIs5AgNpdCMJC2FlXKTy+H3/7rIjNyFyvbX0vxIXtK
-liOVNXiyVM++KZXqktqMUDlsJENmIHV9B046luqbgW018fHkyEYlL3iRZGbYegwr
-XO9VVIKVPw1BEvJ8VNdGFGuZGepd8qX2ezfYADrNR+4t85HDm8inbjTobSjWuljs
-ftUNkOeCHqAvWCFQTLCfdykvV08EJfVY79y7yFPtfRV2gxYokXFifjo3su9sVQr1
-UiIS5ZAsIC1hBXWeXoBN7QVTkFi7Yto6E1q2k10LiT3obpUUUQ/oclhrJOCJVjrS
-oRcj2QBy8OT4T9slJr5maTWdgd7Lt6+I6cGQXPaDvjGOJl0eBYM14vhx4rRQWytJ
-k07hhHFO4+9CGCuHS8AAy2gR6acYFWt2ZiiNZ0z/iPIHNK4YEyy9aLf6uZH/KQjE
-jmHToo7XD6QvCAEC5qTHby3o3LfHIhyZi/4L+AhS4FKUHF6M0peeyYt4z3HaK2d2
-N6mHLPdjwNjra7GOmcns4gzcrdfoF+R293KpPal4PjknvR3dZL4kKP/ougTAM5zv
-qDIvRbkHzjP8ChTpoLcJsNVXykNcNkjcSi0GHtIpYjh6QX6P2uvR/S4+Bbb9p9rn
-hIy/ovu9tWN2hiPxGPe6torF6BulAxsTYlDercC204AyzsrdA0pr6HBgJH9C6ML1
-TchwodbFJqn9rSv91i1liusAGoOvE81AGBdrXY7LxfSNhYY1IK6yR/POJPTd53sA
-uX2/j6Rtoksd/2BHPM6AUnI/2B9slhuzWX2aCtWLeuwvXDS6rYuTigaQmLkzTRfM
-dlMI3s9KLXxgi5YVumUZleJWXwBNP7KiKajd+VTSD+7WAhyhM5FIG5wVOaxmy4G2
-TyqZ/Ax9d2VEjTQHWvQlLPQ4Mp0EIz0aEl94K/S8CK8bJRH6+PRkar+dJi1xqlL+
-BYb42At9mEJ8odLlFikvNi1+t7jqXk5jRi5C0xFKx3nTtzoH2zNUeuA3R6vSocVK
-45jnze9IkKmxMlJ4loR5sgszdpDCD3kXqjtCcbMTmcrGyzJek3HSOTpiEORoTFOe
-Rhg6jH5lm+QcC263oipojS0qEQcnsWJP2CylNYMYHR9O/9NQxT3o2lsRHqZTMELV
-uQa/SFH+paQNbZOj8MRwPSqqiIxJFuLswKte1R+W7LKn1yBSM7Pp39lNbzGvJD2E
-YRfnCwFpJ54voVAuQ4jXJvigCW2qeCjXlxeD6K2j4eGJEEOmIjIW1wjubyBY6OI3
------END RSA PRIVATE KEY-----
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIHbTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIhD+rJdxqb6ECAggA
+MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBDTdyjCP3riOSUfxix4aXEvBIIH
+ECGkbsFabrcFMZcplw5jHMaOlG7rYjUzwDJ80JM8uzbv2Jb8SvNlns2+xmnEvH/M
+mNvRmnXmplbVjH3XBMK8o2Psnr2V/a0j7/pgqpRxHykG+koOY4gzdt3MAg8JPbS2
+hymSl+Y5EpciO3xLfz4aFL1ZNqspQbO/TD13Ij7DUIy7xIRBMp4taoZCrP0cEBAZ
++wgu9m23I4dh3E8RUBzWyFFNic2MVVHrui6JbHc4dIHfyKLtXJDhUcS0vIC9PvcV
+jhorh3UZC4lM+/jjXV5AhzQ0VrJ2tXAUX2dA144XHzkSH2QmwfnajPsci7BL2CGC
+rjyTy4NfB/lDwU+55dqJZQSKXMxAapJMrtgw7LD5CKQcN6zmfhXGssJ7HQUXKkaX
+I1YOFzuUD7oo56BVCnVswv0jX9RxrE5QYNreMlOP9cS+kIYH65N+PAhlURuQC14K
+PgDkHn5knSa2UQA5tc5f7zdHOZhGRUfcjLP+KAWA3nh+/2OKw/X3zuPx75YT/FKe
+tACPw5hjEpl62m9Xa0eWepZXwqkIOkzHMmCyNCsbC0mmRoEjmvfnslfsmnh4Dg/c
+4YsTYMOLLIeCa+WIc38aA5W2lNO9lW0LwLhX1rP+GRVPv+TVHXlfoyaI+jp0iXrJ
+t3xxT0gaiIR/VznyS7Py68QV/zB7VdqbsNzS7LdquHK1k8+7OYiWjY3gqyU40Iu2
+d1eSnIoDvQJwyYp7XYXbOlXNLY+s1Qb7yxcW3vXm0Bg3gKT8r1XHWJ9rj+CxAn5r
+ysfkPs1JsesxzzQjwTiDNvHnBnZnwxuxfBr26ektEHmuAXSl8V6dzLN/aaPjpTj4
+CkE7KyqX3U9bLkp+ztl4xWKEmW44nskzm0+iqrtrxMyTfvvID4QrABjZL4zmWIqc
+e3ZfA3AYk9VDIegk/YKGC5VZ8YS7ZXQ0ASK652XqJ7QlMKTxxV7zda6Fp4uW6/qN
+ezt5wgbGGhZQXj2wDQmWNQYyG/juIgYTpCUA54U5XBIjuR6pg+Ytm0UrvNjsUoAC
+wGelyqaLDq8U8jdIFYVTJy9aJjQOYXjsUJ0dZN2aGHSlju0ZGIZc49cTIVQ9BTC5
+Yc0Vlwzpl+LuA25DzKZNSb/ci0lO/cQGJ2uXQQgaNgdsHlu8nukENGJhnIzx4fzK
+wEh3yHxhTRCzPPwDfXmx0IHXrPqJhSpAgaXBVIm8OjvmMxO+W75W4uLfNY/B7e2H
+3cjklGuvkofOf7sEOrGUYf4cb6Obg8FpvHgpKo5Twwmoh/qvEKckBFqNhZXDDl88
+GbGlSEgyaAV1Ig8s1NJKBolWFa0juyPAwJ8vT1T4iwW7kQ7KXKt2UNn96K/HxkLu
+pikvukz8oRHMlfVHa0R48UB1fFHwZLzPmwkpu6ancIxk3uO3yfhf6iDk3bmnyMlz
+g3k/b6MrLYaOVByRxay85jH3Vvgqfgn6wa6BJ7xQ81eZ8B45gFuTH0J5JtLL7SH8
+darRPLCYfA+Ums9/H6pU5EXfd3yfjMIbvhCXHkJrrljkZ+th3p8dyto6wmYqIY6I
+qR9sU+o6DhRaiP8tCICuhHxQpXylUM6WeJkJwduTJ8KWIvzsj4mReIKOl/oC2jSd
+gIdKhb9Q3zj9ce4N5m6v66tyvjxGZ+xf3BvUPDD+LwZeXgf7OBsNVbXzQbzto594
+nbCzPocFi3gERE50ru4K70eQCy08TPG5NpOz+DDdO5vpAuMLYEuI7O3L+3GjW40Q
+G5bu7H5/i7o/RWR67qhG/7p9kPw3nkUtYgnvnWaPMIuTfb4c2d069kjlfgWjIbbI
+tpSKmm5DHlqTE4/ECAbIEDtSaw9dXHCdL3nh5+n428xDdGbjN4lT86tfu17EYKzl
+ydH1RJ1LX3o3TEj9UkmDPt7LnftvwybMFEcP7hM2xD4lC++wKQs7Alg6dTkBnJV4
+5xU78WRntJkJTU7kFkpPKA0QfyCuSF1fAMoukDBkqUdOj6jE0BlJQlHk5iwgnJlt
+uEdkTjHZEjIUxWC6llPcAzaPNlmnD45AgfEW+Jn21IvutmJiQAz5lm9Z9PXaR0C8
+hXB6owRY67C0YKQwXhoNf6xQun2xGBGYy5rPEEezX1S1tUH5GR/KW1Lh+FzFqHXI
+ZEb5avfDqHKehGAjPON+Br7akuQ125M9LLjKuSyPaQzeeCAy356Xd7XzVwbPddbm
+9S9WSPqzaPgh10chIHoNoC8HMd33dB5j9/Q6jrbU/oPlptu/GlorWblvJdcTuBGI
+IVn45RFnkG8hCz0GJSNzW7+70YdESQbfJW79vssWMaiSjFE0pMyFXrFR5lBywBTx
+PiGEUWtvrKG94X1TMlGUzDzDJOQNZ9dT94bonNe9pVmP5BP4/DzwwiWh6qrzWk6p
+j8OE4cfCSh2WvHnhJbH7/N0v+JKjtxeIeJ16jx/K2oK5
+-----END ENCRYPTED PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIEWTCCAsGgAwIBAgIJAJinz4jHSjLtMA0GCSqGSIb3DQEBCwUAMF8xCzAJBgNV
BAYTAlhZMRcwFQYDVQQHDA5DYXN0bGUgQW50aHJheDEjMCEGA1UECgwaUHl0aG9u
9Wc2uXpw9xF8itV4Uvcdr3dwqByvIqn7iI/gB+4l41e0u8OmH2MKOx4Nxlly5TNW
HcVKQHyOeyvnINuBAQ==
-----END CERTIFICATE-----
+
group.add_argument('--junit-xml', dest='xmlpath', metavar='FILENAME',
help='writes JUnit-style XML results to the specified '
'file')
- group.add_argument('--tempdir', dest='tempdir', metavar='PATH',
+ group.add_argument('--tempdir', metavar='PATH',
help='override the working directory for the test run')
+ group.add_argument('--cleanup', action='store_true',
+ help='remove old test_python_* directories')
return parser
from test.libregrtest.runtest import (
findtests, runtest, get_abs_module,
STDTESTS, NOTTESTS, PASSED, FAILED, ENV_CHANGED, SKIPPED, RESOURCE_DENIED,
- INTERRUPTED, CHILD_ERROR, TEST_DID_NOT_RUN,
+ INTERRUPTED, CHILD_ERROR, TEST_DID_NOT_RUN, TIMEOUT,
PROGRESS_MIN_TIME, format_test_result, is_failed)
from test.libregrtest.setup import setup_tests
from test.libregrtest.utils import removepy, count, format_duration, printlist
from test import support
+# bpo-38203: Maximum delay in seconds to exit Python (call Py_Finalize()).
+# Used to protect against threading._shutdown() hang.
+# Must be smaller than buildbot "1200 seconds without output" limit.
+EXIT_TIMEOUT = 120.0
+
+
class Regrtest:
"""Execute a test suite.
self.run_no_tests.append(test_name)
elif ok == INTERRUPTED:
self.interrupted = True
+ elif ok == TIMEOUT:
+ self.bad.append(test_name)
else:
raise ValueError("invalid test result: %r" % ok)
def parse_args(self, kwargs):
ns = _parse_args(sys.argv[1:], **kwargs)
- if ns.timeout and not hasattr(faulthandler, 'dump_traceback_later'):
- print("Warning: The timeout option requires "
- "faulthandler.dump_traceback_later", file=sys.stderr)
- ns.timeout = None
-
if ns.xmlpath:
support.junit_xml_list = self.testsuite_xml = []
# Strip .py extensions.
removepy(ns.args)
- return ns
+ if ns.huntrleaks:
+ warmup, repetitions, _ = ns.huntrleaks
+ if warmup < 1 or repetitions < 1:
+ msg = ("Invalid values for the --huntrleaks/-R parameters. The "
+ "number of warmups and repetitions must be at least 1 "
+ "each (1:1).")
+ print(msg, file=sys.stderr, flush=True)
+ sys.exit(2)
+
+ if ns.tempdir:
+ ns.tempdir = os.path.expanduser(ns.tempdir)
+
+ self.ns = ns
def find_tests(self, tests):
self.tests = tests
self.run_tests_sequential()
def finalize(self):
- if self.win_load_tracker is not None:
- self.win_load_tracker.close()
- self.win_load_tracker = None
-
if self.next_single_filename:
if self.next_single_test:
with open(self.next_single_filename, 'w') as fp:
for s in ET.tostringlist(root):
f.write(s)
- def create_temp_dir(self):
+ def set_temp_dir(self):
if self.ns.tempdir:
self.tmp_dir = self.ns.tempdir
self.tmp_dir = tempfile.gettempdir()
self.tmp_dir = os.path.abspath(self.tmp_dir)
+
+ def create_temp_dir(self):
os.makedirs(self.tmp_dir, exist_ok=True)
# Define a writable temp dir that will be used as cwd while running
# testing (see the -j option).
pid = os.getpid()
if self.worker_test_name is not None:
- test_cwd = 'worker_{}'.format(pid)
+ test_cwd = 'test_python_worker_{}'.format(pid)
else:
test_cwd = 'test_python_{}'.format(pid)
test_cwd = os.path.join(self.tmp_dir, test_cwd)
return test_cwd
+ def cleanup(self):
+ import glob
+
+ path = os.path.join(self.tmp_dir, 'test_python_*')
+ print("Cleanup %s directory" % self.tmp_dir)
+ for name in glob.glob(path):
+ if os.path.isdir(name):
+ print("Remove directory: %s" % name)
+ support.rmtree(name)
+ else:
+ print("Remove file: %s" % name)
+ support.unlink(name)
+
def main(self, tests=None, **kwargs):
- self.ns = self.parse_args(kwargs)
+ self.parse_args(kwargs)
+
+ self.set_temp_dir()
+
+ if self.ns.cleanup:
+ self.cleanup()
+ sys.exit(0)
test_cwd = self.create_temp_dir()
- # Run the tests in a context manager that temporarily changes the CWD
- # to a temporary and writable directory. If it's not possible to
- # create or change the CWD, the original CWD will be used.
- # The original CWD is available from support.SAVEDCWD.
- with support.temp_cwd(test_cwd, quiet=True):
- # When using multiprocessing, worker processes will use test_cwd
- # as their parent temporary directory. So when the main process
- # exit, it removes also subdirectories of worker processes.
- self.ns.tempdir = test_cwd
- self._main(tests, kwargs)
+ try:
+ # Run the tests in a context manager that temporarily changes the CWD
+ # to a temporary and writable directory. If it's not possible to
+ # create or change the CWD, the original CWD will be used.
+ # The original CWD is available from support.SAVEDCWD.
+ with support.temp_cwd(test_cwd, quiet=True):
+ # When using multiprocessing, worker processes will use test_cwd
+ # as their parent temporary directory. So when the main process
+ # exit, it removes also subdirectories of worker processes.
+ self.ns.tempdir = test_cwd
+
+ self._main(tests, kwargs)
+ except SystemExit as exc:
+ # bpo-38203: Python can hang at exit in Py_Finalize(), especially
+ # on threading._shutdown() call: put a timeout
+ faulthandler.dump_traceback_later(EXIT_TIMEOUT, exit=True)
+
+ sys.exit(exc.code)
def getloadavg(self):
if self.win_load_tracker is not None:
return None
def _main(self, tests, kwargs):
- if self.ns.huntrleaks:
- warmup, repetitions, _ = self.ns.huntrleaks
- if warmup < 1 or repetitions < 1:
- msg = ("Invalid values for the --huntrleaks/-R parameters. The "
- "number of warmups and repetitions must be at least 1 "
- "each (1:1).")
- print(msg, file=sys.stderr, flush=True)
- sys.exit(2)
-
if self.worker_test_name is not None:
from test.libregrtest.runtest_mp import run_tests_worker
run_tests_worker(self.ns, self.worker_test_name)
# typeperf.exe for x64, x86 or ARM
print(f'Failed to create WindowsLoadTracker: {error}')
- self.run_tests()
- self.display_result()
+ try:
+ self.run_tests()
+ self.display_result()
- if self.ns.verbose2 and self.bad:
- self.rerun_failed_tests()
+ if self.ns.verbose2 and self.bad:
+ self.rerun_failed_tests()
+ finally:
+ if self.win_load_tracker is not None:
+ self.win_load_tracker.close()
+ self.win_load_tracker = None
self.finalize()
from test import support
from test.libregrtest.refleak import dash_R, clear_caches
from test.libregrtest.save_env import saved_test_environment
-from test.libregrtest.utils import print_warning
+from test.libregrtest.utils import format_duration, print_warning
# Test result constants.
INTERRUPTED = -4
CHILD_ERROR = -5 # error in a child process
TEST_DID_NOT_RUN = -6
+TIMEOUT = -7
_FORMAT_TEST_RESULT = {
PASSED: '%s passed',
INTERRUPTED: '%s interrupted',
CHILD_ERROR: '%s crashed',
TEST_DID_NOT_RUN: '%s run no tests',
+ TIMEOUT: '%s timed out',
}
# Minimum duration of a test to display its duration or to mention that
def format_test_result(result):
fmt = _FORMAT_TEST_RESULT.get(result.result, "%s")
- return fmt % result.test_name
+ text = fmt % result.test_name
+ if result.result == TIMEOUT:
+ text = '%s (%s)' % (text, format_duration(result.test_time))
+ return text
def findtestdir(path=None):
FAILED test failed
PASSED test passed
EMPTY_TEST_SUITE test ran no subtests.
+ TIMEOUT test timed out.
If ns.xmlpath is not None, xml_data is a list containing each
generated testsuite element.
from test.libregrtest.runtest import (
runtest, INTERRUPTED, CHILD_ERROR, PROGRESS_MIN_TIME,
- format_test_result, TestResult, is_failed)
+ format_test_result, TestResult, is_failed, TIMEOUT)
from test.libregrtest.setup import setup_tests
-from test.libregrtest.utils import format_duration
+from test.libregrtest.utils import format_duration, print_warning
# Display the running tests if nothing happened last N seconds
PROGRESS_UPDATE = 30.0 # seconds
+assert PROGRESS_UPDATE >= PROGRESS_MIN_TIME
# Time to wait until a worker completes: should be immediate
JOIN_TIMEOUT = 30.0 # seconds
pass
-class MultiprocessThread(threading.Thread):
- def __init__(self, pending, output, ns):
+class TestWorkerProcess(threading.Thread):
+ def __init__(self, worker_id, pending, output, ns, timeout):
super().__init__()
+ self.worker_id = worker_id
self.pending = pending
self.output = output
self.ns = ns
+ self.timeout = timeout
self.current_test_name = None
self.start_time = None
self._popen = None
self._killed = False
+ self._stopped = False
def __repr__(self):
- info = ['MultiprocessThread']
- test = self.current_test_name
+ info = [f'TestWorkerProcess #{self.worker_id}']
if self.is_alive():
- info.append('alive')
+ dt = time.monotonic() - self.start_time
+ info.append("running for %s" % format_duration(dt))
+ else:
+ info.append('stopped')
+ test = self.current_test_name
if test:
info.append(f'test={test}')
popen = self._popen
info.append(f'pid={popen.pid}')
return '<%s>' % ' '.join(info)
- def kill(self):
+ def _kill(self):
+ if self._killed:
+ return
self._killed = True
popen = self._popen
if popen is None:
return
- popen.kill()
- # stdout and stderr must be closed to ensure that communicate()
- # does not hang
- popen.stdout.close()
- popen.stderr.close()
- def _runtest(self, test_name):
+ print(f"Kill {self}", file=sys.stderr, flush=True)
try:
- self.start_time = time.monotonic()
- self.current_test_name = test_name
+ popen.kill()
+ except OSError as exc:
+ print_warning(f"Failed to kill {self}: {exc!r}")
+
+ def stop(self):
+ # Method called from a different thread to stop this thread
+ self._stopped = True
+ self._kill()
+
+ def mp_result_error(self, test_name, error_type, stdout='', stderr='',
+ err_msg=None):
+ test_time = time.monotonic() - self.start_time
+ result = TestResult(test_name, error_type, test_time, None)
+ return MultiprocessResult(result, stdout, stderr, err_msg)
+ def _timedout(self, test_name):
+ self._kill()
+
+ stdout = stderr = ''
+ popen = self._popen
+ try:
+ stdout, stderr = popen.communicate(timeout=JOIN_TIMEOUT)
+ except (subprocess.TimeoutExpired, OSError) as exc:
+ print_warning(f"Failed to read {self} output "
+ f"(timeout={format_duration(JOIN_TIMEOUT)}): "
+ f"{exc!r}")
+
+ return self.mp_result_error(test_name, TIMEOUT, stdout, stderr)
+
+ def _run_process(self, test_name):
+ self.start_time = time.monotonic()
+
+ self.current_test_name = test_name
+ try:
+ self._killed = False
self._popen = run_test_in_subprocess(test_name, self.ns)
popen = self._popen
- with popen:
- try:
- if self._killed:
- # If kill() has been called before self._popen is set,
- # self._popen is still running. Call again kill()
- # to ensure that the process is killed.
- self.kill()
- raise ExitThread
-
- try:
- stdout, stderr = popen.communicate()
- except OSError:
- if self._killed:
- # kill() has been called: communicate() fails
- # on reading closed stdout/stderr
- raise ExitThread
- raise
- except:
- self.kill()
- popen.wait()
- raise
-
- retcode = popen.wait()
- finally:
+ except:
self.current_test_name = None
+ raise
+
+ try:
+ if self._stopped:
+ # If kill() has been called before self._popen is set,
+ # self._popen is still running. Call again kill()
+ # to ensure that the process is killed.
+ self._kill()
+ raise ExitThread
+
+ try:
+ stdout, stderr = popen.communicate(timeout=self.timeout)
+ except subprocess.TimeoutExpired:
+ if self._stopped:
+ # kill() has been called: communicate() fails
+ # on reading closed stdout/stderr
+ raise ExitThread
+
+ return self._timedout(test_name)
+ except OSError:
+ if self._stopped:
+ # kill() has been called: communicate() fails
+ # on reading closed stdout/stderr
+ raise ExitThread
+ raise
+
+ retcode = popen.returncode
+ stdout = stdout.strip()
+ stderr = stderr.rstrip()
+
+ return (retcode, stdout, stderr)
+ except:
+ self._kill()
+ raise
+ finally:
+ self._wait_completed()
self._popen = None
+ self.current_test_name = None
+
+ def _runtest(self, test_name):
+ result = self._run_process(test_name)
- stdout = stdout.strip()
- stderr = stderr.rstrip()
+ if isinstance(result, MultiprocessResult):
+ # _timedout() case
+ return result
+
+ retcode, stdout, stderr = result
err_msg = None
if retcode != 0:
err_msg = "Failed to parse worker JSON: %s" % exc
if err_msg is not None:
- test_time = time.monotonic() - self.start_time
- result = TestResult(test_name, CHILD_ERROR, test_time, None)
+ return self.mp_result_error(test_name, CHILD_ERROR, stdout, stderr, err_msg)
return MultiprocessResult(result, stdout, stderr, err_msg)
def run(self):
- while not self._killed:
+ while not self._stopped:
try:
try:
test_name = next(self.pending)
self.output.put((True, traceback.format_exc()))
break
+ def _wait_completed(self):
+ popen = self._popen
+
+ # stdout and stderr must be closed to ensure that communicate()
+ # does not hang
+ popen.stdout.close()
+ popen.stderr.close()
+
+ try:
+ popen.wait(JOIN_TIMEOUT)
+ except (subprocess.TimeoutExpired, OSError) as exc:
+ print_warning(f"Failed to wait for {self} completion "
+ f"(timeout={format_duration(JOIN_TIMEOUT)}): "
+ f"{exc!r}")
+
+ def wait_stopped(self, start_time):
+ while True:
+ # Write a message every second
+ self.join(1.0)
+ if not self.is_alive():
+ break
+ dt = time.monotonic() - start_time
+ print(f"Waiting for {self} thread for {format_duration(dt)}", flush=True)
+ if dt > JOIN_TIMEOUT:
+ print_warning(f"Failed to join {self} in {format_duration(dt)}")
+ break
+
def get_running(workers):
running = []
return running
-class MultiprocessRunner:
+class MultiprocessTestRunner:
def __init__(self, regrtest):
self.regrtest = regrtest
self.ns = regrtest.ns
self.output = queue.Queue()
self.pending = MultiprocessIterator(self.regrtest.tests)
if self.ns.timeout is not None:
- self.test_timeout = self.ns.timeout * 1.5
+ self.worker_timeout = self.ns.timeout * 1.5
else:
- self.test_timeout = None
+ self.worker_timeout = None
self.workers = None
def start_workers(self):
- self.workers = [MultiprocessThread(self.pending, self.output, self.ns)
- for _ in range(self.ns.use_mp)]
+ self.workers = [TestWorkerProcess(index, self.pending, self.output,
+ self.ns, self.worker_timeout)
+ for index in range(1, self.ns.use_mp + 1)]
print("Run tests in parallel using %s child processes"
% len(self.workers))
for worker in self.workers:
worker.start()
- def wait_workers(self):
+ def stop_workers(self):
start_time = time.monotonic()
for worker in self.workers:
- worker.kill()
+ worker.stop()
for worker in self.workers:
- while True:
- worker.join(1.0)
- if not worker.is_alive():
- break
- dt = time.monotonic() - start_time
- print("Wait for regrtest worker %r for %.1f sec" % (worker, dt))
- if dt > JOIN_TIMEOUT:
- print("Warning -- failed to join a regrtest worker %s"
- % worker)
- break
+ worker.wait_stopped(start_time)
def _get_result(self):
if not any(worker.is_alive() for worker in self.workers):
except queue.Empty:
return None
+ use_faulthandler = (self.ns.timeout is not None)
+ timeout = PROGRESS_UPDATE
while True:
- if self.test_timeout is not None:
- faulthandler.dump_traceback_later(self.test_timeout, exit=True)
+ if use_faulthandler:
+ faulthandler.dump_traceback_later(timeout * 2.0, exit=True)
# wait for a thread
- timeout = max(PROGRESS_UPDATE, PROGRESS_MIN_TIME)
try:
return self.output.get(timeout=timeout)
except queue.Empty:
print()
self.regrtest.interrupted = True
finally:
- if self.test_timeout is not None:
+ if self.ns.timeout is not None:
faulthandler.cancel_dump_traceback_later()
- # a test failed (and --failfast is set) or all tests completed
- self.pending.stop()
- self.wait_workers()
+ # Always ensure that all worker processes are no longer
+ # worker when we exit this function
+ self.pending.stop()
+ self.stop_workers()
def run_tests_multiprocess(regrtest):
- MultiprocessRunner(regrtest).run_tests()
+ MultiprocessTestRunner(regrtest).run_tests()
import os
import subprocess
import uuid
+import winreg
from test import support
+from test.libregrtest.utils import print_warning
# Max size of asynchronous reads
BUFSIZE = 8192
# Exponential damping factor (see below)
LOAD_FACTOR_1 = 0.9200444146293232478931553241
+
# Seconds per measurement
SAMPLING_INTERVAL = 5
-COUNTER_NAME = r'\System\Processor Queue Length'
+# Windows registry subkey of HKEY_LOCAL_MACHINE where the counter names
+# of typeperf are registered
+COUNTER_REGISTRY_KEY = (r"SOFTWARE\Microsoft\Windows NT\CurrentVersion"
+ r"\Perflib\CurrentLanguage")
class WindowsLoadTracker():
"""
This class asynchronously interacts with the `typeperf` command to read
- the system load on Windows. Mulitprocessing and threads can't be used
+ the system load on Windows. Multiprocessing and threads can't be used
here because they interfere with the test suite's cases for those
modules.
"""
def __init__(self):
self.load = 0.0
+ self.counter_name = ''
+ self.popen = None
self.start()
def start(self):
overlap.GetOverlappedResult(True)
# Spawn off the load monitor
- command = ['typeperf', COUNTER_NAME, '-si', str(SAMPLING_INTERVAL)]
- self.p = subprocess.Popen(command, stdout=command_stdout, cwd=support.SAVEDCWD)
+ counter_name = self._get_counter_name()
+ command = ['typeperf', counter_name, '-si', str(SAMPLING_INTERVAL)]
+ self.popen = subprocess.Popen(' '.join(command), stdout=command_stdout, cwd=support.SAVEDCWD)
# Close our copy of the write end of the pipe
os.close(command_stdout)
+ def _get_counter_name(self):
+ # accessing the registry to get the counter localization name
+ with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, COUNTER_REGISTRY_KEY) as perfkey:
+ counters = winreg.QueryValueEx(perfkey, 'Counter')[0]
+
+ # Convert [key1, value1, key2, value2, ...] list
+ # to {key1: value1, key2: value2, ...} dict
+ counters = iter(counters)
+ counters_dict = dict(zip(counters, counters))
+
+ # System counter has key '2' and Processor Queue Length has key '44'
+ system = counters_dict['2']
+ process_queue_length = counters_dict['44']
+ return f'"\\{system}\\{process_queue_length}"'
+
def close(self):
- if self.p is None:
+ if self.popen is None:
return
- self.p.kill()
- self.p.wait()
- self.p = None
+ self.popen.kill()
+ self.popen.wait()
+ self.popen = None
def __del__(self):
self.close()
def read_output(self):
- import _winapi
-
overlapped, _ = _winapi.ReadFile(self.pipe, BUFSIZE, True)
bytes_read, res = overlapped.GetOverlappedResult(False)
if res != 0:
return
- return overlapped.getbuffer().decode()
+ output = overlapped.getbuffer()
+ return output.decode('oem', 'replace')
def getloadavg(self):
typeperf_output = self.read_output()
# Process the backlog of load values
for line in typeperf_output.splitlines():
+ # Ignore the initial header:
+ # "(PDH-CSV 4.0)","\\\\WIN\\System\\Processor Queue Length"
+ if '\\\\' in line:
+ continue
+
+ # Ignore blank lines
+ if not line.strip():
+ continue
+
# typeperf outputs in a CSV format like this:
# "07/19/2018 01:32:26.605","3.000000"
- toks = line.split(',')
- # Ignore blank lines and the initial header
- if line.strip() == '' or (COUNTER_NAME in line) or len(toks) != 2:
+ # (date, process queue length)
+ try:
+ tokens = line.split(',')
+ if len(tokens) != 2:
+ raise ValueError
+
+ value = tokens[1].replace('"', '')
+ load = float(value)
+ except ValueError:
+ print_warning("Failed to parse typeperf output: %a" % line)
continue
- load = float(toks[1].replace('"', ''))
# We use an exponentially weighted moving average, imitating the
# load calculation on Unix systems.
# https://en.wikipedia.org/wiki/Load_(computing)#Unix-style_load_calculation
with open('ssl_key.pem', 'w') as f:
f.write(key)
print("password protecting ssl_key.pem in ssl_key.passwd.pem")
- check_call(['openssl','rsa','-in','ssl_key.pem','-out','ssl_key.passwd.pem','-des3','-passout','pass:somepass'])
- check_call(['openssl','rsa','-in','ssl_key.pem','-out','keycert.passwd.pem','-des3','-passout','pass:somepass'])
+ check_call(['openssl','pkey','-in','ssl_key.pem','-out','ssl_key.passwd.pem','-aes256','-passout','pass:somepass'])
+ check_call(['openssl','pkey','-in','ssl_key.pem','-out','keycert.passwd.pem','-aes256','-passout','pass:somepass'])
with open('keycert.pem', 'w') as f:
f.write(key)
------BEGIN RSA PRIVATE KEY-----
-Proc-Type: 4,ENCRYPTED
-DEK-Info: DES-EDE3-CBC,8064BE1494B24B13
-
-KJrffOMbo8M0I3PzcYxRZGMpKD1yB3Ii4+bT5XoanxjIJ+4fdx6LfZ0Rsx+riyzs
-tymsQu/iYY9j+4rCvN9+eetsL1X6iZpiimKsLexcid9M3fb0vxED5Sgw0dvunCUA
-xhqjLIKR92MKbODHf6KrDKCpsiPbjq4gZ7P+uCGXAMHL3MXIJSC0hW9rK7Ce6oyO
-CjpIcgB8x+GUWZZZhAFdlzIHMZrteNP2P5HK6QcaT71P034Dz1hhqoj4Q0t+Fta2
-4tfsM/bnTR/l6hwlhPa1e3Uj322tDTDWBScgWANn5+sEWldLmozMaWhZsn22pfk2
-KjRMGXG024JVheV882nbdOBvG7oq+lxkZ/ZP+vvqJqnvYtf7WtM8UivzYpe5Hz5b
-kVvWzPjBLUSZ9whM9rDLqSSqMPyPvDTuEmLkuq+xm7pYJmsLqIMP2klZLqRxLX6K
-uqwplb8UG440qauxgnQ905PId1l2fJEnRtV+7vXprA0L0QotgXLVHBhLmTFM+3PH
-9H3onf31dionUAPrn3nfVE36HhvVgRyvDBnBzJSIMighgq21Qx/d1dk0DRYi1hUI
-nCHl0YJPXheVcXR7JiSF2XQCAaFuS1Mr7NCXfWZOZQC/0dkvmHnl9DUAhuqq9BNZ
-1cKhZXcKHadg2/r0Zup/oDzmHPUEfTAXT0xbqoWlhkdwbF2veWQ96A/ncx3ISTb4
-PkXBlX9rdia8nmtyQDQRn4NuvchbaGkj4WKFC8pF8Hn7naHqwjpHaDUimBc0CoQW
-edNJqruKWwtSVLuwKHCC2gZFX9AXSKJXJz/QRSUlhFGOhuF/J6yKaXj6n5lxWNiQ
-54J+OP/hz2aS95CD2+Zf1SKpxdWiLZSIQqESpmmUrXROixNJZ/Z7gI74Dd9dSJOH
-W+3AU03vrrFZVrJVZhjcINHoH1Skh6JKscH18L6x4U868nSr4SrRLX8BhHllOQyD
-bmU+PZAjF8ZBIaCtTGulDXD29F73MeAZeTSsgQjFu0iKLj1wPiphbx8i/SUtR4YP
-X6PVA04g66r1NBw+3RQASVorZ3g1MSFvITHXcbKkBDeJH2z1+c6t/VVyTONnQhM5
-lLgRSk6HCbetvT9PKxWrWutA12pdBYEHdZhMHVf2+xclky7l09w8hg2/qqcdGRGe
-oAOZ72t0l5ObNyaruDKUS6f4AjOyWq/Xj5xuFtf1n3tQHyslSyCTPcAbQhDfTHUx
-vixb/V9qvYPt7OCn8py7v1M69NH42QVFAvwveDIFjZdqfIKBoJK2V4qPoevJI6uj
-Q5ByMt8OXOjSXNpHXpYQWUiWeCwOEBXJX8rzCHdMtg37jJ0zCmeErR1NTdg+EujM
-TWYgd06jlT67tURST0aB2kg4ijKgUJefD313LW1zC6gVsTbjSZxYyRbPfSP6flQB
-yCi1C19E2OsgleqbkBVC5GlYUzaJT7SGjCRmGx1eqtbrALu+LVH24Wceexlpjydl
-+s2nf/DZlKun/tlPh6YioifPCJjByZMQOCEfIox6BkemZETz8uYA4TTWimG13Z03
-gyDGC2jdpEW414J2qcQDvrdUgJ+HlhrAAHaWpMQDbXYxBGoZ+3+ORvQV4kAsCwL8
-k3EIrVpePdik+1xgOWsyLj6QxFXlTMvL6Wc5pnArFPORsgHEolJvxSPTf9aAHNPn
-V2WBvxiLBtYpGrujAUM40Syx/aN2RPtcXYPAusHUBw+S8/p+/8Kg8GZmnIXG3F89
-45Eepl2quZYIrou7a1fwIpIIZ0hFiBQ1mlHVMFtxwVHS1bQb3SU2GeO+JcGjdVXc
-04qeGuQ5M164eQ5C0T7ZQ1ULiUlFWKD30m+cjqmZzt3d7Q0mKpMKuESIuZJo/wpD
-Nas432aLKUhcNx/pOYLkKJRpGZKOupQoD5iUj/j44o8JoFkDK33v2S57XB5QGz28
-9Zuhx49b3W8mbM6EBanlQKLWJGCxXqc/jhYhFWn+b0MhidynFgA0oeWvf6ZDyt6H
-Yi5Etxsar09xp0Do3NxtQXLuSUu0ji2pQzSIKuoqQWKqldm6VrpwojiqJhy4WQBQ
-aVVyFeWBC7G3Zj76dO+yp2sfJ0itJUQ8AIB9Cg0f34rEZu+r9luPmqBoUeL95Tk7
-YvCOU3Jl8Iqysv8aNpVXT8sa8rrSbruWCByEePZ37RIdHLMVBwVY0eVaFQjrjU7E
-mXmM9eaoYLfXOllsQ+M2+qPFUITr/GU3Qig13DhK/+yC1R6V2a0l0WRhMltIPYKW
-Ztvvr4hK5LcYCeS113BLiMbDIMMZZYGDZGMdC8DnnVbT2loF0Rfmp80Af31KmMQ4
-6XvMatW9UDjBoY5a/YMpdm7SRwm+MgV2KNPpc2kST87/yi9oprGAb8qiarHiHTM0
------END RSA PRIVATE KEY-----
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIHbTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQI072N7W+PDDMCAggA
+MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBA/AuaRNi4vE4KGqI4In+70BIIH
+ENGS5Vex5NID873frmd1UZEHZ+O/Bd0wDb+NUpIqesHkRYf7kKi6Gnr+nKQ/oVVn
+Lm3JjE7c8ECP0OkOOXmiXuWL1SkzBBWqCI4stSGUPvBiHsGwNnvJAaGjUffgMlcC
+aJOA2+dnejLkzblq4CB2LQdm06N3Xoe9tyqtQaUHxfzJAf5Ydd8uj7vpKN2MMhY7
+icIPJwSyh0N7S6XWVtHEokr9Kp4y2hS5a+BgCWV1/1z0aF7agnSVndmT1VR+nWmc
+lM14k+lethmHMB+fsNSjnqeJ7XOPlOTHqhiZ9bBSTgF/xr5Bck/NiKRzHjdovBox
+TKg+xchaBhpRh7wBPBIlNJeHmIjv+8obOKjKU98Ig/7R9+IryZaNcKAH0PuOT+Sw
+QHXiCGQbOiYHB9UyhDTWiB7YVjd8KHefOFxfHzOQb/iBhbv1x3bTl3DgepvRN6VO
+dIsPLoIZe42sdf9GeMsk8mGJyZUQ6AzsfhWk3grb/XscizPSvrNsJ2VL1R7YTyT3
+3WA4ZXR1EqvXnWL7N/raemQjy62iOG6t7fcF5IdP9CMbWP+Plpsz4cQW7FtesCTq
+a5ZXraochQz361ODFNIeBEGU+0qqXUtZDlmos/EySkZykSeU/L0bImS62VGE3afo
+YXBmznTTT9kkFkqv7H0MerfJsrE/wF8puP3GM01DW2JRgXRpSWlvbPV/2LnMtRuD
+II7iH4rWDtTjCN6BWKAgDOnPkc9sZ4XulqT32lcUeV6LTdMBfq8kMEc8eDij1vUT
+maVCRpuwaq8EIT3lVgNLufHiG96ojlyYtj3orzw22IjkgC/9ee8UDik9CqbMVmFf
+fVHhsw8LNSg8Q4bmwm5Eg2w2it2gtI68+mwr75oCxuJ/8OMjW21Prj8XDh5reie2
+c0lDKQOFZ9UnLU1bXR/6qUM+JFKR4DMq+fOCuoQSVoyVUEOsJpvBOYnYZN9cxsZm
+vh9dKafMEcKZ8flsbr+gOmOw7+Py2ifSlf25E/Frb1W4gtbTb0LQVHb6+drutrZj
+8HEu4CnHYFCD4ZnOJb26XlZCb8GFBddW86yJYyUqMMV6Q1aJfAOAglsTo1LjIMOZ
+byo0BTAmwUevU/iuOXQ4qRBXXcoidDcTCrxfUSPG9wdt9l+m5SdQpWqfQ+fx5O7m
+SLlrHyZCiPSFMtC9DxqjIklHjf5W3wslGLgaD30YXa4VDYkRihf3CNsxGQ+tVvef
+l0ZjoAitF7Gaua06IESmKnpHe23dkr1cjYq+u2IV+xGH8LeExdwsQ9kpuTeXPnQs
+JOA99SsFx1ct32RrwjxnDDsiNkaViTKo9GDkV3jQTfoFgAVqfSgg9wGXpqUqhNG7
+TiSIHCowllLny2zn4XrXCy2niD3VDt0skb3l/PaegHE2z7S5YY85nQtYwpLiwB9M
+SQ08DYKxPBZYKtS2iZ/fsA1gjSRQDPg/SIxMhUC3M3qH8iWny1Lzl25F2Uq7VVEX
+LdTUtaby49jRTT3CQGr5n6z7bMbUegiY7h8WmOekuThGDH+4xZp6+rDP4GFk4FeK
+JcF70vMQYIjQZhadic6olv+9VtUP42ltGG/yP9a3eWRkzfAf2eCh6B1rYdgEWwE8
+rlcZzwM+y6eUmeNF2FVWB8iWtTMQHy+dYNPM+Jtus1KQKxiiq/yCRs7nWvzWRFWA
+HRyqV0J6/lqgm4FvfktFt1T0W+mDoLJOR2/zIwMy2lgL5zeHuR3SaMJnCikJbqKS
+HB3UvrhAWUcZqdH29+FhVWeM7ybyF1Wccmf+IIC/ePLa6gjtqPV8lG/5kbpcpnB6
+UQY8WWaKMxyr3jJ9bAX5QKshchp04cDecOLZrpFGNNQngR8RxSEkiIgAqNxWunIu
+KrdBDrupv/XAgEOclmgToY3iywLJSV5gHAyHWDUhRH4cFCLiGPl4XIcnXOuTze3H
+3j+EYSiS3v3DhHjp33YU2pXlJDjiYsKzAXejEh66++Y8qaQdCAad3ruWRCzW3kgk
+Md0A1VGzntTnQsewvExQEMZH2LtYIsPv3KCYGeSAuLabX4tbGk79PswjnjLLEOr0
+Ghf6RF6qf5/iFyJoG4vrbKT8kx6ywh0InILCdjUunuDskIBxX6tEcr9XwajoIvb2
+kcmGdjam5kKLS7QOWQTl8/r/cuFes0dj34cX5Qpq+Gd7tRq/D+b0207926Cxvftv
+qQ1cVn8HiLxKkZzd3tpf2xnoV1zkTL0oHrNg+qzxoxXUTUcwtIf1d/HRbYEAhi/d
+bBBoFeftEHWNq+sJgS9bH+XNzo/yK4u04B5miOq8v4CSkJdzu+ZdF22d4cjiGmtQ
+8BTmcn0Unzm+u5H0+QSZe54QBHJGNXXOIKMTkgnOdW27g4DbI1y7fCqJiSMbRW6L
+oHmMfbdB3GWqGbsUkhY8i6h9op0MU6WOX7ea2Rxyt4t6
+-----END ENCRYPTED PRIVATE KEY-----
"run_with_locale", "swap_item",
"swap_attr", "Matcher", "set_memlimit", "SuppressCrashReport", "sortdict",
"run_with_tz", "PGO", "missing_compiler_executable", "fd_count",
+ "ALWAYS_EQ", "LARGEST", "SMALLEST"
]
class Error(Exception):
# bpo-31910: socket.create_connection() fails randomly
# with EADDRNOTAVAIL on Travis CI
errors.append(errno.EADDRNOTAVAIL)
+ if hasattr(errno, 'EHOSTUNREACH'):
+ # bpo-37583: The destination host cannot be reached
+ errors.append(errno.EHOSTUNREACH)
return errors
if sys.platform.startswith(('linux', 'freebsd')):
try:
names = os.listdir("/proc/self/fd")
- # Substract one because listdir() opens internally a file
+ # Subtract one because listdir() internally opens a file
# descriptor to list the content of the /proc/self/fd/ directory.
return len(names) - 1
except FileNotFoundError:
raise self.path
else:
return self.path
+
+
+class _ALWAYS_EQ:
+ """
+ Object that is equal to anything.
+ """
+ def __eq__(self, other):
+ return True
+ def __ne__(self, other):
+ return False
+
+ALWAYS_EQ = _ALWAYS_EQ()
+
+@functools.total_ordering
+class _LARGEST:
+ """
+ Object that is greater than anything (except itself).
+ """
+ def __eq__(self, other):
+ return isinstance(other, _LARGEST)
+ def __lt__(self, other):
+ return False
+
+LARGEST = _LARGEST()
+
+@functools.total_ordering
+class _SMALLEST:
+ """
+ Object that is less than anything (except itself).
+ """
+ def __eq__(self, other):
+ return isinstance(other, _SMALLEST)
+ def __gt__(self, other):
+ return False
+
+SMALLEST = _SMALLEST()
-c c help
'''
+class TestMutuallyExclusiveNested(MEMixin, TestCase):
+
+ def get_parser(self, required):
+ parser = ErrorRaisingArgumentParser(prog='PROG')
+ group = parser.add_mutually_exclusive_group(required=required)
+ group.add_argument('-a')
+ group.add_argument('-b')
+ group2 = group.add_mutually_exclusive_group(required=required)
+ group2.add_argument('-c')
+ group2.add_argument('-d')
+ group3 = group2.add_mutually_exclusive_group(required=required)
+ group3.add_argument('-e')
+ group3.add_argument('-f')
+ return parser
+
+ usage_when_not_required = '''\
+ usage: PROG [-h] [-a A | -b B | [-c C | -d D | [-e E | -f F]]]
+ '''
+ usage_when_required = '''\
+ usage: PROG [-h] (-a A | -b B | (-c C | -d D | (-e E | -f F)))
+ '''
+
+ help = '''\
+
+ optional arguments:
+ -h, --help show this help message and exit
+ -a A
+ -b B
+ -c C
+ -d D
+ -e E
+ -f F
+ '''
+
+ # We are only interested in testing the behavior of format_usage().
+ test_failures_when_not_required = None
+ test_failures_when_required = None
+ test_successes_when_not_required = None
+ test_successes_when_required = None
+
# =================================================
# Mutually exclusive group in parent parser tests
# =================================================
import sys
import unittest
import weakref
+from textwrap import dedent
from test import support
"lineno=1, col_offset=0), lineno=1, col_offset=0)])"
)
+ def test_dump_incomplete(self):
+ node = ast.Raise(lineno=3, col_offset=4)
+ self.assertEqual(ast.dump(node),
+ "Raise()"
+ )
+ self.assertEqual(ast.dump(node, include_attributes=True),
+ "Raise(lineno=3, col_offset=4)"
+ )
+ node = ast.Raise(exc=ast.Name(id='e', ctx=ast.Load()), lineno=3, col_offset=4)
+ self.assertEqual(ast.dump(node),
+ "Raise(exc=Name(id='e', ctx=Load()))"
+ )
+ self.assertEqual(ast.dump(node, annotate_fields=False),
+ "Raise(Name('e', Load()))"
+ )
+ self.assertEqual(ast.dump(node, include_attributes=True),
+ "Raise(exc=Name(id='e', ctx=Load()), lineno=3, col_offset=4)"
+ )
+ self.assertEqual(ast.dump(node, annotate_fields=False, include_attributes=True),
+ "Raise(Name('e', Load()), lineno=3, col_offset=4)"
+ )
+ node = ast.Raise(cause=ast.Name(id='e', ctx=ast.Load()))
+ self.assertEqual(ast.dump(node),
+ "Raise(cause=Name(id='e', ctx=Load()))"
+ )
+ self.assertEqual(ast.dump(node, annotate_fields=False),
+ "Raise(cause=Name('e', Load()))"
+ )
+
def test_copy_location(self):
src = ast.parse('1 + 1', mode='eval')
src.body.right = ast.copy_location(ast.Num(2), src.body.right)
self.assertEqual(ast.literal_eval(binop), 10+20j)
+class NodeVisitorTests(unittest.TestCase):
+ def test_old_constant_nodes(self):
+ class Visitor(ast.NodeVisitor):
+ def visit_Num(self, node):
+ log.append((node.lineno, 'Num', node.n))
+ def visit_Str(self, node):
+ log.append((node.lineno, 'Str', node.s))
+ def visit_Bytes(self, node):
+ log.append((node.lineno, 'Bytes', node.s))
+ def visit_NameConstant(self, node):
+ log.append((node.lineno, 'NameConstant', node.value))
+ def visit_Ellipsis(self, node):
+ log.append((node.lineno, 'Ellipsis', ...))
+ mod = ast.parse(dedent('''\
+ i = 42
+ f = 4.25
+ c = 4.25j
+ s = 'string'
+ b = b'bytes'
+ t = True
+ n = None
+ e = ...
+ '''))
+ visitor = Visitor()
+ log = []
+ visitor.visit(mod)
+ self.assertEqual(log, [
+ (1, 'Num', 42),
+ (2, 'Num', 4.25),
+ (3, 'Num', 4.25j),
+ (4, 'Str', 'string'),
+ (5, 'Bytes', b'bytes'),
+ (6, 'NameConstant', True),
+ (7, 'NameConstant', None),
+ (8, 'Ellipsis', ...),
+ ])
+
+
def main():
if __name__ != '__main__':
return
res = self.loop.run_until_complete(run())
self.assertEqual(res, [i * 2 for i in range(1, 10)])
+ def test_asyncgen_nonstarted_hooks_are_cancellable(self):
+ # See https://bugs.python.org/issue38013
+ messages = []
+
+ def exception_handler(loop, context):
+ messages.append(context)
+
+ async def async_iterate():
+ yield 1
+ yield 2
+
+ async def main():
+ loop = asyncio.get_running_loop()
+ loop.set_exception_handler(exception_handler)
+
+ async for i in async_iterate():
+ break
+
+ asyncio.run(main())
+
+ self.assertEqual([], messages)
+
if __name__ == "__main__":
unittest.main()
@mock.patch('os.read')
def test_resume_reading(self, m_read):
tr = self.read_pipe_transport()
+ tr.pause_reading()
tr.resume_reading()
self.loop.assert_reader(5, tr._read_ready)
self.assertIsNone(tr._protocol)
self.assertIsNone(tr._loop)
+ def test_pause_reading_on_closed_pipe(self):
+ tr = self.read_pipe_transport()
+ tr.close()
+ test_utils.run_briefly(self.loop)
+ self.assertIsNone(tr._loop)
+ tr.pause_reading()
+
+ def test_pause_reading_on_paused_pipe(self):
+ tr = self.read_pipe_transport()
+ tr.pause_reading()
+ # the second call should do nothing
+ tr.pause_reading()
+
+ def test_resume_reading_on_closed_pipe(self):
+ tr = self.read_pipe_transport()
+ tr.close()
+ test_utils.run_briefly(self.loop)
+ self.assertIsNone(tr._loop)
+ tr.resume_reading()
+
+ def test_resume_reading_on_paused_pipe(self):
+ tr = self.read_pipe_transport()
+ # the pipe is not paused
+ # resuming should do nothing
+ tr.resume_reading()
+
class UnixWritePipeTransportTests(test_utils.TestCase):
self.assertRaises(TypeError, __import__, 1, 2, 3, 4)
self.assertRaises(ValueError, __import__, '')
self.assertRaises(TypeError, __import__, 'sys', name='sys')
+ # Relative import outside of a package with no __package__ or __spec__ (bpo-37409).
+ with self.assertWarns(ImportWarning):
+ self.assertRaises(ImportError, __import__, '',
+ {'__package__': None, '__spec__': None, '__name__': '__main__'},
+ locals={}, fromlist=('foo',), level=1)
# embedded null character
self.assertRaises(ModuleNotFoundError, __import__, 'string\x00')
self.assertRaises(ValueError, x.translate, b"1", 1)
self.assertRaises(TypeError, x.translate, b"1"*256, 1)
+ def test_bytearray_extend_error(self):
+ array = bytearray()
+ bad_iter = map(int, "X")
+ self.assertRaises(ValueError, array.extend, bad_iter)
+
def test_construct_singletons(self):
for const in None, Ellipsis, NotImplemented:
tp = type(const)
class EncodingDetails(_EncodingDetails):
# XXX (ncoghlan): Using JSON for child state reporting may be less fragile
CHILD_PROCESS_SCRIPT = ";".join([
- "import sys, os",
- "print(sys.getfilesystemencoding())",
- "print(sys.stdin.encoding + ':' + sys.stdin.errors)",
- "print(sys.stdout.encoding + ':' + sys.stdout.errors)",
- "print(sys.stderr.encoding + ':' + sys.stderr.errors)",
+ "import sys, os, codecs",
+ "print(codecs.lookup(sys.getfilesystemencoding()).name)",
+ "print(codecs.lookup(sys.stdin.encoding).name + ':' + sys.stdin.errors)",
+ "print(codecs.lookup(sys.stdout.encoding).name + ':' + sys.stdout.errors)",
+ "print(codecs.lookup(sys.stderr.encoding).name + ':' + sys.stderr.errors)",
"print(os.environ.get('LANG', 'not set'))",
"print(os.environ.get('LC_CTYPE', 'not set'))",
"print(os.environ.get('LC_ALL', 'not set'))",
stream_info = 2*[_stream.format("surrogateescape")]
# stderr should always use backslashreplace
stream_info.append(_stream.format("backslashreplace"))
- expected_lang = env_vars.get("LANG", "not set").lower()
+ expected_lang = env_vars.get("LANG", "not set")
if coercion_expected:
- expected_lc_ctype = CLI_COERCION_TARGET.lower()
+ expected_lc_ctype = CLI_COERCION_TARGET
else:
- expected_lc_ctype = env_vars.get("LC_CTYPE", "not set").lower()
- expected_lc_all = env_vars.get("LC_ALL", "not set").lower()
+ expected_lc_ctype = env_vars.get("LC_CTYPE", "not set")
+ expected_lc_all = env_vars.get("LC_ALL", "not set")
env_info = expected_lang, expected_lc_ctype, expected_lc_all
return dict(cls(fs_encoding, *stream_info, *env_info)._asdict())
- @staticmethod
- def _handle_output_variations(data):
- """Adjust the output to handle platform specific idiosyncrasies
-
- * Some platforms report ASCII as ANSI_X3.4-1968
- * Some platforms report ASCII as US-ASCII
- * Some platforms report UTF-8 instead of utf-8
- """
- data = data.replace(b"ANSI_X3.4-1968", b"ascii")
- data = data.replace(b"US-ASCII", b"ascii")
- data = data.lower()
- return data
-
@classmethod
def get_child_details(cls, env_vars):
"""Retrieves fsencoding and standard stream details from a child process
if not result.rc == 0:
result.fail(py_cmd)
# All subprocess outputs in this test case should be pure ASCII
- adjusted_output = cls._handle_output_variations(result.out)
- stdout_lines = adjusted_output.decode("ascii").splitlines()
+ stdout_lines = result.out.decode("ascii").splitlines()
child_encoding_details = dict(cls(*stdout_lines)._asdict())
stderr_lines = result.err.decode("ascii").rstrip().splitlines()
return child_encoding_details, stderr_lines
self.assertEqual(fs.list[0].name, 'submit-name')
self.assertEqual(fs.list[0].value, 'Larry')
+ def test_field_storage_multipart_no_content_length(self):
+ fp = BytesIO(b"""--MyBoundary
+Content-Disposition: form-data; name="my-arg"; filename="foo"
+
+Test
+
+--MyBoundary--
+""")
+ env = {
+ "REQUEST_METHOD": "POST",
+ "CONTENT_TYPE": "multipart/form-data; boundary=MyBoundary",
+ "wsgi.input": fp,
+ }
+ fields = cgi.FieldStorage(fp, environ=env)
+
+ self.assertEqual(len(fields["my-arg"].file.read()), 5)
+
def test_fieldstorage_as_context_manager(self):
fp = BytesIO(b'x' * 10)
env = {'REQUEST_METHOD': 'PUT'}
self.assertEqual(codec.name, 'mbcs')
@support.bigmemtest(size=2**31, memuse=7, dry_run=False)
- def test_large_input(self):
+ def test_large_input(self, size):
# Test input longer than INT_MAX.
# Input should contain undecodable bytes before and after
# the INT_MAX limit.
- encoded = (b'01234567' * (2**28-1) +
+ encoded = (b'01234567' * ((size//8)-1) +
b'\x85\x86\xea\xeb\xec\xef\xfc\xfd\xfe\xff')
- self.assertEqual(len(encoded), 2**31+2)
+ self.assertEqual(len(encoded), size+2)
decoded = codecs.code_page_decode(932, encoded, 'surrogateescape', True)
self.assertEqual(decoded[1], len(encoded))
del encoded
'\udc85\udc86\udcea\udceb\udcec'
'\udcef\udcfc\udcfd\udcfe\udcff')
+ @support.bigmemtest(size=2**31, memuse=6, dry_run=False)
+ def test_large_utf8_input(self, size):
+ # Test input longer than INT_MAX.
+ # Input should contain a decodable multi-byte character
+ # surrounding INT_MAX
+ encoded = (b'0123456\xed\x84\x80' * (size//8))
+ self.assertEqual(len(encoded), size // 8 * 10)
+ decoded = codecs.code_page_decode(65001, encoded, 'ignore', True)
+ self.assertEqual(decoded[1], len(encoded))
+ del encoded
+ self.assertEqual(len(decoded[0]), size)
+ self.assertEqual(decoded[0][:10], '0123456\ud10001')
+ self.assertEqual(decoded[0][-11:], '56\ud1000123456\ud100')
+
class ASCIITest(unittest.TestCase):
def test_encode(self):
self.assertTrue(is_dataclass(d.d))
self.assertFalse(is_dataclass(d.e))
+ def test_is_dataclass_when_getattr_always_returns(self):
+ # See bpo-37868.
+ class A:
+ def __getattr__(self, key):
+ return 0
+ self.assertFalse(is_dataclass(A))
+ a = A()
+
+ # Also test for an instance attribute.
+ class B:
+ pass
+ b = B()
+ b.__dataclass_fields__ = []
+
+ for obj in a, b:
+ with self.subTest(obj=obj):
+ self.assertFalse(is_dataclass(obj))
+
+ # Indirect tests for _is_dataclass_instance().
+ with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'):
+ asdict(obj)
+ with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'):
+ astuple(obj)
+ with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'):
+ replace(obj, x=0)
+
def test_helper_fields_with_class_instance(self):
# Check that we can call fields() on either a class or instance,
# and get back the same thing.
def test_non_identifier_field_names(self):
for field in ['()', 'x,y', '*', '2@3', '', 'little johnny tables']:
with self.subTest(field=field):
- with self.assertRaisesRegex(TypeError, 'must be valid identifers'):
+ with self.assertRaisesRegex(TypeError, 'must be valid identifiers'):
make_dataclass('C', ['a', field])
- with self.assertRaisesRegex(TypeError, 'must be valid identifers'):
+ with self.assertRaisesRegex(TypeError, 'must be valid identifiers'):
make_dataclass('C', [field])
- with self.assertRaisesRegex(TypeError, 'must be valid identifers'):
+ with self.assertRaisesRegex(TypeError, 'must be valid identifiers'):
make_dataclass('C', [field, 'a'])
def test_underscore_field_names(self):
self.assertEqual(Sub.test(), Base.aProp)
# Verify that super() doesn't allow keyword args
- try:
+ with self.assertRaises(TypeError):
super(Base, kw=1)
- except TypeError:
- pass
- else:
- self.assertEqual("super shouldn't accept keyword args")
def test_basic_inheritance(self):
# Testing inheritance from basic types...
from xmlrpc.server import DocXMLRPCServer
import http.client
+import re
import sys
import threading
from test import support
b'method_annotation</strong></a>(x: bytes)</dt></dl>'),
response.read())
+ def test_server_title_escape(self):
+ # bpo-38243: Ensure that the server title and documentation
+ # are escaped for HTML.
+ self.serv.set_server_title('test_title<script>')
+ self.serv.set_server_documentation('test_documentation<script>')
+ self.assertEqual('test_title<script>', self.serv.server_title)
+ self.assertEqual('test_documentation<script>',
+ self.serv.server_documentation)
+
+ generated = self.serv.generate_html_documentation()
+ title = re.search(r'<title>(.+?)</title>', generated).group()
+ documentation = re.search(r'<p><tt>(.+?)</tt></p>', generated).group()
+ self.assertEqual('<title>Python: test_title<script></title>', title)
+ self.assertEqual('<p><tt>test_documentation<script></tt></p>', documentation)
+
if __name__ == '__main__':
unittest.main()
print()
print("--- run eintr_tester.py ---", flush=True)
# In verbose mode, the child process inherit stdout and stdout,
- # to see output in realtime and reduce the risk of loosing output.
+ # to see output in realtime and reduce the risk of losing output.
args = [sys.executable, "-E", "-X", "faulthandler", *args]
proc = subprocess.run(args)
print(f"--- eintr_tester.py completed: "
[errors.InvalidHeaderDefect],
'')
+ def test_get_unstructured_without_trailing_whitespace_hang_case(self):
+ self._test_get_x(self._get_unst,
+ '=?utf-8?q?somevalue?=aa',
+ 'somevalueaa',
+ 'somevalueaa',
+ [errors.InvalidHeaderDefect],
+ '')
+
+ def test_get_unstructured_invalid_ew(self):
+ self._test_get_x(self._get_unst,
+ '=?utf-8?q?=somevalue?=',
+ '=?utf-8?q?=somevalue?=',
+ '=?utf-8?q?=somevalue?=',
+ [],
+ '')
+
# get_qp_ctext
def test_get_qp_ctext_only(self):
self._test_get_x(parser.get_bare_quoted_string,
'""', '""', '', [], '')
+ def test_get_bare_quoted_string_missing_endquotes(self):
+ self._test_get_x(parser.get_bare_quoted_string,
+ '"', '""', '', [errors.InvalidHeaderDefect], '')
+
def test_get_bare_quoted_string_following_wsp_preserved(self):
self._test_get_x(parser.get_bare_quoted_string,
'"foo"\t bar', '"foo"', 'foo', [], '\t bar')
self.assertEqual(word.token_type, 'atom')
self.assertEqual(word[0].token_type, 'cfws')
+ def test_get_word_all_CFWS(self):
+ # bpo-29412: Test that we don't raise IndexError when parsing CFWS only
+ # token.
+ with self.assertRaises(errors.HeaderParseError):
+ parser.get_word('(Recipients list suppressed')
+
def test_get_word_qs_yields_qs(self):
word = self._test_get_x(parser.get_word,
'"bar " (bang) ah', '"bar " (bang) ', 'bar ', [], 'ah')
self.assertEqual(addr_spec.domain, 'example.com')
self.assertEqual(addr_spec.addr_spec, 'star.a.star@example.com')
+ def test_get_addr_spec_multiple_domains(self):
+ with self.assertRaises(errors.HeaderParseError):
+ parser.get_addr_spec('star@a.star@example.com')
+
+ with self.assertRaises(errors.HeaderParseError):
+ parser.get_addr_spec('star@a@example.com')
+
+ with self.assertRaises(errors.HeaderParseError):
+ parser.get_addr_spec('star@172.17.0.1@example.com')
+
# get_obs_route
def test_get_obs_route_simple(self):
self.assertEqual(display_name[3].comments, ['with trailing comment'])
self.assertEqual(display_name.display_name, 'simple phrase.')
+ def test_get_display_name_for_invalid_address_field(self):
+ # bpo-32178: Test that address fields starting with `:` don't cause
+ # IndexError when parsing the display name.
+ display_name = self._test_get_x(
+ parser.get_display_name,
+ ':Foo ', '', '', [errors.InvalidHeaderDefect], ':Foo ')
+ self.assertEqual(display_name.value, '')
+
# get_name_addr
def test_get_name_addr_angle_addr_only(self):
# get_address_list
+ def test_get_address_list_CFWS(self):
+ address_list = self._test_get_x(parser.get_address_list,
+ '(Recipient list suppressed)',
+ '(Recipient list suppressed)',
+ ' ',
+ [errors.ObsoleteHeaderDefect], # no content in address list
+ '')
+ self.assertEqual(address_list.token_type, 'address-list')
+ self.assertEqual(len(address_list.mailboxes), 0)
+ self.assertEqual(address_list.mailboxes, address_list.all_mailboxes)
+
def test_get_address_list_mailboxes_simple(self):
address_list = self._test_get_x(parser.get_address_list,
'dinsdale@example.com',
# Defects are apparent missing *0*, and two 'out of sequence'.
[errors.InvalidHeaderDefect]*3),
+ # bpo-37461: Check that we don't go into an infinite loop.
+ 'extra_dquote': (
+ 'r*="\'a\'\\"',
+ ' r="\\""',
+ 'r*=\'a\'"',
+ [('r', '"')],
+ [errors.InvalidHeaderDefect]*2),
}
@parameterize
self.assertEqual(utils.parseaddr('<>'), ('', ''))
self.assertEqual(utils.formataddr(utils.parseaddr('<>')), '')
+ def test_parseaddr_multiple_domains(self):
+ self.assertEqual(
+ utils.parseaddr('a@b@c'),
+ ('', '')
+ )
+ self.assertEqual(
+ utils.parseaddr('a@b.c@c'),
+ ('', '')
+ )
+ self.assertEqual(
+ utils.parseaddr('a@172.17.0.1@c'),
+ ('', '')
+ )
+
def test_noquote_dump(self):
self.assertEqual(
utils.formataddr(('A Silly Person', 'person@dom.ain')),
eq(language, 'en-us')
eq(s, 'My Document For You')
+ def test_should_not_hang_on_invalid_ew_messages(self):
+ messages = ["""From: user@host.com
+To: user@host.com
+Bad-Header:
+ =?us-ascii?Q?LCSwrV11+IB0rSbSker+M9vWR7wEDSuGqmHD89Gt=ea0nJFSaiz4vX3XMJPT4vrE?=
+ =?us-ascii?Q?xGUZeOnp0o22pLBB7CYLH74Js=wOlK6Tfru2U47qR?=
+ =?us-ascii?Q?72OfyEY2p2=2FrA9xNFyvH+fBTCmazxwzF8nGkK6D?=
+
+Hello!
+""", """From: ����� �������� <xxx@xxx>
+To: "xxx" <xxx@xxx>
+Subject: ��� ���������� ����� ����� � ��������� �� ����
+MIME-Version: 1.0
+Content-Type: text/plain; charset="windows-1251";
+Content-Transfer-Encoding: 8bit
+
+�� ����� � ���� ������ ��� ��������
+"""]
+ for m in messages:
+ with self.subTest(m=m):
+ msg = email.message_from_string(m)
# Tests to ensure that signed parts of an email are completely preserved, as
class TestFolding(TestHeaderBase):
+ def test_address_display_names(self):
+ """Test the folding and encoding of address headers."""
+ for name, result in (
+ ('Foo Bar, France', '"Foo Bar, France"'),
+ ('Foo Bar (France)', '"Foo Bar (France)"'),
+ ('Foo Bar, España', 'Foo =?utf-8?q?Bar=2C_Espa=C3=B1a?='),
+ ('Foo Bar (España)', 'Foo Bar =?utf-8?b?KEVzcGHDsWEp?='),
+ ('Foo, Bar España', '=?utf-8?q?Foo=2C_Bar_Espa=C3=B1a?='),
+ ('Foo, Bar [España]', '=?utf-8?q?Foo=2C_Bar_=5BEspa=C3=B1a=5D?='),
+ ('Foo Bär, France', 'Foo =?utf-8?q?B=C3=A4r=2C?= France'),
+ ('Foo Bär <France>', 'Foo =?utf-8?q?B=C3=A4r_=3CFrance=3E?='),
+ (
+ 'Lôrem ipsum dôlôr sit amet, cônsectetuer adipiscing. '
+ 'Suspendisse pôtenti. Aliquam nibh. Suspendisse pôtenti.',
+ '=?utf-8?q?L=C3=B4rem_ipsum_d=C3=B4l=C3=B4r_sit_amet=2C_c'
+ '=C3=B4nsectetuer?=\n =?utf-8?q?adipiscing=2E_Suspendisse'
+ '_p=C3=B4tenti=2E_Aliquam_nibh=2E?=\n Suspendisse =?utf-8'
+ '?q?p=C3=B4tenti=2E?=',
+ ),
+ ):
+ h = self.make_header('To', Address(name, addr_spec='a@b.com'))
+ self.assertEqual(h.fold(policy=policy.default),
+ 'To: %s <a@b.com>\n' % result)
+
def test_short_unstructured(self):
h = self.make_header('subject', 'this is a test')
self.assertEqual(h.fold(policy=policy.default),
m.set_content(content_manager=cm)
self.assertNotIn('MIME-Version', m)
+ def test_string_payload_with_multipart_content_type(self):
+ msg = message_from_string(textwrap.dedent("""\
+ Content-Type: multipart/mixed; charset="utf-8"
+
+ sample text
+ """), policy=policy.default)
+ attachments = msg.iter_attachments()
+ self.assertEqual(list(attachments), [])
+
if __name__ == '__main__':
unittest.main()
import types
import textwrap
import unittest
+import email.errors
import email.policy
import email.parser
import email.generator
'Subject: \n' +
12 * ' =?utf-8?q?=C4=85?=\n')
+ def test_short_maxlen_error(self):
+ # RFC 2047 chrome takes up 7 characters, plus the length of the charset
+ # name, so folding should fail if maxlen is lower than the minimum
+ # required length for a line.
+
+ # Note: This is only triggered when there is a single word longer than
+ # max_line_length, hence the 1234567890 at the end of this whimsical
+ # subject. This is because when we encounter a word longer than
+ # max_line_length, it is broken down into encoded words to fit
+ # max_line_length. If the max_line_length isn't large enough to even
+ # contain the RFC 2047 chrome (`?=<charset>?q??=`), we fail.
+ subject = "Melt away the pounds with this one simple trick! 1234567890"
+
+ for maxlen in [3, 7, 9]:
+ with self.subTest(maxlen=maxlen):
+ policy = email.policy.default.clone(max_line_length=maxlen)
+ with self.assertRaises(email.errors.HeaderParseError):
+ policy.fold("Subject", subject)
+
# XXX: Need subclassing tests.
# For adding subclassed objects, make sure the usual rules apply (subclass
# wins), but that the order still works (right overrides left).
elif script:
args += [script]
- # print args
- # print (' '.join(args))
-
# Use "args" to invoke gdb, capturing stdout, stderr:
out, err = run_gdb(*args, PYTHONHASHSEED=PYTHONHASHSEED)
- errlines = err.splitlines()
- unexpected_errlines = []
-
- # Ignore some benign messages on stderr.
- ignore_patterns = (
- 'Function "%s" not defined.' % breakpoint,
- 'Do you need "set solib-search-path" or '
- '"set sysroot"?',
- # BFD: /usr/lib/debug/(...): unable to initialize decompress
- # status for section .debug_aranges
- 'BFD: ',
- # ignore all warnings
- 'warning: ',
- )
- for line in errlines:
- if not line:
- continue
- # bpo34007: Sometimes some versions of the shared libraries that
- # are part of the traceback are compiled in optimised mode and the
- # Program Counter (PC) is not present, not allowing gdb to walk the
- # frames back. When this happens, the Python bindings of gdb raise
- # an exception, making the test impossible to succeed.
- if "PC not saved" in line:
- raise unittest.SkipTest("gdb cannot walk the frame object"
- " because the Program Counter is"
- " not present")
- if not line.startswith(ignore_patterns):
- unexpected_errlines.append(line)
-
- # Ensure no unexpected error messages:
- self.assertEqual(unexpected_errlines, [])
+ for line in err.splitlines():
+ print(line, file=sys.stderr)
+
+ # bpo-34007: Sometimes some versions of the shared libraries that
+ # are part of the traceback are compiled in optimised mode and the
+ # Program Counter (PC) is not present, not allowing gdb to walk the
+ # frames back. When this happens, the Python bindings of gdb raise
+ # an exception, making the test impossible to succeed.
+ if "PC not saved" in err:
+ raise unittest.SkipTest("gdb cannot walk the frame object"
+ " because the Program Counter is"
+ " not present")
+
return out
def get_gdb_repr(self, source,
# gdb can insert additional '\n' and space characters in various places
# in its output, depending on the width of the terminal it's connected
# to (using its "wrap_here" function)
- m = re.match(r'.*#0\s+builtin_id\s+\(self\=.*,\s+v=\s*(.*?)\)\s+at\s+\S*Python/bltinmodule.c.*',
- gdb_output, re.DOTALL)
+ m = re.search(
+ # Match '#0 builtin_id(self=..., v=...)'
+ r'#0\s+builtin_id\s+\(self\=.*,\s+v=\s*(.*?)?\)'
+ # Match ' at Python/bltinmodule.c'.
+ # bpo-38239: builtin_id() is defined in Python/bltinmodule.c,
+ # but accept any "Directory\file.c" to support Link Time
+ # Optimization (LTO).
+ r'\s+at\s+\S*[A-Za-z]+/[A-Za-z0-9_-]+\.c',
+ gdb_output, re.DOTALL)
if not m:
self.fail('Unexpected gdb output: %r\n%s' % (gdb_output, gdb_output))
return m.group(1), gdb_output
import time
import unittest
import urllib.request
+import warnings
from http.cookiejar import (time2isoz, http2time, iso2time, time2netscape,
parse_ns_headers, join_header_words, split_header_words, Cookie,
# if expires is in future, keep cookie...
c = CookieJar()
future = time2netscape(time.time()+3600)
+
+ with warnings.catch_warnings(record=True) as warns:
+ headers = [f"Set-Cookie: FOO=BAR; path=/; expires={future}"]
+ req = urllib.request.Request("http://www.coyote.com/")
+ res = FakeResponse(headers, "http://www.coyote.com/")
+ cookies = c.make_cookies(res, req)
+ self.assertEqual(len(cookies), 1)
+ self.assertEqual(time2netscape(cookies[0].expires), future)
+ self.assertEqual(len(warns), 0)
+
interact_netscape(c, "http://www.acme.com/", 'spam="bar"; expires=%s' %
future)
self.assertEqual(len(c), 1)
thread.join()
self.assertEqual(result, b"proxied data\n")
+ def test_putrequest_override_validation(self):
+ """
+ It should be possible to override the default validation
+ behavior in putrequest (bpo-38216).
+ """
+ class UnsafeHTTPConnection(client.HTTPConnection):
+ def _validate_path(self, url):
+ pass
+
+ conn = UnsafeHTTPConnection('example.com')
+ conn.sock = FakeSocket('')
+ conn.putrequest('GET', '/\x00')
+
+ def test_putrequest_override_encoding(self):
+ """
+ It should be possible to override the default encoding
+ to transmit bytes in another encoding even if invalid
+ (bpo-36274).
+ """
+ class UnsafeHTTPConnection(client.HTTPConnection):
+ def _encode_request(self, str_url):
+ return str_url.encode('utf-8')
+
+ conn = UnsafeHTTPConnection('example.com')
+ conn.sock = FakeSocket('')
+ conn.putrequest('GET', '/☃')
+
+
class ExtendedReadTest(TestCase):
"""
Test peek(), read1(), readline()
p = self.resp.peek(0)
self.assertLessEqual(0, len(p))
+
class ExtendedReadTestChunked(ExtendedReadTest):
"""
Test peek(), read1(), readline() in chunked mode
ns = dict(__package__=object())
self.assertRaises(TypeError, check_relative)
+ def test_parentless_import_shadowed_by_global(self):
+ # Test as if this were done from the REPL where this error most commonly occurs (bpo-37409).
+ script_helper.assert_python_failure('-W', 'ignore', '-c',
+ "foo = 1; from . import foo")
+
def test_absolute_import_without_future(self):
# If explicit relative import syntax is used, then do not try
# to perform an absolute import in the face of failure.
def test_module_missing_spec(self):
#Test that reload() throws ModuleNotFounderror when reloading
- # a module who's missing a spec. (bpo-29851)
+ # a module whose missing a spec. (bpo-29851)
name = 'spam'
with test_util.uncache(name):
module = sys.modules[name] = types.ModuleType(name)
class MySignature(inspect.Signature): pass
def foo(a, *, b:1): pass
foo_sig = MySignature.from_callable(foo)
- self.assertTrue(isinstance(foo_sig, MySignature))
+ self.assertIsInstance(foo_sig, MySignature)
+
+ def test_signature_from_callable_class(self):
+ # A regression test for a class inheriting its signature from `object`.
+ class MySignature(inspect.Signature): pass
+ class foo: pass
+ foo_sig = MySignature.from_callable(foo)
+ self.assertIsInstance(foo_sig, MySignature)
@unittest.skipIf(MISSING_C_DOCSTRINGS,
"Signature information for builtins requires docstrings")
def test_signature_from_callable_builtin_obj(self):
class MySignature(inspect.Signature): pass
sig = MySignature.from_callable(_pickle.Pickler)
- self.assertTrue(isinstance(sig, MySignature))
+ self.assertIsInstance(sig, MySignature)
def test_signature_definition_order_preserved_on_kwonly(self):
for fn in signatures_with_lexicographic_keyword_only_parameters():
import pickle
import ipaddress
import weakref
+from test.support import LARGEST, SMALLEST
class BaseTestCase(unittest.TestCase):
"""Input validation on interfaces and networks is very similar"""
def test_no_mask(self):
- self.assertEqual(str(self.factory('1.2.3.4')), '1.2.3.4/32')
+ for address in ('1.2.3.4', 0x01020304, b'\x01\x02\x03\x04'):
+ net = self.factory(address)
+ self.assertEqual(str(net), '1.2.3.4/32')
+ self.assertEqual(str(net.netmask), '255.255.255.255')
+ self.assertEqual(str(net.hostmask), '0.0.0.0')
+ # IPv4Network has prefixlen, but IPv4Interface doesn't.
+ # Should we add it to IPv4Interface too? (bpo-36392)
def test_split_netmask(self):
addr = "1.2.3.4/32/24"
class NetmaskTestMixin_v6(CommonTestMixin_v6):
"""Input validation on interfaces and networks is very similar"""
+ def test_no_mask(self):
+ for address in ('::1', 1, b'\x00'*15 + b'\x01'):
+ net = self.factory(address)
+ self.assertEqual(str(net), '::1/128')
+ self.assertEqual(str(net.netmask), 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff')
+ self.assertEqual(str(net.hostmask), '::')
+ # IPv6Network has prefixlen, but IPv6Interface doesn't.
+ # Should we add it to IPv4Interface too? (bpo-36392)
+
def test_split_netmask(self):
addr = "cafe:cafe::/128/190"
with self.assertAddressError("Only one '/' permitted in %r" % addr):
self.assertFactoryError(ipaddress.ip_network, "network")
-@functools.total_ordering
-class LargestObject:
- def __eq__(self, other):
- return isinstance(other, LargestObject)
- def __lt__(self, other):
- return False
-
-@functools.total_ordering
-class SmallestObject:
- def __eq__(self, other):
- return isinstance(other, SmallestObject)
- def __gt__(self, other):
- return False
-
class ComparisonTests(unittest.TestCase):
v4addr = ipaddress.IPv4Address(1)
def test_foreign_type_ordering(self):
other = object()
- smallest = SmallestObject()
- largest = LargestObject()
for obj in self.objects:
with self.assertRaises(TypeError):
obj < other
obj <= other
with self.assertRaises(TypeError):
obj >= other
- self.assertTrue(obj < largest)
- self.assertFalse(obj > largest)
- self.assertTrue(obj <= largest)
- self.assertFalse(obj >= largest)
- self.assertFalse(obj < smallest)
- self.assertTrue(obj > smallest)
- self.assertFalse(obj <= smallest)
- self.assertTrue(obj >= smallest)
+ self.assertTrue(obj < LARGEST)
+ self.assertFalse(obj > LARGEST)
+ self.assertTrue(obj <= LARGEST)
+ self.assertFalse(obj >= LARGEST)
+ self.assertFalse(obj < SMALLEST)
+ self.assertTrue(obj > SMALLEST)
+ self.assertFalse(obj <= SMALLEST)
+ self.assertTrue(obj >= SMALLEST)
def test_mixed_type_key(self):
# with get_mixed_type_key, you can sort addresses and network.
from functools import reduce
import sys
import struct
+import threading
maxsize = support.MAX_Py_ssize_t
minsize = -maxsize-1
del forward, backward
raise
+ def test_tee_reenter(self):
+ class I:
+ first = True
+ def __iter__(self):
+ return self
+ def __next__(self):
+ first = self.first
+ self.first = False
+ if first:
+ return next(b)
+
+ a, b = tee(I())
+ with self.assertRaisesRegex(RuntimeError, "tee"):
+ next(a)
+
+ def test_tee_concurrent(self):
+ start = threading.Event()
+ finish = threading.Event()
+ class I:
+ def __iter__(self):
+ return self
+ def __next__(self):
+ start.set()
+ finish.wait()
+
+ a, b = tee(I())
+ thread = threading.Thread(target=next, args=[a])
+ thread.start()
+ try:
+ start.wait()
+ with self.assertRaisesRegex(RuntimeError, "tee"):
+ next(b)
+ finally:
+ finish.set()
+ thread.join()
+
def test_StopIteration(self):
self.assertRaises(StopIteration, next, zip())
def test_dumps(self):
self.assertEqual(self.dumps({}), '{}')
+ def test_dump_skipkeys(self):
+ v = {b'invalid_key': False, 'valid_key': True}
+ with self.assertRaises(TypeError):
+ self.json.dumps(v)
+
+ s = self.json.dumps(v, skipkeys=True)
+ o = self.json.loads(s)
+ self.assertIn('valid_key', o)
+ self.assertNotIn(b'invalid_key', o)
+
def test_encode_truefalse(self):
self.assertEqual(self.dumps(
{True: False, False: True}, sort_keys=True),
a[:] = data
self.assertEqual(list(it), [])
+ def test_step_overflow(self):
+ a = [0, 1, 2, 3, 4]
+ a[1::sys.maxsize] = [0]
+ self.assertEqual(a[3::sys.maxsize], [3])
+
def test_no_comdat_folding(self):
# Issue 8847: In the PGO build, the MSVC linker's COMDAT folding
# optimization causes failures in code that relies on distinct
class TestMiscellaneous(unittest.TestCase):
+ def test_defaults_UTF8(self):
+ # Issue #18378: on (at least) macOS setting LC_CTYPE to "UTF-8" is
+ # valid. Futhermore LC_CTYPE=UTF is used by the UTF-8 locale coercing
+ # during interpreter startup (on macOS).
+ import _locale
+ import os
+
+ self.assertEqual(locale._parse_localename('UTF-8'), (None, 'UTF-8'))
+
+ if hasattr(_locale, '_getdefaultlocale'):
+ orig_getlocale = _locale._getdefaultlocale
+ del _locale._getdefaultlocale
+ else:
+ orig_getlocale = None
+
+ orig_env = {}
+ try:
+ for key in ('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE'):
+ if key in os.environ:
+ orig_env[key] = os.environ[key]
+ del os.environ[key]
+
+ os.environ['LC_CTYPE'] = 'UTF-8'
+
+ self.assertEqual(locale.getdefaultlocale(), (None, 'UTF-8'))
+
+ finally:
+ for k in orig_env:
+ os.environ[k] = orig_env[k]
+
+ if 'LC_CTYPE' not in orig_env:
+ del os.environ['LC_CTYPE']
+
+ if orig_getlocale is not None:
+ _locale._getdefaultlocale = orig_getlocale
+
def test_getpreferredencoding(self):
# Invoke getpreferredencoding to make sure it does not cause exceptions.
enc = locale.getpreferredencoding()
logging.setLoggerClass(logging.Logger)
self.assertEqual(logging.getLoggerClass(), logging.Logger)
+ def test_subclass_logger_cache(self):
+ # bpo-37258
+ message = []
+
+ class MyLogger(logging.getLoggerClass()):
+ def __init__(self, name='MyLogger', level=logging.NOTSET):
+ super().__init__(name, level)
+ message.append('initialized')
+
+ logging.setLoggerClass(MyLogger)
+ logger = logging.getLogger('just_some_logger')
+ self.assertEqual(message, ['initialized'])
+ stream = io.StringIO()
+ h = logging.StreamHandler(stream)
+ logger.addHandler(h)
+ try:
+ logger.setLevel(logging.DEBUG)
+ logger.debug("hello")
+ self.assertEqual(stream.getvalue().strip(), "hello")
+
+ stream.truncate(0)
+ stream.seek(0)
+
+ logger.setLevel(logging.INFO)
+ logger.debug("hello")
+ self.assertEqual(stream.getvalue(), "")
+ finally:
+ logger.removeHandler(h)
+ h.close()
+ logging.setLoggerClass(logging.Logger)
+
@support.requires_type_collecting
def test_logging_at_shutdown(self):
# Issue #20037
logging._handlers.clear()
logging._handlers.update(self.saved_handlers)
logging._handlerList[:] = self.saved_handler_list
- logging.root.level = self.original_logging_level
+ logging.root.setLevel(self.original_logging_level)
def test_no_kwargs(self):
logging.basicConfig()
f.close()
self.assertRaises(ValueError, f.tell)
+ def test_issue21872(self):
+ # sometimes decompress data incompletely
+
+ # ---------------------
+ # when max_length == -1
+ # ---------------------
+ d1 = LZMADecompressor()
+ entire = d1.decompress(ISSUE_21872_DAT, max_length=-1)
+ self.assertEqual(len(entire), 13160)
+ self.assertTrue(d1.eof)
+
+ # ---------------------
+ # when max_length > 0
+ # ---------------------
+ d2 = LZMADecompressor()
+
+ # When this value of max_length is used, the input and output
+ # buffers are exhausted at the same time, and lzs's internal
+ # state still have 11 bytes can be output.
+ out1 = d2.decompress(ISSUE_21872_DAT, max_length=13149)
+ self.assertFalse(d2.needs_input) # ensure needs_input mechanism works
+ self.assertFalse(d2.eof)
+
+ # simulate needs_input mechanism
+ # output internal state's 11 bytes
+ out2 = d2.decompress(b'')
+ self.assertEqual(len(out2), 11)
+ self.assertTrue(d2.eof)
+ self.assertEqual(out1 + out2, entire)
+
class OpenTestCase(unittest.TestCase):
b"\x00"
)
+ISSUE_21872_DAT = (
+ b']\x00\x00@\x00h3\x00\x00\x00\x00\x00\x00\x00\x00`D\x0c\x99\xc8'
+ b'\xd1\xbbZ^\xc43+\x83\xcd\xf1\xc6g\xec-\x061F\xb1\xbb\xc7\x17%-\xea'
+ b'\xfap\xfb\x8fs\x128\xb2,\x88\xe4\xc0\x12|*x\xd0\xa2\xc4b\x1b!\x02c'
+ b'\xab\xd9\x87U\xb8n \xfaVJ\x9a"\xb78\xff%_\x17`?@*\xc2\x82'
+ b"\xf2^\x1b\xb8\x04&\xc0\xbb\x03g\x9d\xca\xe9\xa4\xc9\xaf'\xe5\x8e}"
+ b'F\xdd\x11\xf3\x86\xbe\x1fN\x95\\\xef\xa2Mz-\xcb\x9a\xe3O@'
+ b"\x19\x07\xf6\xee\x9e\x9ag\xc6\xa5w\rnG'\x99\xfd\xfeGI\xb0"
+ b'\xbb\xf9\xc2\xe1\xff\xc5r\xcf\x85y[\x01\xa1\xbd\xcc/\xa3\x1b\x83\xaa'
+ b'\xc6\xf9\x99\x0c\xb6_\xc9MQ+x\xa2F\xda]\xdd\xe8\xfb\x1a&'
+ b',\xc4\x19\x1df\x81\x1e\x90\xf3\xb8Hgr\x85v\xbe\xa3qx\x01Y\xb5\x9fF'
+ b"\x13\x18\x01\xe69\x9b\xc8'\x1e\x9d\xd6\xe4F\x84\xac\xf8d<\x11\xd5"
+ b'\\\x0b\xeb\x0e\x82\xab\xb1\xe6\x1fka\xe1i\xc4 C\xb1"4)\xd6\xa7`\x02'
+ b'\xec\x11\x8c\xf0\x14\xb0\x1d\x1c\xecy\xf0\xb7|\x11j\x85X\xb2!\x1c'
+ b'\xac\xb5N\xc7\x85j\x9ev\xf5\xe6\x0b\xc1]c\xc15\x16\x9f\xd5\x99'
+ b"\xfei^\xd2G\x9b\xbdl\xab:\xbe,\xa9'4\x82\xe5\xee\xb3\xc1"
+ b'$\x93\x95\xa8Y\x16\xf5\xbf\xacw\x91\x04\x1d\x18\x06\xe9\xc5\xfdk\x06'
+ b'\xe8\xfck\xc5\x86>\x8b~\xa4\xcb\xf1\xb3\x04\xf1\x04G5\xe2\xcc]'
+ b'\x16\xbf\x140d\x18\xe2\xedw#(3\xca\xa1\x80bX\x7f\xb3\x84'
+ b'\x9d\xdb\xe7\x08\x97\xcd\x16\xb9\xf1\xd5r+m\x1e\xcb3q\xc5\x9e\x92'
+ b"\x7f\x8e*\xc7\xde\xe9\xe26\xcds\xb1\x10-\xf6r\x02?\x9d\xddCgJN'"
+ b'\x11M\xfa\nQ\n\xe6`m\xb8N\xbbq\x8el\x0b\x02\xc7:q\x04G\xa1T'
+ b'\xf1\xfe!0\x85~\xe5\x884\xe9\x89\xfb\x13J8\x15\xe42\xb6\xad'
+ b'\x877A\x9a\xa6\xbft]\xd0\xe35M\xb0\x0cK\xc8\xf6\x88\xae\xed\xa9,j7'
+ b'\x81\x13\xa0(\xcb\xe1\xe9l2\x7f\xcd\xda\x95(\xa70B\xbd\xf4\xe3'
+ b'hp\x94\xbdJ\xd7\t\xc7g\xffo?\x89?\xf8}\x7f\xbc\x1c\x87'
+ b'\x14\xc0\xcf\x8cV:\x9a\x0e\xd0\xb2\x1ck\xffk\xb9\xe0=\xc7\x8d/'
+ b'\xb8\xff\x7f\x1d\x87`\x19.\x98X*~\xa7j\xb9\x0b"\xf4\xe4;V`\xb9\xd7'
+ b'\x03\x1e\xd0t0\xd3\xde\x1fd\xb9\xe2)\x16\x81}\xb1\\b\x7fJ'
+ b'\x92\xf4\xff\n+V!\xe9\xde\x98\xa0\x8fK\xdf7\xb9\xc0\x12\x1f\xe2'
+ b'\xe9\xb0`\xae\x14\r\xa7\xc4\x81~\xd8\x8d\xc5\x06\xd8m\xb0Y\x8a)'
+ b'\x06/\xbb\xf9\xac\xeaP\xe0\x91\x05m[\xe5z\xe6Z\xf3\x9f\xc7\xd0'
+ b'\xd3\x8b\xf3\x8a\x1b\xfa\xe4Pf\xbc0\x17\x10\xa9\xd0\x95J{\xb3\xc3'
+ b'\xfdW\x9bop\x0f\xbe\xaee\xa3]\x93\x9c\xda\xb75<\xf6g!\xcc\xb1\xfc\\'
+ b'7\x152Mc\x17\x84\x9d\xcd35\r0\xacL-\xf3\xfb\xcb\x96\x1e\xe9U\x7f'
+ b'\xd7\xca\xb0\xcc\x89\x0c*\xce\x14\xd1P\xf1\x03\xb6.~9o?\xe8'
+ b'\r\x86\xe0\x92\x87}\xa3\x84\x03P\xe0\xc2\x7f\n;m\x9d\x9e\xb4|'
+ b'\x8c\x18\xc0#0\xfe3\x07<\xda\xd8\xcf^\xd4Hi\xd6\xb3\x0bT'
+ b'\x1dF\x88\x85q}\x02\xc6&\xc4\xae\xce\x9cU\xfa\x0f\xcc\xb6\x1f\x11'
+ b'drw\x9eN\x19\xbd\xffz\x0f\xf0\x04s\xadR\xc1\xc0\xbfl\xf1\xba\xf95^'
+ b'e\xb1\xfbVY\xd9\x9f\x1c\xbf*\xc4\xa86\x08+\xd6\x88[\xc4_rc\xf0f'
+ b'\xb8\xd4\xec\x1dx\x19|\xbf\xa7\xe0\x82\x0b\x8c~\x10L/\x90\xd6\xfb'
+ b'\x81\xdb\x98\xcc\x02\x14\xa5C\xb2\xa7i\xfd\xcd\x1fO\xf7\xe9\x89t\xf0'
+ b'\x17\xa5\x1c\xad\xfe<Q`%\x075k\n7\x9eI\x82<#)&\x04\xc2\xf0C\xd4`!'
+ b'\xcb\xa9\xf9\xb3F\x86\xb5\xc3M\xbeu\x12\xb2\xca\x95e\x10\x0b\xb1\xcc'
+ b'\x01b\x9bXa\x1b[B\x8c\x07\x11Of;\xeaC\xebr\x8eb\xd9\x9c\xe4i]<z\x9a'
+ b'\x03T\x8b9pF\x10\x8c\x84\xc7\x0e\xeaPw\xe5\xa0\x94\x1f\x84\xdd'
+ b'a\xe8\x85\xc2\x00\xebq\xe7&Wo5q8\xc2t\x98\xab\xb7\x7f\xe64-H'
+ b'\t\xb4d\xbe\x06\xe3Q\x8b\xa9J\xb0\x00\xd7s.\x85"\xc0p\x05'
+ b'\x1c\x06N\x87\xa5\xf8\xc3g\x1b}\x0f\x0f\xc3|\x90\xea\xefd3X'
+ b'[\xab\x04E\xf2\xf2\xc9\x08\x8a\xa8+W\xa2v\xec\x15G\x08/I<L\\1'
+ b'\xff\x15O\xaa\x89{\xd1mW\x13\xbd~\xe1\x90^\xc4@\r\xed\xb5D@\xb4\x08'
+ b'A\x90\xe69;\xc7BO\xdb\xda\xebu\x9e\xa9tN\xae\x8aJ5\xcd\x11\x1d\xea'
+ b"\xe5\xa7\x04\xe6\x82Z\xc7O\xe46[7\xdco*[\xbe\x0b\xc9\xb7a\xab'\xf6"
+ b"\xd1u\xdb\xd9q\xf5+y\x1b\x00\xb4\xf3a\xae\xf1M\xc4\xbc\xd00'\x06pQ"
+ b'\x8dH\xaa\xaa\xc4\xd2K\x9b\xc0\xe9\xec=n\xa9\x1a\x8a\xc2\xe8\x18\xbc'
+ b'\x93\xb8F\xa1\x8fOY\xe7\xda\xcf0\t\xff|\xd9\xe5\xcf\xe7\xf6\xbe'
+ b'\xf8\x04\x17\xf2\xe5P\xa7y~\xce\x11h0\x81\x80d[\x00_v\xbbc\xdbI'
+ b'3\xbc`W\xc0yrkB\xf5\x9f\xe9i\xc5\x8a^\x8d\xd4\x81\xd9\x05\xc1\xfc>'
+ b'"\xd1v`\x82\xd5$\x89\xcf^\xd52.\xafd\xe8d@\xaa\xd5Y|\x90\x84'
+ b'j\xdb}\x84riV\x8e\xf0X4rB\xf2NPS[\x8e\x88\xd4\x0fI\xb8'
+ b'\xdd\xcb\x1d\xf2(\xdf;9\x9e|\xef^0;.*[\x9fl\x7f\xa2_X\xaff!\xbb\x03'
+ b'\xff\x19\x8f\x88\xb5\xb6\x884\xa3\x05\xde3D{\xe3\xcb\xce\xe4t]'
+ b'\x875\xe3Uf\xae\xea\x88\x1c\x03b\n\xb1,Q\xec\xcf\x08\t\xde@\x83\xaa<'
+ b',-\xe4\xee\x9b\x843\xe5\x007\tK\xac\x057\xd6*X\xa3\xc6~\xba\xe6O'
+ b'\x81kz"\xbe\xe43sL\xf1\xfa;\xf4^\x1e\xb4\x80\xe2\xbd\xaa\x17Z\xe1f'
+ b'\xda\xa6\xb9\x07:]}\x9fa\x0b?\xba\xe7\xf15\x04M\xe3\n}M\xa4\xcb\r'
+ b'2\x8a\x88\xa9\xa7\x92\x93\x84\x81Yo\x00\xcc\xc4\xab\x9aT\x96\x0b\xbe'
+ b'U\xac\x1d\x8d\x1b\x98"\xf8\x8f\xf1u\xc1n\xcc\xfcA\xcc\x90\xb7i'
+ b'\x83\x9c\x9c~\x1d4\xa2\xf0*J\xe7t\x12\xb4\xe3\xa0u\xd7\x95Z'
+ b'\xf7\xafG\x96~ST,\xa7\rC\x06\xf4\xf0\xeb`2\x9e>Q\x0e\xf6\xf5\xc5'
+ b'\x9b\xb5\xaf\xbe\xa3\x8f\xc0\xa3hu\x14\x12 \x97\x99\x04b\x8e\xc7\x1b'
+ b'VKc\xc1\xf3 \xde\x85-:\xdc\x1f\xac\xce*\x06\xb3\x80;`'
+ b'\xdb\xdd\x97\xfdg\xbf\xe7\xa8S\x08}\xf55e7\xb8/\xf0!\xc8'
+ b"Y\xa8\x9a\x07'\xe2\xde\r\x02\xe1\xb2\x0c\xf4C\xcd\xf9\xcb(\xe8\x90"
+ b'\xd3bTD\x15_\xf6\xc3\xfb\xb3E\xfc\xd6\x98{\xc6\\fz\x81\xa99\x85\xcb'
+ b'\xa5\xb1\x1d\x94bqW\x1a!;z~\x18\x88\xe8i\xdb\x1b\x8d\x8d'
+ b'\x06\xaa\x0e\x99s+5k\x00\xe4\xffh\xfe\xdbt\xa6\x1bU\xde\xa3'
+ b'\xef\xcb\x86\x9e\x81\x16j\n\x9d\xbc\xbbC\x80?\x010\xc7Jj;'
+ b'\xc4\xe5\x86\xd5\x0e0d#\xc6;\xb8\xd1\xc7c\xb5&8?\xd9J\xe5\xden\xb9'
+ b'\xe9cb4\xbb\xe6\x14\xe0\xe7l\x1b\x85\x94\x1fh\xf1n\xdeZ\xbe'
+ b'\x88\xff\xc2e\xca\xdc,B-\x8ac\xc9\xdf\xf5|&\xe4LL\xf0\x1f\xaa8\xbd'
+ b'\xc26\x94bVi\xd3\x0c\x1c\xb6\xbb\x99F\x8f\x0e\xcc\x8e4\xc6/^W\xf5?'
+ b'\xdc\x84(\x14dO\x9aD6\x0f4\xa3,\x0c\x0bS\x9fJ\xe1\xacc^\x8a0\t\x80D['
+ b'\xb8\xe6\x86\xb0\xe8\xd4\xf9\x1en\xf1\xf5^\xeb\xb8\xb8\xf8'
+ b')\xa8\xbf\xaa\x84\x86\xb1a \x95\x16\x08\x1c\xbb@\xbd+\r/\xfb'
+ b'\x92\xfbh\xf1\x8d3\xf9\x92\xde`\xf1\x86\x03\xaa+\xd9\xd9\xc6P\xaf'
+ b'\xe3-\xea\xa5\x0fB\xca\xde\xd5n^\xe3/\xbf\xa6w\xc8\x0e<M'
+ b'\xc2\x1e!\xd4\xc6E\xf2\xad\x0c\xbc\x1d\x88Y\x03\x98<\x92\xd9\xa6B'
+ b'\xc7\x83\xb5"\x97D|&\xc4\xd4\xfad\x0e\xde\x06\xa3\xc2\x9c`\xf2'
+ b'7\x03\x1a\xed\xd80\x10\xe9\x0co\x10\xcf\x18\x16\xa7\x1c'
+ b"\xe5\x96\xa4\xd9\xe1\xa5v;]\xb7\xa9\xdc'hA\xe3\x9c&\x98\x0b9\xdf~@"
+ b'\xf8\xact\x87<\xf94\x0c\x9d\x93\xb0)\xe1\xa2\x0f\x1e=:&\xd56\xa5A+'
+ b'\xab\xc4\x00\x8d\x81\x93\xd4\xd8<\x82k\\d\xd8v\xab\xbd^l5C?\xd4\xa0'
+ b'M\x12C\xc8\x80\r\xc83\xe8\xc0\xf5\xdf\xca\x05\xf4BPjy\xbe\x91\x9bzE'
+ b"\xd8[\x93oT\r\x13\x16'\x1a\xbd*H\xd6\xfe\r\xf3\x91M\x8b\xee\x8f7f"
+ b"\x0b;\xaa\x85\xf2\xdd'\x0fwM \xbd\x13\xb9\xe5\xb8\xb7 D+P\x1c\xe4g"
+ b'n\xd2\xf1kc\x15\xaf\xc6\x90V\x03\xc2UovfZ\xcc\xd23^\xb3\xe7\xbf'
+ b'\xacv\x1d\x82\xedx\xa3J\xa9\xb7\xcf\x0c\xe6j\x96n*o\x18>'
+ b'\xc6\xfd\x97_+D{\x03\x15\xe8s\xb1\xc8HAG\xcf\xf4\x1a\xdd'
+ b'\xad\x11\xbf\x157q+\xdeW\x89g"X\x82\xfd~\xf7\xab4\xf6`\xab\xf1q'
+ b')\x82\x10K\xe9sV\xfe\xe45\xafs*\x14\xa7;\xac{\x06\x9d<@\x93G'
+ b'j\x1d\xefL\xe9\xd8\x92\x19&\xa1\x16\x19\x04\tu5\x01]\xf6\xf4'
+ b'\xcd\\\xd8A|I\xd4\xeb\x05\x88C\xc6e\xacQ\xe9*\x97~\x9au\xf8Xy'
+ b"\x17P\x10\x9f\n\x8c\xe2fZEu>\x9b\x1e\x91\x0b'`\xbd\xc0\xa8\x86c\x1d"
+ b'Z\xe2\xdc8j\x95\xffU\x90\x1e\xf4o\xbc\xe5\xe3e>\xd2R\xc0b#\xbc\x15'
+ b'H-\xb9!\xde\x9d\x90k\xdew\x9b{\x99\xde\xf7/K)A\xfd\xf5\xe6:\xda'
+ b'UM\xcc\xbb\xa2\x0b\x9a\x93\xf5{9\xc0 \xd2((6i\xc0\xbbu\xd8\x9e\x8d'
+ b'\xf8\x04q\x10\xd4\x14\x9e7-\xb9B\xea\x01Q8\xc8v\x9a\x12A\x88Cd\x92'
+ b"\x1c\x8c!\xf4\x94\x87'\xe3\xcd\xae\xf7\xd8\x93\xfa\xde\xa8b\x9e\xee2"
+ b'K\xdb\x00l\x9d\t\xb1|D\x05U\xbb\xf4>\xf1w\x887\xd1}W\x9d|g|1\xb0\x13'
+ b"\xa3 \xe5\xbfm@\xc06+\xb7\t\xcf\x15D\x9a \x1fM\x1f\xd2\xb5'\xa9\xbb"
+ b'~Co\x82\xfa\xc2\t\xe6f\xfc\xbeI\xae1\x8e\xbe\xb8\xcf\x86\x17'
+ b'\x9f\xe2`\xbd\xaf\xba\xb9\xbc\x1b\xa3\xcd\x82\x8fwc\xefd\xa9\xd5\x14'
+ b'\xe2C\xafUE\xb6\x11MJH\xd0=\x05\xd4*I\xff"\r\x1b^\xcaS6=\xec@\xd5'
+ b'\x11,\xe0\x87Gr\xaa[\xb8\xbc>n\xbd\x81\x0c\x07<\xe9\x92('
+ b'\xb2\xff\xac}\xe7\xb6\x15\x90\x9f~4\x9a\xe6\xd6\xd8s\xed\x99tf'
+ b'\xa0f\xf8\xf1\x87\t\x96/)\x85\xb6\n\xd7\xb2w\x0b\xbc\xba\x99\xee'
+ b'Q\xeen\x1d\xad\x03\xc3s\xd1\xfd\xa2\xc6\xb7\x9a\x9c(G<6\xad[~H '
+ b'\x16\x89\x89\xd0\xc3\xd2\xca~\xac\xea\xa5\xed\xe5\xfb\r:'
+ b'\x8e\xa6\xf1e\xbb\xba\xbd\xe0(\xa3\x89_\x01(\xb5c\xcc\x9f\x1fg'
+ b'v\xfd\x17\xb3\x08S=S\xee\xfc\x85>\x91\x8d\x8d\nYR\xb3G\xd1A\xa2\xb1'
+ b'\xec\xb0\x01\xd2\xcd\xf9\xfe\x82\x06O\xb3\xecd\xa9c\xe0\x8eP\x90\xce'
+ b'\xe0\xcd\xd8\xd8\xdc\x9f\xaa\x01"[Q~\xe4\x88\xa1#\xc1\x12C\xcf'
+ b'\xbe\x80\x11H\xbf\x86\xd8\xbem\xcfWFQ(X\x01DK\xdfB\xaa\x10.-'
+ b'\xd5\x9e|\x86\x15\x86N]\xc7Z\x17\xcd=\xd7)M\xde\x15\xa4LTi\xa0\x15'
+ b'\xd1\xe7\xbdN\xa4?\xd1\xe7\x02\xfe4\xe4O\x89\x98&\x96\x0f\x02\x9c'
+ b'\x9e\x19\xaa\x13u7\xbd0\xdc\xd8\x93\xf4BNE\x1d\x93\x82\x81\x16'
+ b'\xe5y\xcf\x98D\xca\x9a\xe2\xfd\xcdL\xcc\xd1\xfc_\x0b\x1c\xa0]\xdc'
+ b'\xa91 \xc9c\xd8\xbf\x97\xcfp\xe6\x19-\xad\xff\xcc\xd1N(\xe8'
+ b'\xeb#\x182\x96I\xf7l\xf3r\x00'
+)
+
def test_main():
run_unittest(
import io
import locale
import mimetypes
+import pathlib
import sys
import unittest
strict=True)
self.assertEqual(exts, ['.g3', '.g\xb3'])
+ def test_init_reinitializes(self):
+ # Issue 4936: make sure an init starts clean
+ # First, put some poison into the types table
+ mimetypes.add_type('foo/bar', '.foobar')
+ self.assertEqual(mimetypes.guess_extension('foo/bar'), '.foobar')
+ # Reinitialize
+ mimetypes.init()
+ # Poison should be gone.
+ self.assertEqual(mimetypes.guess_extension('foo/bar'), None)
+
+ def test_preferred_extension(self):
+ def check_extensions():
+ self.assertEqual(mimetypes.guess_extension('application/octet-stream'), '.bin')
+ self.assertEqual(mimetypes.guess_extension('application/postscript'), '.ps')
+ self.assertEqual(mimetypes.guess_extension('application/vnd.apple.mpegurl'), '.m3u')
+ self.assertEqual(mimetypes.guess_extension('application/vnd.ms-excel'), '.xls')
+ self.assertEqual(mimetypes.guess_extension('application/vnd.ms-powerpoint'), '.ppt')
+ self.assertEqual(mimetypes.guess_extension('application/x-texinfo'), '.texi')
+ self.assertEqual(mimetypes.guess_extension('application/x-troff'), '.roff')
+ self.assertEqual(mimetypes.guess_extension('application/xml'), '.xsl')
+ self.assertEqual(mimetypes.guess_extension('audio/mpeg'), '.mp3')
+ self.assertEqual(mimetypes.guess_extension('image/jpeg'), '.jpg')
+ self.assertEqual(mimetypes.guess_extension('image/tiff'), '.tiff')
+ self.assertEqual(mimetypes.guess_extension('message/rfc822'), '.eml')
+ self.assertEqual(mimetypes.guess_extension('text/html'), '.html')
+ self.assertEqual(mimetypes.guess_extension('text/plain'), '.txt')
+ self.assertEqual(mimetypes.guess_extension('video/mpeg'), '.mpeg')
+ self.assertEqual(mimetypes.guess_extension('video/quicktime'), '.mov')
+
+ check_extensions()
+ mimetypes.init()
+ check_extensions()
+
+ def test_init_stability(self):
+ mimetypes.init()
+
+ suffix_map = mimetypes.suffix_map
+ encodings_map = mimetypes.encodings_map
+ types_map = mimetypes.types_map
+ common_types = mimetypes.common_types
+
+ mimetypes.init()
+ self.assertIsNot(suffix_map, mimetypes.suffix_map)
+ self.assertIsNot(encodings_map, mimetypes.encodings_map)
+ self.assertIsNot(types_map, mimetypes.types_map)
+ self.assertIsNot(common_types, mimetypes.common_types)
+ self.assertEqual(suffix_map, mimetypes.suffix_map)
+ self.assertEqual(encodings_map, mimetypes.encodings_map)
+ self.assertEqual(types_map, mimetypes.types_map)
+ self.assertEqual(common_types, mimetypes.common_types)
+
+ def test_path_like_ob(self):
+ filename = "LICENSE.txt"
+ filepath = pathlib.Path(filename)
+ filepath_with_abs_dir = pathlib.Path('/dir/'+filename)
+ filepath_relative = pathlib.Path('../dir/'+filename)
+ path_dir = pathlib.Path('./')
+
+ expected = self.db.guess_type(filename)
+
+ self.assertEqual(self.db.guess_type(filepath), expected)
+ self.assertEqual(self.db.guess_type(
+ filepath_with_abs_dir), expected)
+ self.assertEqual(self.db.guess_type(filepath_relative), expected)
+ self.assertEqual(self.db.guess_type(path_dir), (None, None))
+
+ def test_keywords_args_api(self):
+ self.assertEqual(self.db.guess_type(
+ url="foo.html", strict=True), ("text/html", None))
+ self.assertEqual(self.db.guess_all_extensions(
+ type='image/jpg', strict=True), [])
+ self.assertEqual(self.db.guess_extension(
+ type='image/jpg', strict=False), '.jpg')
+
@unittest.skipUnless(sys.platform.startswith("win"), "Windows only")
class Win32MimeTypesTestCase(unittest.TestCase):
def test_directory_start_component_keyfile(self):
db, db_path = init_database()
self.addCleanup(db.Close)
+ self.addCleanup(msilib._directories.clear)
feature = msilib.Feature(db, 0, 'Feature', 'A feature', 'Python')
cab = msilib.CAB('CAB')
dir = msilib.Directory(db, cab, None, TESTFN, 'TARGETDIR',
# but for those that require it we import here.
nt = None
+
+def _norm(path):
+ if isinstance(path, (bytes, str, os.PathLike)):
+ return ntpath.normcase(os.fsdecode(path))
+ elif hasattr(path, "__iter__"):
+ return tuple(ntpath.normcase(os.fsdecode(p)) for p in path)
+ return path
+
+
def tester(fn, wantResult):
fn = fn.replace("\\", "\\\\")
gotResult = eval(fn)
- if wantResult != gotResult:
+ if wantResult != gotResult and _norm(wantResult) != _norm(gotResult):
raise TestFailed("%s should return: %s but returned: %s" \
%(str(fn), str(wantResult), str(gotResult)))
with warnings.catch_warnings():
warnings.simplefilter("ignore", DeprecationWarning)
gotResult = eval(fn)
- if isinstance(wantResult, str):
- wantResult = os.fsencode(wantResult)
- elif isinstance(wantResult, tuple):
- wantResult = tuple(os.fsencode(r) for r in wantResult)
-
- gotResult = eval(fn)
- if wantResult != gotResult:
+ if _norm(wantResult) != _norm(gotResult):
raise TestFailed("%s should return: %s but returned: %s" \
%(str(fn), str(wantResult), repr(gotResult)))
-class TestNtpath(unittest.TestCase):
+class NtpathTestCase(unittest.TestCase):
+ def assertPathEqual(self, path1, path2):
+ if path1 == path2 or _norm(path1) == _norm(path2):
+ return
+ self.assertEqual(path1, path2)
+
+ def assertPathIn(self, path, pathset):
+ self.assertIn(_norm(path), _norm(pathset))
+
+
+class TestNtpath(NtpathTestCase):
def test_splitext(self):
tester('ntpath.splitext("foo.ext")', ('foo', '.ext'))
tester('ntpath.splitext("/foo/foo.ext")', ('/foo/foo', '.ext'))
attributes = ['relpath']
-class PathLikeTests(unittest.TestCase):
+class PathLikeTests(NtpathTestCase):
path = ntpath
with open(self.file_name, 'xb', 0) as file:
file.write(b"test_ntpath.PathLikeTests")
- def assertPathEqual(self, func):
- self.assertEqual(func(self.file_path), func(self.file_name))
+ def _check_function(self, func):
+ self.assertPathEqual(func(self.file_path), func(self.file_name))
def test_path_normcase(self):
- self.assertPathEqual(self.path.normcase)
+ self._check_function(self.path.normcase)
def test_path_isabs(self):
- self.assertPathEqual(self.path.isabs)
+ self._check_function(self.path.isabs)
def test_path_join(self):
self.assertEqual(self.path.join('a', FakePath('b'), 'c'),
self.path.join('a', 'b', 'c'))
def test_path_split(self):
- self.assertPathEqual(self.path.split)
+ self._check_function(self.path.split)
def test_path_splitext(self):
- self.assertPathEqual(self.path.splitext)
+ self._check_function(self.path.splitext)
def test_path_splitdrive(self):
- self.assertPathEqual(self.path.splitdrive)
+ self._check_function(self.path.splitdrive)
def test_path_basename(self):
- self.assertPathEqual(self.path.basename)
+ self._check_function(self.path.basename)
def test_path_dirname(self):
- self.assertPathEqual(self.path.dirname)
+ self._check_function(self.path.dirname)
def test_path_islink(self):
- self.assertPathEqual(self.path.islink)
+ self._check_function(self.path.islink)
def test_path_lexists(self):
- self.assertPathEqual(self.path.lexists)
+ self._check_function(self.path.lexists)
def test_path_ismount(self):
- self.assertPathEqual(self.path.ismount)
+ self._check_function(self.path.ismount)
def test_path_expanduser(self):
- self.assertPathEqual(self.path.expanduser)
+ self._check_function(self.path.expanduser)
def test_path_expandvars(self):
- self.assertPathEqual(self.path.expandvars)
+ self._check_function(self.path.expandvars)
def test_path_normpath(self):
- self.assertPathEqual(self.path.normpath)
+ self._check_function(self.path.normpath)
def test_path_abspath(self):
- self.assertPathEqual(self.path.abspath)
+ self._check_function(self.path.abspath)
def test_path_realpath(self):
- self.assertPathEqual(self.path.realpath)
+ self._check_function(self.path.realpath)
def test_path_relpath(self):
- self.assertPathEqual(self.path.relpath)
+ self._check_function(self.path.relpath)
def test_path_commonpath(self):
common_path = self.path.commonpath([self.file_path, self.file_name])
- self.assertEqual(common_path, self.file_name)
+ self.assertPathEqual(common_path, self.file_name)
def test_path_isdir(self):
- self.assertPathEqual(self.path.isdir)
+ self._check_function(self.path.isdir)
if __name__ == "__main__":
import _winapi
except ImportError:
_winapi = None
-try:
- import grp
- groups = [g.gr_gid for g in grp.getgrall() if getpass.getuser() in g.gr_mem]
- if hasattr(os, 'getgid'):
- process_gid = os.getgid()
- if process_gid not in groups:
- groups.append(process_gid)
-except ImportError:
- groups = []
try:
import pwd
all_users = [u.pw_uid for u in pwd.getpwall()]
self.assertIsNone(os.chown(support.TESTFN, uid, gid))
self.assertIsNone(os.chown(support.TESTFN, -1, -1))
- @unittest.skipUnless(len(groups) > 1, "test needs more than one group")
- def test_chown(self):
+ @unittest.skipUnless(hasattr(os, 'getgroups'), 'need os.getgroups')
+ def test_chown_gid(self):
+ groups = os.getgroups()
+ if len(groups) < 2:
+ self.skipTest("test needs at least 2 groups")
+
gid_1, gid_2 = groups[:2]
uid = os.stat(support.TESTFN).st_uid
+
os.chown(support.TESTFN, uid, gid_1)
gid = os.stat(support.TESTFN).st_gid
self.assertEqual(gid, gid_1)
+
os.chown(support.TESTFN, uid, gid_2)
gid = os.stat(support.TESTFN).st_gid
self.assertEqual(gid, gid_2)
self.addCleanup(os.close, fd2)
self.assertEqual(os.get_inheritable(fd2), False)
+ def test_dup_standard_stream(self):
+ fd = os.dup(1)
+ self.addCleanup(os.close, fd)
+ self.assertGreater(fd, 0)
+
@unittest.skipUnless(sys.platform == 'win32', 'win32-specific test')
def test_dup_nul(self):
# os.dup() was creating inheritable fds for character files.
func(*args, **kwargs)
self.assertEqual(cm.exception.errno, errno.ENOENT)
+ def assertEqualNormCase(self, path_a, path_b):
+ self.assertEqual(os.path.normcase(path_a), os.path.normcase(path_b))
+
def _test_cwd(self, p):
q = self.cls(os.getcwd())
self.assertEqual(p, q)
- self.assertEqual(str(p), str(q))
+ self.assertEqualNormCase(str(p), str(q))
self.assertIs(type(p), type(q))
self.assertTrue(p.is_absolute())
def _test_home(self, p):
q = self.cls(os.path.expanduser('~'))
self.assertEqual(p, q)
- self.assertEqual(str(p), str(q))
+ self.assertEqualNormCase(str(p), str(q))
self.assertIs(type(p), type(q))
self.assertTrue(p.is_absolute())
p.resolve(strict=True)
self.assertEqual(cm.exception.errno, errno.ENOENT)
# Non-strict
- self.assertEqual(str(p.resolve(strict=False)),
- os.path.join(BASE, 'foo'))
+ self.assertEqualNormCase(str(p.resolve(strict=False)),
+ os.path.join(BASE, 'foo'))
p = P(BASE, 'foo', 'in', 'spam')
- self.assertEqual(str(p.resolve(strict=False)),
- os.path.join(BASE, 'foo', 'in', 'spam'))
+ self.assertEqualNormCase(str(p.resolve(strict=False)),
+ os.path.join(BASE, 'foo', 'in', 'spam'))
p = P(BASE, '..', 'foo', 'in', 'spam')
- self.assertEqual(str(p.resolve(strict=False)),
- os.path.abspath(os.path.join('foo', 'in', 'spam')))
- # These are all relative symlinks
+ self.assertEqualNormCase(str(p.resolve(strict=False)),
+ os.path.abspath(os.path.join('foo', 'in', 'spam')))
+ # These are all relative symlinks.
p = P(BASE, 'dirB', 'fileB')
self._check_resolve_relative(p, p)
p = P(BASE, 'linkA')
# Resolve absolute paths
p = (P / 'link0').resolve()
self.assertEqual(p, P)
- self.assertEqual(str(p), BASE)
+ self.assertEqualNormCase(str(p), BASE)
p = (P / 'link1').resolve()
self.assertEqual(p, P)
- self.assertEqual(str(p), BASE)
+ self.assertEqualNormCase(str(p), BASE)
p = (P / 'link2').resolve()
self.assertEqual(p, P)
- self.assertEqual(str(p), BASE)
+ self.assertEqualNormCase(str(p), BASE)
p = (P / 'link3').resolve()
self.assertEqual(p, P)
- self.assertEqual(str(p), BASE)
+ self.assertEqualNormCase(str(p), BASE)
# Resolve relative paths
old_path = os.getcwd()
try:
p = self.cls('link0').resolve()
self.assertEqual(p, P)
- self.assertEqual(str(p), BASE)
+ self.assertEqualNormCase(str(p), BASE)
p = self.cls('link1').resolve()
self.assertEqual(p, P)
- self.assertEqual(str(p), BASE)
+ self.assertEqualNormCase(str(p), BASE)
p = self.cls('link2').resolve()
self.assertEqual(p, P)
- self.assertEqual(str(p), BASE)
+ self.assertEqualNormCase(str(p), BASE)
p = self.cls('link3').resolve()
self.assertEqual(p, P)
- self.assertEqual(str(p), BASE)
+ self.assertEqualNormCase(str(p), BASE)
finally:
os.chdir(old_path)
if save_home is not None:
os.environ['HOME'] = save_home
+ def test_readrc_homedir(self):
+ save_home = os.environ.pop("HOME", None)
+ with support.temp_dir() as temp_dir, patch("os.path.expanduser"):
+ rc_path = os.path.join(temp_dir, ".pdbrc")
+ os.path.expanduser.return_value = rc_path
+ try:
+ with open(rc_path, "w") as f:
+ f.write("invalid")
+ self.assertEqual(pdb.Pdb().rcLines[0], "invalid")
+ finally:
+ if save_home is not None:
+ os.environ["HOME"] = save_home
+
def test_header(self):
stdout = StringIO()
header = 'Nobody expects... blah, blah, blah'
self.assertEqual(posix.sched_getaffinity(0), mask)
self.assertRaises(OSError, posix.sched_setaffinity, 0, [])
self.assertRaises(ValueError, posix.sched_setaffinity, 0, [-10])
+ self.assertRaises(ValueError, posix.sched_setaffinity, 0, map(int, "0X"))
self.assertRaises(OverflowError, posix.sched_setaffinity, 0, [1<<128])
self.assertRaises(OSError, posix.sched_setaffinity, -1, mask)
choices([], cum_weights=[], k=5)
def test_choices_subnormal(self):
- # Subnormal weights would occassionally trigger an IndexError
+ # Subnormal weights would occasionally trigger an IndexError
# in choices() when the value returned by random() was large
# enough to make `random() * total` round up to the total.
# See https://bugs.python.org/msg275594 for more detail.
env_changed=[testname],
fail_env_changed=True)
+ def test_multiprocessing_timeout(self):
+ code = textwrap.dedent(r"""
+ import time
+ import unittest
+ try:
+ import faulthandler
+ except ImportError:
+ faulthandler = None
+
+ class Tests(unittest.TestCase):
+ # test hangs and so should be stopped by the timeout
+ def test_sleep(self):
+ # we want to test regrtest multiprocessing timeout,
+ # not faulthandler timeout
+ if faulthandler is not None:
+ faulthandler.cancel_dump_traceback_later()
+
+ time.sleep(60 * 5)
+ """)
+ testname = self.create_test(code=code)
+
+ output = self.run_tests("-j2", "--timeout=1.0", testname, exitcode=2)
+ self.check_executed_tests(output, [testname],
+ failed=testname)
+ self.assertRegex(output,
+ re.compile('%s timed out' % testname, re.MULTILINE))
+
+ def test_cleanup(self):
+ dirname = os.path.join(self.tmptestdir, "test_python_123")
+ os.mkdir(dirname)
+ filename = os.path.join(self.tmptestdir, "test_python_456")
+ open(filename, "wb").close()
+ names = [dirname, filename]
+
+ cmdargs = ['-m', 'test',
+ '--tempdir=%s' % self.tmptestdir,
+ '--cleanup']
+ self.run_python(cmdargs)
+
+ for name in names:
+ self.assertFalse(os.path.exists(name), name)
+
class TestUtils(unittest.TestCase):
def test_format_duration(self):
self.assertEqual(shlex.quote("test%s'name'" % u),
"'test%s'\"'\"'name'\"'\"''" % u)
+ def testPunctuationCharsReadOnly(self):
+ punctuation_chars = "/|$%^"
+ shlex_instance = shlex.shlex(punctuation_chars=punctuation_chars)
+ self.assertEqual(shlex_instance.punctuation_chars, punctuation_chars)
+ with self.assertRaises(AttributeError):
+ shlex_instance.punctuation_chars = False
+
+
# Allow this test to be used with old shlex.py
if not getattr(shlex, "split", None):
for methname in dir(ShlexTest):
try:
compile(b"# coding: cp932\nprint '\x94\x4e'", "dummy", "exec")
except SyntaxError as v:
- self.assertEqual(v.text, "print '\u5e74'\n")
+ self.assertEqual(v.text.rstrip('\n'), "print '\u5e74'")
else:
self.fail()
import platform
import functools
import sysconfig
+import functools
try:
import ctypes
except ImportError:
OP_ENABLE_MIDDLEBOX_COMPAT = getattr(ssl, "OP_ENABLE_MIDDLEBOX_COMPAT", 0)
+def has_tls_protocol(protocol):
+ """Check if a TLS protocol is available and enabled
+
+ :param protocol: enum ssl._SSLMethod member or name
+ :return: bool
+ """
+ if isinstance(protocol, str):
+ assert protocol.startswith('PROTOCOL_')
+ protocol = getattr(ssl, protocol, None)
+ if protocol is None:
+ return False
+ if protocol in {
+ ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS_SERVER,
+ ssl.PROTOCOL_TLS_CLIENT
+ }:
+ # auto-negotiate protocols are always available
+ return True
+ name = protocol.name
+ return has_tls_version(name[len('PROTOCOL_'):])
+
+
+@functools.lru_cache()
+def has_tls_version(version):
+ """Check if a TLS/SSL version is enabled
+
+ :param version: TLS version name or ssl.TLSVersion member
+ :return: bool
+ """
+ if version == "SSLv2":
+ # never supported and not even in TLSVersion enum
+ return False
+
+ if isinstance(version, str):
+ version = ssl.TLSVersion.__members__[version]
+
+ # check compile time flags like ssl.HAS_TLSv1_2
+ if not getattr(ssl, f'HAS_{version.name}'):
+ return False
+
+ # check runtime and dynamic crypto policy settings. A TLS version may
+ # be compiled in but disabled by a policy or config option.
+ ctx = ssl.SSLContext()
+ if (
+ hasattr(ctx, 'minimum_version') and
+ ctx.minimum_version != ssl.TLSVersion.MINIMUM_SUPPORTED and
+ version < ctx.minimum_version
+ ):
+ return False
+ if (
+ hasattr(ctx, 'maximum_version') and
+ ctx.maximum_version != ssl.TLSVersion.MAXIMUM_SUPPORTED and
+ version > ctx.maximum_version
+ ):
+ return False
+
+ return True
+
+
+def requires_tls_version(version):
+ """Decorator to skip tests when a required TLS version is not available
+
+ :param version: TLS version name or ssl.TLSVersion member
+ :return:
+ """
+ def decorator(func):
+ @functools.wraps(func)
+ def wrapper(*args, **kw):
+ if not has_tls_version(version):
+ raise unittest.SkipTest(f"{version} is not available.")
+ else:
+ return func(*args, **kw)
+ return wrapper
+ return decorator
+
+
+requires_minimum_version = unittest.skipUnless(
+ hasattr(ssl.SSLContext, 'minimum_version'),
+ "required OpenSSL >= 1.1.0g"
+)
+
+
def handle_error(prefix):
exc_format = ' '.join(traceback.format_exception(*sys.exc_info()))
if support.verbose:
cert, enc, trust = element
self.assertIsInstance(cert, bytes)
self.assertIn(enc, {"x509_asn", "pkcs_7_asn"})
- self.assertIsInstance(trust, (set, bool))
- if isinstance(trust, set):
+ self.assertIsInstance(trust, (frozenset, set, bool))
+ if isinstance(trust, (frozenset, set)):
trust_oids.update(trust)
serverAuth = "1.3.6.1.5.5.7.3.1"
with self.assertRaises(AttributeError):
ctx.hostname_checks_common_name = True
- @unittest.skipUnless(hasattr(ssl.SSLContext, 'minimum_version'),
- "required OpenSSL 1.1.0g")
+ @requires_minimum_version
+ @unittest.skipIf(IS_LIBRESSL, "see bpo-34001")
def test_min_max_version(self):
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
# OpenSSL default is MINIMUM_SUPPORTED, however some vendors like
# Fedora override the setting to TLS 1.0.
+ minimum_range = {
+ # stock OpenSSL
+ ssl.TLSVersion.MINIMUM_SUPPORTED,
+ # Fedora 29 uses TLS 1.0 by default
+ ssl.TLSVersion.TLSv1,
+ # RHEL 8 uses TLS 1.2 by default
+ ssl.TLSVersion.TLSv1_2
+ }
+
self.assertIn(
- ctx.minimum_version,
- {ssl.TLSVersion.MINIMUM_SUPPORTED,
- # Fedora 29 uses TLS 1.0 by default
- ssl.TLSVersion.TLSv1,
- # RHEL 8 uses TLS 1.2 by default
- ssl.TLSVersion.TLSv1_2}
+ ctx.minimum_version, minimum_range
)
self.assertEqual(
ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1)
- self.assertEqual(
- ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED
+ self.assertIn(
+ ctx.minimum_version, minimum_range
)
self.assertEqual(
ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED
for protocol in PROTOCOLS:
if protocol in {ssl.PROTOCOL_TLS_CLIENT, ssl.PROTOCOL_TLS_SERVER}:
continue
+ if not has_tls_protocol(protocol):
+ continue
with self.subTest(protocol=ssl._PROTOCOL_NAMES[protocol]):
context = ssl.SSLContext(protocol)
context.load_cert_chain(CERTFILE)
else:
self.fail("Use of invalid cert should have failed!")
- @unittest.skipUnless(ssl.HAS_TLSv1_3, "Test needs TLS 1.3")
+ @requires_tls_version('TLSv1_3')
def test_wrong_cert_tls13(self):
client_context, server_context, hostname = testing_context()
# load client cert that is not signed by trusted CA
self.assertIn(msg, repr(e))
self.assertIn('certificate verify failed', repr(e))
- @skip_if_broken_ubuntu_ssl
- @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'),
- "OpenSSL is compiled without SSLv2 support")
+ @requires_tls_version('SSLv2')
def test_protocol_sslv2(self):
"""Connecting to an SSLv2 server with various client options"""
if support.verbose:
try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL)
try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED)
try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False)
- if hasattr(ssl, 'PROTOCOL_SSLv3'):
+ if has_tls_version('SSLv3'):
try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False)
try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False)
# SSLv23 client with specific SSL options
"""Connecting to an SSLv23 server with various client options"""
if support.verbose:
sys.stdout.write("\n")
- if hasattr(ssl, 'PROTOCOL_SSLv2'):
+ if has_tls_version('SSLv2'):
try:
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv2, True)
except OSError as x:
sys.stdout.write(
" SSL2 client to SSL23 server test unexpectedly failed:\n %s\n"
% str(x))
- if hasattr(ssl, 'PROTOCOL_SSLv3'):
+ if has_tls_version('SSLv3'):
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False)
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True)
- try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1')
+ if has_tls_version('TLSv1'):
+ try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1')
- if hasattr(ssl, 'PROTOCOL_SSLv3'):
+ if has_tls_version('SSLv3'):
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_OPTIONAL)
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_OPTIONAL)
- try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
+ if has_tls_version('TLSv1'):
+ try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
- if hasattr(ssl, 'PROTOCOL_SSLv3'):
+ if has_tls_version('SSLv3'):
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False, ssl.CERT_REQUIRED)
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True, ssl.CERT_REQUIRED)
- try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
+ if has_tls_version('TLSv1'):
+ try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
# Server with specific SSL options
- if hasattr(ssl, 'PROTOCOL_SSLv3'):
+ if has_tls_version('SSLv3'):
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv3, False,
server_options=ssl.OP_NO_SSLv3)
# Will choose TLSv1
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLS, True,
server_options=ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3)
- try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, False,
- server_options=ssl.OP_NO_TLSv1)
-
+ if has_tls_version('TLSv1'):
+ try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1, False,
+ server_options=ssl.OP_NO_TLSv1)
- @skip_if_broken_ubuntu_ssl
- @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv3'),
- "OpenSSL is compiled without SSLv3 support")
+ @requires_tls_version('SSLv3')
def test_protocol_sslv3(self):
"""Connecting to an SSLv3 server with various client options"""
if support.verbose:
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3')
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_OPTIONAL)
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv3, 'SSLv3', ssl.CERT_REQUIRED)
- if hasattr(ssl, 'PROTOCOL_SSLv2'):
+ if has_tls_version('SSLv2'):
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_SSLv2, False)
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS, False,
client_options=ssl.OP_NO_SSLv3)
try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS,
False, client_options=ssl.OP_NO_SSLv2)
- @skip_if_broken_ubuntu_ssl
+ @requires_tls_version('TLSv1')
def test_protocol_tlsv1(self):
"""Connecting to a TLSv1 server with various client options"""
if support.verbose:
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1')
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_OPTIONAL)
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1, 'TLSv1', ssl.CERT_REQUIRED)
- if hasattr(ssl, 'PROTOCOL_SSLv2'):
+ if has_tls_version('SSLv2'):
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv2, False)
- if hasattr(ssl, 'PROTOCOL_SSLv3'):
+ if has_tls_version('SSLv3'):
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_SSLv3, False)
try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLS, False,
client_options=ssl.OP_NO_TLSv1)
- @skip_if_broken_ubuntu_ssl
- @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"),
- "TLS version 1.1 not supported.")
+ @requires_tls_version('TLSv1_1')
def test_protocol_tlsv1_1(self):
"""Connecting to a TLSv1.1 server with various client options.
Testing against older TLS versions."""
if support.verbose:
sys.stdout.write("\n")
try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
- if hasattr(ssl, 'PROTOCOL_SSLv2'):
+ if has_tls_version('SSLv2'):
try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv2, False)
- if hasattr(ssl, 'PROTOCOL_SSLv3'):
+ if has_tls_version('SSLv3'):
try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_SSLv3, False)
try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLS, False,
client_options=ssl.OP_NO_TLSv1_1)
try_protocol_combo(ssl.PROTOCOL_TLS, ssl.PROTOCOL_TLSv1_1, 'TLSv1.1')
- try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False)
- try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False)
+ try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1_2, False)
+ try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_1, False)
- @skip_if_broken_ubuntu_ssl
- @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"),
- "TLS version 1.2 not supported.")
+ @requires_tls_version('TLSv1_2')
def test_protocol_tlsv1_2(self):
"""Connecting to a TLSv1.2 server with various client options.
Testing against older TLS versions."""
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLSv1_2, 'TLSv1.2',
server_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,
client_options=ssl.OP_NO_SSLv3|ssl.OP_NO_SSLv2,)
- if hasattr(ssl, 'PROTOCOL_SSLv2'):
+ if has_tls_version('SSLv2'):
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv2, False)
- if hasattr(ssl, 'PROTOCOL_SSLv3'):
+ if has_tls_version('SSLv3'):
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_SSLv3, False)
try_protocol_combo(ssl.PROTOCOL_TLSv1_2, ssl.PROTOCOL_TLS, False,
client_options=ssl.OP_NO_TLSv1_2)
self.assertIs(s.version(), None)
self.assertIs(s._sslobj, None)
s.connect((HOST, server.port))
- if IS_OPENSSL_1_1_1 and ssl.HAS_TLSv1_3:
+ if IS_OPENSSL_1_1_1 and has_tls_version('TLSv1_3'):
self.assertEqual(s.version(), 'TLSv1.3')
elif ssl.OPENSSL_VERSION_INFO >= (1, 0, 2):
self.assertEqual(s.version(), 'TLSv1.2')
self.assertIs(s._sslobj, None)
self.assertIs(s.version(), None)
- @unittest.skipUnless(ssl.HAS_TLSv1_3,
- "test requires TLSv1.3 enabled OpenSSL")
+ @requires_tls_version('TLSv1_3')
def test_tls1_3(self):
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
context.load_cert_chain(CERTFILE)
})
self.assertEqual(s.version(), 'TLSv1.3')
- @unittest.skipUnless(hasattr(ssl.SSLContext, 'minimum_version'),
- "required OpenSSL 1.1.0g")
- def test_min_max_version(self):
+ @requires_minimum_version
+ @requires_tls_version('TLSv1_2')
+ def test_min_max_version_tlsv1_2(self):
client_context, server_context, hostname = testing_context()
# client TLSv1.0 to 1.2
client_context.minimum_version = ssl.TLSVersion.TLSv1
s.connect((HOST, server.port))
self.assertEqual(s.version(), 'TLSv1.2')
+ @requires_minimum_version
+ @requires_tls_version('TLSv1_1')
+ def test_min_max_version_tlsv1_1(self):
+ client_context, server_context, hostname = testing_context()
# client 1.0 to 1.2, server 1.0 to 1.1
+ client_context.minimum_version = ssl.TLSVersion.TLSv1
+ client_context.maximum_version = ssl.TLSVersion.TLSv1_2
server_context.minimum_version = ssl.TLSVersion.TLSv1
server_context.maximum_version = ssl.TLSVersion.TLSv1_1
s.connect((HOST, server.port))
self.assertEqual(s.version(), 'TLSv1.1')
+ @requires_minimum_version
+ @requires_tls_version('TLSv1_2')
+ def test_min_max_version_mismatch(self):
+ client_context, server_context, hostname = testing_context()
# client 1.0, server 1.2 (mismatch)
server_context.minimum_version = ssl.TLSVersion.TLSv1_2
server_context.maximum_version = ssl.TLSVersion.TLSv1_2
s.connect((HOST, server.port))
self.assertIn("alert", str(e.exception))
-
- @unittest.skipUnless(hasattr(ssl.SSLContext, 'minimum_version'),
- "required OpenSSL 1.1.0g")
- @unittest.skipUnless(ssl.HAS_SSLv3, "requires SSLv3 support")
+ @requires_minimum_version
+ @requires_tls_version('SSLv3')
def test_min_max_version_sslv3(self):
client_context, server_context, hostname = testing_context()
server_context.minimum_version = ssl.TLSVersion.SSLv3
'Session refers to a different SSLContext.')
-@unittest.skipUnless(ssl.HAS_TLSv1_3, "Test needs TLS 1.3")
+@unittest.skipUnless(has_tls_version('TLSv1_3'), "Test needs TLS 1.3")
class TestPostHandshakeAuth(unittest.TestCase):
def test_pha_setter(self):
protocols = [
import errno
import tempfile
import time
+import traceback
import selectors
import sysconfig
import select
support.reap_children()
def tearDown(self):
- for inst in subprocess._active:
- inst.wait()
- subprocess._cleanup()
- self.assertFalse(subprocess._active, "subprocess._active not empty")
+ if not mswindows:
+ # subprocess._active is not used on Windows and is set to None.
+ for inst in subprocess._active:
+ inst.wait()
+ subprocess._cleanup()
+ self.assertFalse(
+ subprocess._active, "subprocess._active not empty"
+ )
self.doCleanups()
support.reap_children()
self.assertIn('stderr', c.exception.args[0])
self.assertIn('capture_output', c.exception.args[0])
+ # This test _might_ wind up a bit fragile on loaded build+test machines
+ # as it depends on the timing with wide enough margins for normal situations
+ # but does assert that it happened "soon enough" to believe the right thing
+ # happened.
+ @unittest.skipIf(mswindows, "requires posix like 'sleep' shell command")
+ def test_run_with_shell_timeout_and_capture_output(self):
+ """Output capturing after a timeout mustn't hang forever on open filehandles."""
+ before_secs = time.monotonic()
+ try:
+ subprocess.run('sleep 3', shell=True, timeout=0.1,
+ capture_output=True) # New session unspecified.
+ except subprocess.TimeoutExpired as exc:
+ after_secs = time.monotonic()
+ stacks = traceback.format_exc() # assertRaises doesn't give this.
+ else:
+ self.fail("TimeoutExpired not raised.")
+ self.assertLess(after_secs - before_secs, 1.5,
+ msg="TimeoutExpired was delayed! Bad traceback:\n```\n"
+ f"{stacks}```")
+
@unittest.skipIf(mswindows, "POSIX specific tests")
class POSIXProcessTestCase(BaseTestCase):
with support.check_warnings(('', ResourceWarning)):
p = None
- # check that p is in the active processes list
- self.assertIn(ident, [id(o) for o in subprocess._active])
+ if mswindows:
+ # subprocess._active is not used on Windows and is set to None.
+ self.assertIsNone(subprocess._active)
+ else:
+ # check that p is in the active processes list
+ self.assertIn(ident, [id(o) for o in subprocess._active])
def test_leak_fast_process_del_killed(self):
# Issue #12650: on Unix, if Popen.__del__() was called before the
p = None
os.kill(pid, signal.SIGKILL)
- # check that p is in the active processes list
- self.assertIn(ident, [id(o) for o in subprocess._active])
+ if mswindows:
+ # subprocess._active is not used on Windows and is set to None.
+ self.assertIsNone(subprocess._active)
+ else:
+ # check that p is in the active processes list
+ self.assertIn(ident, [id(o) for o in subprocess._active])
# let some time for the process to exit, and create a new Popen: this
# should trigger the wait() of p
pass
# p should have been wait()ed on, and removed from the _active list
self.assertRaises(OSError, os.waitpid, pid, 0)
- self.assertNotIn(ident, [id(o) for o in subprocess._active])
+ if mswindows:
+ # subprocess._active is not used on Windows and is set to None.
+ self.assertIsNone(subprocess._active)
+ else:
+ self.assertNotIn(ident, [id(o) for o in subprocess._active])
def test_close_fds_after_preexec(self):
fd_status = support.findfile("fd_status.py", subdir="subprocessdata")
-import unittest, test.support
+from test import support
from test.support.script_helper import assert_python_ok, assert_python_failure
-import sys, io, os
+import builtins
+import codecs
+import gc
+import locale
+import operator
+import os
import struct
import subprocess
+import sys
+import sysconfig
+import test.support
import textwrap
+import unittest
import warnings
-import operator
-import codecs
-import gc
-import sysconfig
-import locale
-import threading
+
# count the number of test runs, used to create unique
# strings to intern in test_intern()
-numruns = 0
+INTERN_NUMRUNS = 0
-class SysModuleTest(unittest.TestCase):
+class DisplayHookTest(unittest.TestCase):
- def setUp(self):
- self.orig_stdout = sys.stdout
- self.orig_stderr = sys.stderr
- self.orig_displayhook = sys.displayhook
+ def test_original_displayhook(self):
+ dh = sys.__displayhook__
- def tearDown(self):
- sys.stdout = self.orig_stdout
- sys.stderr = self.orig_stderr
- sys.displayhook = self.orig_displayhook
- test.support.reap_children()
+ with support.captured_stdout() as out:
+ dh(42)
- def test_original_displayhook(self):
- import builtins
- out = io.StringIO()
- sys.stdout = out
+ self.assertEqual(out.getvalue(), "42\n")
+ self.assertEqual(builtins._, 42)
- dh = sys.__displayhook__
+ del builtins._
- self.assertRaises(TypeError, dh)
- if hasattr(builtins, "_"):
- del builtins._
+ with support.captured_stdout() as out:
+ dh(None)
- dh(None)
self.assertEqual(out.getvalue(), "")
self.assertTrue(not hasattr(builtins, "_"))
- dh(42)
- self.assertEqual(out.getvalue(), "42\n")
- self.assertEqual(builtins._, 42)
- del sys.stdout
- self.assertRaises(RuntimeError, dh, 42)
+ # sys.displayhook() requires arguments
+ self.assertRaises(TypeError, dh)
+
+ stdout = sys.stdout
+ try:
+ del sys.stdout
+ self.assertRaises(RuntimeError, dh, 42)
+ finally:
+ sys.stdout = stdout
def test_lost_displayhook(self):
- del sys.displayhook
- code = compile("42", "<string>", "single")
- self.assertRaises(RuntimeError, eval, code)
+ displayhook = sys.displayhook
+ try:
+ del sys.displayhook
+ code = compile("42", "<string>", "single")
+ self.assertRaises(RuntimeError, eval, code)
+ finally:
+ sys.displayhook = displayhook
def test_custom_displayhook(self):
def baddisplayhook(obj):
raise ValueError
- sys.displayhook = baddisplayhook
- code = compile("42", "<string>", "single")
- self.assertRaises(ValueError, eval, code)
- def test_original_excepthook(self):
- err = io.StringIO()
- sys.stderr = err
+ with support.swap_attr(sys, 'displayhook', baddisplayhook):
+ code = compile("42", "<string>", "single")
+ self.assertRaises(ValueError, eval, code)
+
- eh = sys.__excepthook__
+class ExceptHookTest(unittest.TestCase):
- self.assertRaises(TypeError, eh)
+ def test_original_excepthook(self):
try:
raise ValueError(42)
except ValueError as exc:
- eh(*sys.exc_info())
+ with support.captured_stderr() as err:
+ sys.__excepthook__(*sys.exc_info())
self.assertTrue(err.getvalue().endswith("ValueError: 42\n"))
+ self.assertRaises(TypeError, sys.__excepthook__)
+
+ def test_excepthook_bytes_filename(self):
+ # bpo-37467: sys.excepthook() must not crash if a filename
+ # is a bytes string
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', BytesWarning)
+
+ try:
+ raise SyntaxError("msg", (b"bytes_filename", 123, 0, "text"))
+ except SyntaxError as exc:
+ with support.captured_stderr() as err:
+ sys.__excepthook__(*sys.exc_info())
+
+ err = err.getvalue()
+ self.assertIn(""" File "b'bytes_filename'", line 123\n""", err)
+ self.assertIn(""" text\n""", err)
+ self.assertTrue(err.endswith("SyntaxError: msg\n"))
+
def test_excepthook(self):
with test.support.captured_output("stderr") as stderr:
sys.excepthook(1, '1', 1)
# FIXME: testing the code for a lost or replaced excepthook in
# Python/pythonrun.c::PyErr_PrintEx() is tricky.
+
+class SysModuleTest(unittest.TestCase):
+
+ def tearDown(self):
+ test.support.reap_children()
+
def test_exit(self):
# call with two arguments
self.assertRaises(TypeError, sys.exit, 42, 42)
self.assertEqual(sys.__stdout__.encoding, sys.__stderr__.encoding)
def test_intern(self):
- global numruns
- numruns += 1
+ global INTERN_NUMRUNS
+ INTERN_NUMRUNS += 1
self.assertRaises(TypeError, sys.intern)
- s = "never interned before" + str(numruns)
+ s = "never interned before" + str(INTERN_NUMRUNS)
self.assertTrue(sys.intern(s) is s)
s2 = s.swapcase().swapcase()
self.assertTrue(sys.intern(s2) is s)
import errno
import io
import os
+import pathlib
import signal
import sys
import re
with self.assertRaises(TypeError):
tempfile._infer_return_type(b'', None, '')
+ def test_infer_return_type_pathlib(self):
+ self.assertIs(str, tempfile._infer_return_type(pathlib.Path('/')))
+
# Common functionality.
nsuf = nbase[len(nbase)-len(suf):]
if dir is not None:
- self.assertIs(type(name), str if type(dir) is str else bytes,
- "unexpected return type")
+ self.assertIs(
+ type(name),
+ str
+ if type(dir) is str or isinstance(dir, os.PathLike) else
+ bytes,
+ "unexpected return type",
+ )
if pre is not None:
self.assertIs(type(name), str if type(pre) is str else bytes,
"unexpected return type")
dir = tempfile.mkdtemp()
try:
self.do_create(dir=dir).write(b"blat")
+ self.do_create(dir=pathlib.Path(dir)).write(b"blat")
finally:
os.rmdir(dir)
dir = tempfile.mkdtemp()
try:
self.do_create(dir=dir)
+ self.do_create(dir=pathlib.Path(dir))
finally:
os.rmdir(dir)
dir = tempfile.mkdtemp()
try:
os.rmdir(self.do_create(dir=dir))
+ os.rmdir(self.do_create(dir=pathlib.Path(dir)))
finally:
os.rmdir(dir)
def tearDown(self):
self.sock.close()
+ @unittest.skipIf(True, 'need to replace these hosts; see bpo-35518')
def testConnectTimeout(self):
# Testing connect timeout is tricky: we need to have IP connectivity
# to a host that silently drops our packets. We can't simulate this
with self.assertRaises(TypeError):
NamedTuple('Name', x=1, y='a')
+ def test_namedtuple_special_keyword_names(self):
+ NT = NamedTuple("NT", cls=type, self=object, typename=str, fields=list)
+ self.assertEqual(NT.__name__, 'NT')
+ self.assertEqual(NT._fields, ('cls', 'self', 'typename', 'fields'))
+ a = NT(cls=str, self=42, typename='foo', fields=[('bar', tuple)])
+ self.assertEqual(a.cls, str)
+ self.assertEqual(a.self, 42)
+ self.assertEqual(a.typename, 'foo')
+ self.assertEqual(a.fields, [('bar', tuple)])
+
+ def test_namedtuple_errors(self):
+ with self.assertRaises(TypeError):
+ NamedTuple.__new__()
+ with self.assertRaises(TypeError):
+ NamedTuple()
+ with self.assertRaises(TypeError):
+ NamedTuple('Emp', [('name', str)], None)
+ with self.assertRaises(ValueError):
+ NamedTuple('Emp', [('_name', str)])
+
+ Emp = NamedTuple(typename='Emp', name=str, id=int)
+ self.assertEqual(Emp.__name__, 'Emp')
+ self.assertEqual(Emp._fields, ('name', 'id'))
+
+ Emp = NamedTuple('Emp', fields=[('name', str), ('id', int)])
+ self.assertEqual(Emp.__name__, 'Emp')
+ self.assertEqual(Emp._fields, ('name', 'id'))
+
def test_pickle(self):
global Emp # pickle wants to reference the class by name
Emp = NamedTuple('Emp', [('name', str), ('id', int)])
import operator
import struct
import sys
+import unicodedata
import unittest
import warnings
from test import support, string_tests
self.checkequalnofix(True, '\u2000', 'isspace')
self.checkequalnofix(True, '\u200a', 'isspace')
self.checkequalnofix(False, '\u2014', 'isspace')
- # apparently there are no non-BMP spaces chars in Unicode 6
+ # There are no non-BMP whitespace chars as of Unicode 12.
for ch in ['\U00010401', '\U00010427', '\U00010429', '\U0001044E',
'\U0001F40D', '\U0001F46F']:
self.assertFalse(ch.isspace(), '{!a} is not space.'.format(ch))
+ @support.requires_resource('cpu')
+ def test_isspace_invariant(self):
+ for codepoint in range(sys.maxunicode + 1):
+ char = chr(codepoint)
+ bidirectional = unicodedata.bidirectional(char)
+ category = unicodedata.category(char)
+ self.assertEqual(char.isspace(),
+ (bidirectional in ('WS', 'B', 'S')
+ or category == 'Zs'))
+
def test_isalnum(self):
super().test_isalnum()
for ch in ['\U00010401', '\U00010427', '\U00010429', '\U0001044E',
if sys.platform == 'darwin' or support.is_android:
c_arg = arg_utf8
+ elif sys.platform.startswith("aix"):
+ c_arg = arg.decode('iso-8859-1')
else:
c_arg = arg_ascii
for loc in POSIX_LOCALES:
import os
import os.path
import re
+import shutil
import struct
import subprocess
import sys
'pool.terminate()'])
self.assertEqual(out.strip(), "python".encode())
+ @unittest.skipIf(os.name == 'nt', 'not relevant on Windows')
+ def test_deactivate_with_strict_bash_opts(self):
+ bash = shutil.which("bash")
+ if bash is None:
+ self.skipTest("bash required for this test")
+ rmtree(self.env_dir)
+ builder = venv.EnvBuilder(clear=True)
+ builder.create(self.env_dir)
+ activate = os.path.join(self.env_dir, self.bindir, "activate")
+ test_script = os.path.join(self.env_dir, "test_strict.sh")
+ with open(test_script, "w") as f:
+ f.write("set -euo pipefail\n"
+ f"source {activate}\n"
+ "deactivate\n")
+ out, err = check_output([bash, test_script])
+ self.assertEqual(out, "".encode())
+ self.assertEqual(err, "".encode())
+
+
@requireVenvCreate
class EnsurePipTest(BaseTest):
"""Test venv module installation of pip."""
# Please check the permissions and owner of that directory. If
# executing pip with sudo, you may want sudo's -H flag."
# where $HOME is replaced by the HOME environment variable.
- err = re.sub("^The directory .* or its parent directory is not owned "
- "by the current user .*$", "", err, flags=re.MULTILINE)
+ err = re.sub("^(WARNING: )?The directory .* or its parent directory "
+ "is not owned by the current user .*$", "",
+ err, flags=re.MULTILINE)
self.assertEqual(err.rstrip(), "")
# Being fairly specific regarding the expected behaviour for the
# initial bundling phase in Python 3.4. If the output changes in
# copying should not result in a crash.
self.check_threaded_weak_dict_copy(weakref.WeakValueDictionary, True)
+ @support.cpython_only
+ def test_remove_closure(self):
+ d = weakref.WeakValueDictionary()
+ self.assertIsNone(d._remove.__closure__)
+
from test import mapping_tests
("String Val", "A string value", REG_SZ),
("StringExpand", "The path is %path%", REG_EXPAND_SZ),
("Multi-string", ["Lots", "of", "string", "values"], REG_MULTI_SZ),
+ ("Multi-nul", ["", "", "", ""], REG_MULTI_SZ),
("Raw Data", b"binary\x00data", REG_BINARY),
("Big String", "x"*(2**14-1), REG_SZ),
("Big Binary", b"x"*(2**14), REG_BINARY),
class HandlerTests(TestCase):
-
- def checkEnvironAttrs(self, handler):
- env = handler.environ
- for attr in [
- 'version','multithread','multiprocess','run_once','file_wrapper'
- ]:
- if attr=='file_wrapper' and handler.wsgi_file_wrapper is None:
- continue
- self.assertEqual(getattr(handler,'wsgi_'+attr),env['wsgi.'+attr])
-
- def checkOSEnviron(self,handler):
- empty = {}; setup_testing_defaults(empty)
- env = handler.environ
- from os import environ
- for k,v in environ.items():
- if k not in empty:
- self.assertEqual(env[k],v)
- for k,v in empty.items():
- self.assertIn(k, env)
+ # testEnviron() can produce long error message
+ maxDiff = 80 * 50
def testEnviron(self):
- h = TestHandler(X="Y")
- h.setup_environ()
- self.checkEnvironAttrs(h)
- self.checkOSEnviron(h)
- self.assertEqual(h.environ["X"],"Y")
+ os_environ = {
+ # very basic environment
+ 'HOME': '/my/home',
+ 'PATH': '/my/path',
+ 'LANG': 'fr_FR.UTF-8',
+
+ # set some WSGI variables
+ 'SCRIPT_NAME': 'test_script_name',
+ 'SERVER_NAME': 'test_server_name',
+ }
+
+ with support.swap_attr(TestHandler, 'os_environ', os_environ):
+ # override X and HOME variables
+ handler = TestHandler(X="Y", HOME="/override/home")
+ handler.setup_environ()
+
+ # Check that wsgi_xxx attributes are copied to wsgi.xxx variables
+ # of handler.environ
+ for attr in ('version', 'multithread', 'multiprocess', 'run_once',
+ 'file_wrapper'):
+ self.assertEqual(getattr(handler, 'wsgi_' + attr),
+ handler.environ['wsgi.' + attr])
+
+ # Test handler.environ as a dict
+ expected = {}
+ setup_testing_defaults(expected)
+ # Handler inherits os_environ variables which are not overriden
+ # by SimpleHandler.add_cgi_vars() (SimpleHandler.base_env)
+ for key, value in os_environ.items():
+ if key not in expected:
+ expected[key] = value
+ expected.update({
+ # X doesn't exist in os_environ
+ "X": "Y",
+ # HOME is overriden by TestHandler
+ 'HOME': "/override/home",
+
+ # overriden by setup_testing_defaults()
+ "SCRIPT_NAME": "",
+ "SERVER_NAME": "127.0.0.1",
+
+ # set by BaseHandler.setup_environ()
+ 'wsgi.input': handler.get_stdin(),
+ 'wsgi.errors': handler.get_stderr(),
+ 'wsgi.version': (1, 0),
+ 'wsgi.run_once': False,
+ 'wsgi.url_scheme': 'http',
+ 'wsgi.multithread': True,
+ 'wsgi.multiprocess': True,
+ 'wsgi.file_wrapper': util.FileWrapper,
+ })
+ self.assertDictEqual(handler.environ, expected)
def testCGIEnviron(self):
h = BaseCGIHandler(None,None,None,{})
Note that tabs and spaces are both treated as whitespace, but they
are not equal: the lines " hello" and "\\thello" are
- considered to have no common leading whitespace. (This behaviour is
- new in Python 2.5; older versions of this module incorrectly
- expanded tabs before searching for common leading whitespace.)
+ considered to have no common leading whitespace.
+
+ Entirely blank lines are normalized to a newline character.
"""
# Look for the longest leading string of spaces and tabs common to
# all lines.
main thread is not a daemon thread and therefore all threads created in
the main thread default to daemon = False.
- The entire Python program exits when no alive non-daemon threads are
- left.
+ The entire Python program exits when only daemon threads are left.
"""
assert self._initialized, "Thread.__init__() not called"
"""
_root = True
- def __new__(self, typename, fields=None, **kwargs):
+ def __new__(*args, **kwargs):
+ if not args:
+ raise TypeError('NamedTuple.__new__(): not enough arguments')
+ cls, *args = args # allow the "cls" keyword be passed
+ if args:
+ typename, *args = args # allow the "typename" keyword be passed
+ elif 'typename' in kwargs:
+ typename = kwargs.pop('typename')
+ else:
+ raise TypeError("NamedTuple.__new__() missing 1 required positional "
+ "argument: 'typename'")
+ if args:
+ try:
+ fields, = args # allow the "fields" keyword be passed
+ except ValueError:
+ raise TypeError(f'NamedTuple.__new__() takes from 2 to 3 '
+ f'positional arguments but {len(args) + 2} '
+ f'were given') from None
+ elif 'fields' in kwargs and len(kwargs) == 1:
+ fields = kwargs.pop('fields')
+ else:
+ fields = None
+
if fields is None:
fields = kwargs.items()
elif kwargs:
raise TypeError("Either list of fields or keywords"
" can be provided to NamedTuple, not both")
return _make_nmtuple(typename, fields)
+ __new__.__text_signature__ = '($cls, typename, fields=None, /, **kwargs)'
def NewType(name, tp):
)
+def _extract_mock(obj):
+ # Autospecced functions will return a FunctionType with "mock" attribute
+ # which is the actual mock object that needs to be used.
+ if isinstance(obj, FunctionTypes) and hasattr(obj, 'mock'):
+ return obj.mock
+ else:
+ return obj
+
+
def _get_signature_object(func, as_instance, eat_self):
"""
Given an arbitrary, possibly callable object, try to create a suitable
def _check_and_set_parent(parent, value, name, new_name):
- # function passed to create_autospec will have mock
- # attribute attached to which parent must be set
- if isinstance(value, FunctionTypes):
- try:
- value = value.mock
- except AttributeError:
- pass
+ value = _extract_mock(value)
if not _is_instance_mock(value):
return False
Attach a mock as an attribute of this one, replacing its name and
parent. Calls to the attached mock will be recorded in the
`method_calls` and `mock_calls` attributes of this one."""
- mock._mock_parent = None
- mock._mock_new_parent = None
- mock._mock_name = ''
- mock._mock_new_name = None
+ inner_mock = _extract_mock(mock)
+
+ inner_mock._mock_parent = None
+ inner_mock._mock_new_parent = None
+ inner_mock._mock_name = ''
+ inner_mock._mock_new_name = None
setattr(self, attribute, mock)
return message % (expected_string, actual_string)
+ def _get_call_signature_from_name(self, name):
+ """
+ * If call objects are asserted against a method/function like obj.meth1
+ then there could be no name for the call object to lookup. Hence just
+ return the spec_signature of the method/function being asserted against.
+ * If the name is not empty then remove () and split by '.' to get
+ list of names to iterate through the children until a potential
+ match is found. A child mock is created only during attribute access
+ so if we get a _SpecState then no attributes of the spec were accessed
+ and can be safely exited.
+ """
+ if not name:
+ return self._spec_signature
+
+ sig = None
+ names = name.replace('()', '').split('.')
+ children = self._mock_children
+
+ for name in names:
+ child = children.get(name)
+ if child is None or isinstance(child, _SpecState):
+ break
+ else:
+ children = child._mock_children
+ sig = child._spec_signature
+
+ return sig
+
+
def _call_matcher(self, _call):
"""
Given a call (or simply an (args, kwargs) tuple), return a
This is a best effort method which relies on the spec's signature,
if available, or falls back on the arguments themselves.
"""
- sig = self._spec_signature
+
+ if isinstance(_call, tuple) and len(_call) > 2:
+ sig = self._get_call_signature_from_name(_call[0])
+ else:
+ sig = self._spec_signature
+
if sig is not None:
if len(_call) == 2:
name = ''
If `any_order` is True then the calls can be in any order, but
they must all appear in `mock_calls`."""
expected = [self._call_matcher(c) for c in calls]
- cause = expected if isinstance(expected, Exception) else None
+ cause = next((e for e in expected if isinstance(e, Exception)), None)
all_calls = _CallList(self._call_matcher(c) for c in self.mock_calls)
if not any_order:
if expected not in all_calls:
+ if cause is None:
+ problem = 'Calls not found.'
+ else:
+ problem = ('Error processing expected calls.\n'
+ 'Errors: {}').format(
+ [e if isinstance(e, Exception) else None
+ for e in expected])
raise AssertionError(
- 'Calls not found.\nExpected: %r\n'
- 'Actual: %r' % (_CallList(calls), self.mock_calls)
+ '%s\nExpected: %r\nActual: %r' % (
+ problem, _CallList(calls), self.mock_calls)
) from cause
return
method.return_value = fixed
return
- return_calulator = _calculate_return_value.get(name)
- if return_calulator is not None:
+ return_calculator = _calculate_return_value.get(name)
+ if return_calculator is not None:
try:
- return_value = return_calulator(mock)
+ return_value = return_calculator(mock)
except AttributeError:
# XXXX why do we return AttributeError here?
# set it as a side_effect instead?
import copy
+import re
import sys
import tempfile
pass
+def something(a): pass
+
+
class MockTest(unittest.TestCase):
def test_all(self):
)
+ def test_assert_has_calls_nested_spec(self):
+ class Something:
+
+ def __init__(self): pass
+ def meth(self, a, b, c, d=None): pass
+
+ class Foo:
+
+ def __init__(self, a): pass
+ def meth1(self, a, b): pass
+
+ mock_class = create_autospec(Something)
+
+ for m in [mock_class, mock_class()]:
+ m.meth(1, 2, 3, d=1)
+ m.assert_has_calls([call.meth(1, 2, 3, d=1)])
+ m.assert_has_calls([call.meth(1, 2, 3, 1)])
+
+ mock_class.reset_mock()
+
+ for m in [mock_class, mock_class()]:
+ self.assertRaises(AssertionError, m.assert_has_calls, [call.Foo()])
+ m.Foo(1).meth1(1, 2)
+ m.assert_has_calls([call.Foo(1), call.Foo(1).meth1(1, 2)])
+ m.Foo.assert_has_calls([call(1), call().meth1(1, 2)])
+
+ mock_class.reset_mock()
+
+ invalid_calls = [call.meth(1),
+ call.non_existent(1),
+ call.Foo().non_existent(1),
+ call.Foo().meth(1, 2, 3, 4)]
+
+ for kall in invalid_calls:
+ self.assertRaises(AssertionError,
+ mock_class.assert_has_calls,
+ [kall]
+ )
+
+
+ def test_assert_has_calls_nested_without_spec(self):
+ m = MagicMock()
+ m().foo().bar().baz()
+ m.one().two().three()
+ calls = call.one().two().three().call_list()
+ m.assert_has_calls(calls)
+
+
def test_assert_has_calls_with_function_spec(self):
def f(a, b, c, d=None):
pass
mock.assert_has_calls(calls[:-1])
mock.assert_has_calls(calls[:-1], any_order=True)
+ def test_assert_has_calls_not_matching_spec_error(self):
+ def f(x=None): pass
+
+ mock = Mock(spec=f)
+ mock(1)
+
+ with self.assertRaisesRegex(
+ AssertionError,
+ '^{}$'.format(
+ re.escape('Calls not found.\n'
+ 'Expected: [call()]\n'
+ 'Actual: [call(1)]'))) as cm:
+ mock.assert_has_calls([call()])
+ self.assertIsNone(cm.exception.__cause__)
+
+
+ with self.assertRaisesRegex(
+ AssertionError,
+ '^{}$'.format(
+ re.escape(
+ 'Error processing expected calls.\n'
+ "Errors: [None, TypeError('too many positional arguments')]\n"
+ "Expected: [call(), call(1, 2)]\n"
+ 'Actual: [call(1)]'))) as cm:
+ mock.assert_has_calls([call(), call(1, 2)])
+ self.assertIsInstance(cm.exception.__cause__, TypeError)
def test_assert_any_call(self):
mock = Mock()
self.assertEqual(m.mock_calls, call().foo().call_list())
+ def test_attach_mock_patch_autospec(self):
+ parent = Mock()
+
+ with mock.patch(f'{__name__}.something', autospec=True) as mock_func:
+ self.assertEqual(mock_func.mock._extract_mock_name(), 'something')
+ parent.attach_mock(mock_func, 'child')
+ parent.child(1)
+ something(2)
+ mock_func(3)
+
+ parent_calls = [call.child(1), call.child(2), call.child(3)]
+ child_calls = [call(1), call(2), call(3)]
+ self.assertEqual(parent.mock_calls, parent_calls)
+ self.assertEqual(parent.child.mock_calls, child_calls)
+ self.assertEqual(something.mock_calls, child_calls)
+ self.assertEqual(mock_func.mock_calls, child_calls)
+ self.assertIn('mock.child', repr(parent.child.mock))
+ self.assertEqual(mock_func.mock._extract_mock_name(), 'mock.child')
+
+
def test_attribute_deletion(self):
for mock in (Mock(), MagicMock(), NonCallableMagicMock(),
NonCallableMock()):
self.assertRaises(TypeError, mock.child, 1)
self.assertEqual(mock.mock_calls, [call.child(1, 2)])
+ self.assertIn('mock.child', repr(mock.child.mock))
+
+ def test_parent_propagation_with_autospec_attach_mock(self):
+
+ def foo(a, b): pass
+
+ parent = Mock()
+ parent.attach_mock(create_autospec(foo, name='bar'), 'child')
+ parent.child(1, 2)
+
+ self.assertRaises(TypeError, parent.child, 1)
+ self.assertEqual(parent.child.mock_calls, [call.child(1, 2)])
+ self.assertIn('mock.child', repr(parent.child.mock))
+
def test_isinstance_under_settrace(self):
# bpo-36593 : __class__ is not set for a class that has __class__
self.__dict__['is_safe'] = is_safe
def __getstate__(self):
- state = self.__dict__
+ state = self.__dict__.copy()
if self.is_safe != SafeUUID.unknown:
# is_safe is a SafeUUID instance. Return just its value, so that
# it can be un-pickled in older Python versions without SafeUUID.
- state = state.copy()
state['is_safe'] = self.is_safe.value
+ else:
+ # omit is_safe when it is "unknown"
+ del state['is_safe']
return state
def __setstate__(self, state):
fi
unset VIRTUAL_ENV
- if [ ! "$1" = "nondestructive" ] ; then
+ if [ ! "${1:-}" = "nondestructive" ] ; then
# Self destruct!
unset -f deactivate
fi
\r
rem This file is UTF-8 encoded, so we need to update the current code page while executing it\r
for /f "tokens=2 delims=:." %%a in ('"%SystemRoot%\System32\chcp.com"') do (\r
- set "_OLD_CODEPAGE=%%a"\r
+ set _OLD_CODEPAGE=%%a\r
)\r
if defined _OLD_CODEPAGE (\r
"%SystemRoot%\System32\chcp.com" 65001 > nul\r
)\r
\r
-set "VIRTUAL_ENV=__VENV_DIR__"\r
+set VIRTUAL_ENV=__VENV_DIR__\r
\r
-if not defined PROMPT (\r
- set "PROMPT=$P$G"\r
-)\r
-\r
-if defined _OLD_VIRTUAL_PROMPT (\r
- set "PROMPT=%_OLD_VIRTUAL_PROMPT%"\r
-)\r
+if not defined PROMPT set PROMPT=$P$G\r
\r
-if defined _OLD_VIRTUAL_PYTHONHOME (\r
- set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%"\r
-)\r
+if defined _OLD_VIRTUAL_PROMPT set PROMPT=%_OLD_VIRTUAL_PROMPT%\r
+if defined _OLD_VIRTUAL_PYTHONHOME set PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%\r
\r
-set "_OLD_VIRTUAL_PROMPT=%PROMPT%"\r
-set "PROMPT=__VENV_PROMPT__%PROMPT%"\r
+set _OLD_VIRTUAL_PROMPT=%PROMPT%\r
+set PROMPT=__VENV_PROMPT__%PROMPT%\r
\r
-if defined PYTHONHOME (\r
- set "_OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME%"\r
- set PYTHONHOME=\r
-)\r
+if defined PYTHONHOME set _OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME%\r
+set PYTHONHOME=\r
\r
-if defined _OLD_VIRTUAL_PATH (\r
- set "PATH=%_OLD_VIRTUAL_PATH%"\r
-) else (\r
- set "_OLD_VIRTUAL_PATH=%PATH%"\r
-)\r
+if defined _OLD_VIRTUAL_PATH set PATH=%_OLD_VIRTUAL_PATH%\r
+if not defined _OLD_VIRTUAL_PATH set _OLD_VIRTUAL_PATH=%PATH%\r
\r
-set "PATH=%VIRTUAL_ENV%\__VENV_BIN_NAME__;%PATH%"\r
+set PATH=%VIRTUAL_ENV%\__VENV_BIN_NAME__;%PATH%\r
\r
:END\r
if defined _OLD_CODEPAGE (\r
"%SystemRoot%\System32\chcp.com" %_OLD_CODEPAGE% > nul\r
- set "_OLD_CODEPAGE="\r
+ set _OLD_CODEPAGE=\r
)\r
else:
# Atomic removal is necessary since this function
# can be called asynchronously by the GC
- _atomic_removal(d, wr.key)
+ _atomic_removal(self.data, wr.key)
self._remove = remove
# A list of keys to be removed
self._pending_removals = []
self._iterating = set()
- self.data = d = {}
+ self.data = {}
self.update(*args, **kw)
def _commit_removals(self):
from http.server import BaseHTTPRequestHandler
from functools import partial
from inspect import signature
+import html
import http.server
import socketserver
import sys
methods
)
- return documenter.page(self.server_title, documentation)
+ return documenter.page(html.escape(self.server_title), documentation)
class DocXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
"""XML-RPC and documentation request handler class.
--- /dev/null
+Building a Python Mac OS X distribution
+=======================================
+
+The ``build-install.py`` script creates Python distributions, including
+certain third-party libraries as necessary. It builds a complete
+framework-based Python out-of-tree, installs it in a funny place with
+$DESTROOT, massages that installation to remove .pyc files and such, creates
+an Installer package from the installation plus other files in ``resources``
+and ``scripts`` and placed that on a ``.dmg`` disk image.
+
+For Python 3.4.0, PSF practice is to build two installer variants
+for each release.
+
+1. 32-bit-only, i386 and PPC universal, capable on running on all machines
+ supported by Mac OS X 10.5 through (at least) 10.9::
+
+ /path/to/bootstrap/python2.7 build-installer.py \
+ --sdk-path=/Developer/SDKs/MacOSX10.5.sdk \
+ --universal-archs=32-bit \
+ --dep-target=10.5
+
+ - builds the following third-party libraries
+
+ * NCurses 5.9 (http://bugs.python.org/issue15037)
+ * SQLite 3.8.11
+ * XZ 5.0.5
+
+ - uses system-supplied versions of third-party libraries
+
+ * readline module links with Apple BSD editline (libedit)
+
+ - requires ActiveState ``Tcl/Tk 8.4`` (currently 8.4.20) to be installed for building
+
+ - recommended build environment:
+
+ * Mac OS X 10.5.8 Intel or PPC
+ * Xcode 3.1.4
+ * ``MacOSX10.5`` SDK
+ * ``MACOSX_DEPLOYMENT_TARGET=10.5``
+ * Apple ``gcc-4.2``
+ * bootstrap non-framework Python 2.7 for documentation build with
+ Sphinx (as of 3.4.1)
+
+ - alternate build environments:
+
+ * Mac OS X 10.6.8 with Xcode 3.2.6
+ - need to change ``/System/Library/Frameworks/{Tcl,Tk}.framework/Version/Current`` to ``8.4``
+ * Note Xcode 4.* does not support building for PPC so cannot be used for this build
+
+2. 64-bit / 32-bit, x86_64 and i386 universal, for OS X 10.6 (and later)::
+
+ /path/to/bootstrap/python2.7 build-installer.py \
+ --sdk-path=/Developer/SDKs/MacOSX10.6.sdk \
+ --universal-archs=intel \
+ --dep-target=10.6
+
+ - builds the following third-party libraries
+
+ * NCurses 5.9 (http://bugs.python.org/issue15037)
+ * SQLite 3.8.11
+ * XZ 5.0.5
+
+ - uses system-supplied versions of third-party libraries
+
+ * readline module links with Apple BSD editline (libedit)
+
+ - requires ActiveState Tcl/Tk 8.5.15.1 (or later) to be installed for building
+
+ - recommended build environment:
+
+ * Mac OS X 10.6.8 (or later)
+ * Xcode 3.2.6
+ * ``MacOSX10.6`` SDK
+ * ``MACOSX_DEPLOYMENT_TARGET=10.6``
+ * Apple ``gcc-4.2``
+ * bootstrap non-framework Python 2.7 for documentation build with
+ Sphinx (as of 3.4.1)
+
+ - alternate build environments:
+
+ * none. Xcode 4.x currently supplies two C compilers.
+ ``llvm-gcc-4.2.1`` has been found to miscompile Python 3.3.x and
+ produce a non-functional Python executable. As it appears to be
+ considered a migration aid by Apple and is not likely to be fixed,
+ its use should be avoided. The other compiler, ``clang``, has been
+ undergoing rapid development. While it appears to have become
+ production-ready in the most recent Xcode 5 releases, the versions
+ available on the deprecated Xcode 4.x for 10.6 were early releases
+ and did not receive the level of exposure in production environments
+ that the Xcode 3 gcc-4.2 compiler has had.
+
+
+* For Python 2.7.x and 3.2.x, the 32-bit-only installer was configured to
+ support Mac OS X 10.3.9 through (at least) 10.6. Because it is
+ believed that there are few systems still running OS X 10.3 or 10.4
+ and because it has become increasingly difficult to test and
+ support the differences in these earlier systems, as of Python 3.3.0 the PSF
+ 32-bit installer no longer supports them. For reference in building such
+ an installer yourself, the details are::
+
+ /usr/bin/python build-installer.py \
+ --sdk-path=/Developer/SDKs/MacOSX10.4u.sdk \
+ --universal-archs=32-bit \
+ --dep-target=10.3
+
+ - builds the following third-party libraries
+
+ * Bzip2
+ * NCurses
+ * GNU Readline (GPL)
+ * SQLite 3
+ * XZ
+ * Zlib 1.2.3
+ * Oracle Sleepycat DB 4.8 (Python 2.x only)
+
+ - requires ActiveState ``Tcl/Tk 8.4`` (currently 8.4.20) to be installed for building
+
+ - recommended build environment:
+
+ * Mac OS X 10.5.8 PPC or Intel
+ * Xcode 3.1.4 (or later)
+ * ``MacOSX10.4u`` SDK (later SDKs do not support PPC G3 processors)
+ * ``MACOSX_DEPLOYMENT_TARGET=10.3``
+ * Apple ``gcc-4.0``
+ * system Python 2.5 for documentation build with Sphinx
+
+ - alternate build environments:
+
+ * Mac OS X 10.6.8 with Xcode 3.2.6
+ - need to change ``/System/Library/Frameworks/{Tcl,Tk}.framework/Version/Current`` to ``8.4``
+
+
+
+General Prerequisites
+---------------------
+
+* No Fink (in ``/sw``) or MacPorts (in ``/opt/local``) or other local
+ libraries or utilities (in ``/usr/local``) as they could
+ interfere with the build.
+
+* The documentation for the release is built using Sphinx
+ because it is included in the installer. For 2.7.x and 3.x.x up to and
+ including 3.4.0, the ``Doc/Makefile`` uses ``svn`` to download repos of
+ ``Sphinx`` and its dependencies. Beginning with 3.4.1, the ``Doc/Makefile``
+ assumes there is an externally-provided ``sphinx-build`` and requires at
+ least Python 2.6 to run. Because of this, it is no longer possible to
+ build a 3.4.1 or later installer on OS X 10.5 using the Apple-supplied
+ Python 2.5.
+
+* It is safest to start each variant build with an empty source directory
+ populated with a fresh copy of the untarred source.
+
+* It is recommended that you remove any existing installed version of the
+ Python being built::
+
+ sudo rm -rf /Library/Frameworks/Python.framework/Versions/n.n
+
+
+The Recipe
+----------
+
+Here are the steps you need to follow to build a Python installer:
+
+* Run ``build-installer.py``. Optionally you can pass a number of arguments
+ to specify locations of various files. Please see the top of
+ ``build-installer.py`` for its usage.
+
+ Running this script takes some time, it will not only build Python itself
+ but also some 3th-party libraries that are needed for extensions.
+
+* When done the script will tell you where the DMG image is (by default
+ somewhere in ``/tmp/_py``).
+
+Building other universal installers
+...................................
+
+It is also possible to build a 4-way universal installer that runs on
+OS X 10.5 Leopard or later::
+
+ /usr/bin/python /build-installer.py \
+ --dep-target=10.5
+ --universal-archs=all
+ --sdk-path=/Developer/SDKs/MacOSX10.5.sdk
+
+This requires that the deployment target is 10.5, and hence
+also that you are building on at least OS X 10.5. 4-way includes
+``i386``, ``x86_64``, ``ppc``, and ``ppc64`` (G5). ``ppc64`` executable
+variants can only be run on G5 machines running 10.5. Note that,
+while OS X 10.6 is only supported on Intel-based machines, it is possible
+to run ``ppc`` (32-bit) executables unmodified thanks to the Rosetta ppc
+emulation in OS X 10.5 and 10.6. The 4-way installer variant must be
+built with Xcode 3. It is not regularly built or tested.
+
+Other ``--universal-archs`` options are ``64-bit`` (``x86_64``, ``ppc64``),
+and ``3-way`` (``ppc``, ``i386``, ``x86_64``). None of these options
+are regularly exercised; use at your own risk.
+
+
+Testing
+-------
+
+Ideally, the resulting binaries should be installed and the test suite run
+on all supported OS X releases and architectures. As a practical matter,
+that is generally not possible. At a minimum, variant 1 should be run on
+a PPC G4 system with OS X 10.5 and at least one Intel system running OS X
+10.9, 10.8, 10.7, 10.6, or 10.5. Variant 2 should be run on 10.9, 10.8,
+10.7, and 10.6 systems in both 32-bit and 64-bit modes.::
+
+ /usr/local/bin/pythonn.n -m test -w -u all,-largefile
+ /usr/local/bin/pythonn.n-32 -m test -w -u all
+
+Certain tests will be skipped and some cause the interpreter to fail
+which will likely generate ``Python quit unexpectedly`` alert messages
+to be generated at several points during a test run. These are normal
+during testing and can be ignored.
+
+It is also recommend to launch IDLE and verify that it is at least
+functional. Double-click on the IDLE app icon in ``/Applications/Python n.n``.
+It should also be tested from the command line::
+
+ /usr/local/bin/idlen.n
+
+++ /dev/null
-Building a Python Mac OS X distribution
-=======================================
-
-The ``build-install.py`` script creates Python distributions, including
-certain third-party libraries as necessary. It builds a complete
-framework-based Python out-of-tree, installs it in a funny place with
-$DESTROOT, massages that installation to remove .pyc files and such, creates
-an Installer package from the installation plus other files in ``resources``
-and ``scripts`` and placed that on a ``.dmg`` disk image.
-
-For Python 3.4.0, PSF practice is to build two installer variants
-for each release.
-
-1. 32-bit-only, i386 and PPC universal, capable on running on all machines
- supported by Mac OS X 10.5 through (at least) 10.9::
-
- /path/to/bootstrap/python2.7 build-installer.py \
- --sdk-path=/Developer/SDKs/MacOSX10.5.sdk \
- --universal-archs=32-bit \
- --dep-target=10.5
-
- - builds the following third-party libraries
-
- * NCurses 5.9 (http://bugs.python.org/issue15037)
- * SQLite 3.8.11
- * XZ 5.0.5
-
- - uses system-supplied versions of third-party libraries
-
- * readline module links with Apple BSD editline (libedit)
-
- - requires ActiveState ``Tcl/Tk 8.4`` (currently 8.4.20) to be installed for building
-
- - recommended build environment:
-
- * Mac OS X 10.5.8 Intel or PPC
- * Xcode 3.1.4
- * ``MacOSX10.5`` SDK
- * ``MACOSX_DEPLOYMENT_TARGET=10.5``
- * Apple ``gcc-4.2``
- * bootstrap non-framework Python 2.7 for documentation build with
- Sphinx (as of 3.4.1)
-
- - alternate build environments:
-
- * Mac OS X 10.6.8 with Xcode 3.2.6
- - need to change ``/System/Library/Frameworks/{Tcl,Tk}.framework/Version/Current`` to ``8.4``
- * Note Xcode 4.* does not support building for PPC so cannot be used for this build
-
-2. 64-bit / 32-bit, x86_64 and i386 universal, for OS X 10.6 (and later)::
-
- /path/to/bootstrap/python2.7 build-installer.py \
- --sdk-path=/Developer/SDKs/MacOSX10.6.sdk \
- --universal-archs=intel \
- --dep-target=10.6
-
- - builds the following third-party libraries
-
- * NCurses 5.9 (http://bugs.python.org/issue15037)
- * SQLite 3.8.11
- * XZ 5.0.5
-
- - uses system-supplied versions of third-party libraries
-
- * readline module links with Apple BSD editline (libedit)
-
- - requires ActiveState Tcl/Tk 8.5.15.1 (or later) to be installed for building
-
- - recommended build environment:
-
- * Mac OS X 10.6.8 (or later)
- * Xcode 3.2.6
- * ``MacOSX10.6`` SDK
- * ``MACOSX_DEPLOYMENT_TARGET=10.6``
- * Apple ``gcc-4.2``
- * bootstrap non-framework Python 2.7 for documentation build with
- Sphinx (as of 3.4.1)
-
- - alternate build environments:
-
- * none. Xcode 4.x currently supplies two C compilers.
- ``llvm-gcc-4.2.1`` has been found to miscompile Python 3.3.x and
- produce a non-functional Python executable. As it appears to be
- considered a migration aid by Apple and is not likely to be fixed,
- its use should be avoided. The other compiler, ``clang``, has been
- undergoing rapid development. While it appears to have become
- production-ready in the most recent Xcode 5 releases, the versions
- available on the deprecated Xcode 4.x for 10.6 were early releases
- and did not receive the level of exposure in production environments
- that the Xcode 3 gcc-4.2 compiler has had.
-
-
-* For Python 2.7.x and 3.2.x, the 32-bit-only installer was configured to
- support Mac OS X 10.3.9 through (at least) 10.6. Because it is
- believed that there are few systems still running OS X 10.3 or 10.4
- and because it has become increasingly difficult to test and
- support the differences in these earlier systems, as of Python 3.3.0 the PSF
- 32-bit installer no longer supports them. For reference in building such
- an installer yourself, the details are::
-
- /usr/bin/python build-installer.py \
- --sdk-path=/Developer/SDKs/MacOSX10.4u.sdk \
- --universal-archs=32-bit \
- --dep-target=10.3
-
- - builds the following third-party libraries
-
- * Bzip2
- * NCurses
- * GNU Readline (GPL)
- * SQLite 3
- * XZ
- * Zlib 1.2.3
- * Oracle Sleepycat DB 4.8 (Python 2.x only)
-
- - requires ActiveState ``Tcl/Tk 8.4`` (currently 8.4.20) to be installed for building
-
- - recommended build environment:
-
- * Mac OS X 10.5.8 PPC or Intel
- * Xcode 3.1.4 (or later)
- * ``MacOSX10.4u`` SDK (later SDKs do not support PPC G3 processors)
- * ``MACOSX_DEPLOYMENT_TARGET=10.3``
- * Apple ``gcc-4.0``
- * system Python 2.5 for documentation build with Sphinx
-
- - alternate build environments:
-
- * Mac OS X 10.6.8 with Xcode 3.2.6
- - need to change ``/System/Library/Frameworks/{Tcl,Tk}.framework/Version/Current`` to ``8.4``
-
-
-
-General Prerequisites
----------------------
-
-* No Fink (in ``/sw``) or MacPorts (in ``/opt/local``) or other local
- libraries or utilities (in ``/usr/local``) as they could
- interfere with the build.
-
-* The documentation for the release is built using Sphinx
- because it is included in the installer. For 2.7.x and 3.x.x up to and
- including 3.4.0, the ``Doc/Makefile`` uses ``svn`` to download repos of
- ``Sphinx`` and its dependencies. Beginning with 3.4.1, the ``Doc/Makefile``
- assumes there is an externally-provided ``sphinx-build`` and requires at
- least Python 2.6 to run. Because of this, it is no longer possible to
- build a 3.4.1 or later installer on OS X 10.5 using the Apple-supplied
- Python 2.5.
-
-* It is safest to start each variant build with an empty source directory
- populated with a fresh copy of the untarred source.
-
-* It is recommended that you remove any existing installed version of the
- Python being built::
-
- sudo rm -rf /Library/Frameworks/Python.framework/Versions/n.n
-
-
-The Recipe
-----------
-
-Here are the steps you need to follow to build a Python installer:
-
-* Run ``build-installer.py``. Optionally you can pass a number of arguments
- to specify locations of various files. Please see the top of
- ``build-installer.py`` for its usage.
-
- Running this script takes some time, it will not only build Python itself
- but also some 3th-party libraries that are needed for extensions.
-
-* When done the script will tell you where the DMG image is (by default
- somewhere in ``/tmp/_py``).
-
-Building other universal installers
-...................................
-
-It is also possible to build a 4-way universal installer that runs on
-OS X 10.5 Leopard or later::
-
- /usr/bin/python /build-installer.py \
- --dep-target=10.5
- --universal-archs=all
- --sdk-path=/Developer/SDKs/MacOSX10.5.sdk
-
-This requires that the deployment target is 10.5, and hence
-also that you are building on at least OS X 10.5. 4-way includes
-``i386``, ``x86_64``, ``ppc``, and ``ppc64`` (G5). ``ppc64`` executable
-variants can only be run on G5 machines running 10.5. Note that,
-while OS X 10.6 is only supported on Intel-based machines, it is possible
-to run ``ppc`` (32-bit) executables unmodified thanks to the Rosetta ppc
-emulation in OS X 10.5 and 10.6. The 4-way installer variant must be
-built with Xcode 3. It is not regularly built or tested.
-
-Other ``--universal-archs`` options are ``64-bit`` (``x86_64``, ``ppc64``),
-and ``3-way`` (``ppc``, ``i386``, ``x86_64``). None of these options
-are regularly exercised; use at your own risk.
-
-
-Testing
--------
-
-Ideally, the resulting binaries should be installed and the test suite run
-on all supported OS X releases and architectures. As a practical matter,
-that is generally not possible. At a minimum, variant 1 should be run on
-a PPC G4 system with OS X 10.5 and at least one Intel system running OS X
-10.9, 10.8, 10.7, 10.6, or 10.5. Variant 2 should be run on 10.9, 10.8,
-10.7, and 10.6 systems in both 32-bit and 64-bit modes.::
-
- /usr/local/bin/pythonn.n -m test -w -u all,-largefile
- /usr/local/bin/pythonn.n-32 -m test -w -u all
-
-Certain tests will be skipped and some cause the interpreter to fail
-which will likely generate ``Python quit unexpectedly`` alert messages
-to be generated at several points during a test run. These are normal
-during testing and can be ignored.
-
-It is also recommend to launch IDLE and verify that it is at least
-functional. Double-click on the IDLE app icon in ``/Applications/Python n.n``.
-It should also be tested from the command line::
-
- /usr/local/bin/idlen.n
-
result.extend([
dict(
- name="OpenSSL 1.1.1c",
- url="https://www.openssl.org/source/openssl-1.1.1c.tar.gz",
- checksum='15e21da6efe8aa0e0768ffd8cd37a5f6',
+ name="OpenSSL 1.1.1d",
+ url="https://www.openssl.org/source/openssl-1.1.1d.tar.gz",
+ checksum='3be209000dbc7e1b95bcdf47980a3baa',
buildrecipe=build_universal_openssl,
configure=None,
install=None,
-{\rtf1\ansi\ansicpg1252\cocoartf1343\cocoasubrtf160
-{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fmodern\fcharset0 CourierNewPS-BoldMT;\f2\fmodern\fcharset0 CourierNewPSMT;
-}
+{\rtf1\ansi\ansicpg1252\cocoartf1671\cocoasubrtf600
+{\fonttbl\f0\fswiss\fcharset0 Helvetica-Bold;\f1\fswiss\fcharset0 Helvetica;\f2\fmodern\fcharset0 CourierNewPS-BoldMT;
+\f3\fmodern\fcharset0 CourierNewPSMT;}
{\colortbl;\red255\green255\blue255;}
+{\*\expandedcolortbl;;}
\margl1440\margr1440\vieww14620\viewh13380\viewkind0
-\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural
+\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
\f0\b\fs36 \cf0 \ul \ulc0 HISTORY AND LICENSE\
\fs24 \
HISTORY OF THE SOFTWARE\
-\b0 \ulnone \
+\f1\b0 \ulnone \
Python was created in the early 1990s by Guido van Rossum at Stichting Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands as a successor of a language called ABC. Guido remains Python's principal author, although it includes many contributions from others.\
\
In 1995, Guido continued his work on Python at the Corporation for National Research Initiatives (CNRI, see http://www.cnri.reston.va.us) in Reston, Virginia where he released several versions of the software.\
All Python releases are Open Source (see http://www.opensource.org for the Open Source Definition). Historically, most, but not all, Python releases have also been GPL-compatible; the table below summarizes the various releases.\
\
-\f1\b Release Derived Year Owner GPL-\
+\f2\b Release Derived Year Owner GPL-\
from compatible?\
-\f2\b0 \
+\f3\b0 \
0.9.0 thru 1.2 n/a 1991-1995 CWI yes\
1.3 thru 1.5.2 1.2 1995-1999 CNRI yes\
1.6 1.5.2 2000 CNRI no\
2.1.3 2.1.2 2002 PSF yes\
2.2 and above 2.1.1 2001-now PSF yes\
-\f0 \
+\f1 \
-\b Note:
-\b0 GPL-compatible doesn't mean that we're distributing Python under the GPL. All Python licenses, unlike the GPL, let you distribute a modified version without making your changes open source. The GPL-compatible licenses make it possible to combine Python with other software that is released under the GPL; the others don't.\
+\f0\b Note:
+\f1\b0 GPL-compatible doesn't mean that we're distributing Python under the GPL. All Python licenses, unlike the GPL, let you distribute a modified version without making your changes open source. The GPL-compatible licenses make it possible to combine Python with other software that is released under the GPL; the others don't.\
\
Thanks to the many outside volunteers who have worked under Guido's direction to make these releases possible.\
\
\
-\b \ul TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON\
+\f0\b \ul TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON\
-\b0 \ulnone \
+\f1\b0 \ulnone \
-\b PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2\
+\f0\b PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2\
-\b0 \
+\f1\b0 \
1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and the Individual or Organization ("Licensee") accessing and otherwise using this software ("Python") in source or binary form and its associated documentation.\
\
-2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Python Software Foundation; All Rights Reserved" are retained in Python alone or in any derivative version prepared by Licensee.\
+2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 Python Software Foundation; All Rights Reserved" are retained in Python alone or in any derivative version prepared by Licensee.\
\
3. In the event Licensee prepares a derivative work that is based on or incorporates Python or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python.\
\
\
\
-\b BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0\
+\f0\b BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0\
-\b0 \
+\f1\b0 \
BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1\
\
1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the Individual or Organization ("Licensee") accessing and otherwise using this software in source or binary form and its associated documentation ("the Software").\
\
\
-\b CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1\
+\f0\b CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1\
-\b0 \
+\f1\b0 \
1. This LICENSE AGREEMENT is between the Corporation for National Research Initiatives, having an office at 1895 Preston White Drive, Reston, VA 20191 ("CNRI"), and the Individual or Organization ("Licensee") accessing and otherwise using Python 1.6.1 software in source or binary form and its associated documentation.\
\
2. Subject to the terms and conditions of this License Agreement, CNRI hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python 1.6.1 alone or in any derivative version, provided, however, that CNRI's License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) 1995-2001 Corporation for National Research Initiatives; All Rights Reserved" are retained in Python 1.6.1 alone or in any derivative version prepared by Licensee. Alternately, in lieu of CNRI's License Agreement, Licensee may substitute the following text (omitting the quotes): "Python 1.6.1 is made available subject to the terms and conditions in CNRI's License Agreement. This Agreement together with Python 1.6.1 may be located on the Internet using the following unique, persistent identifier (known as a handle): 1895.22/1013. This Agreement may also be obtained from a proxy server on the Internet using the following URL: http://hdl.handle.net/1895.22/1013".\
\
\
-\b CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2\
+\f0\b CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2\
-\b0 \
+\f1\b0 \
Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, The Netherlands. All rights reserved.\
\
Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Stichting Mathematisch Centrum or CWI not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission.\
\
\
-\b \ul LICENSES AND ACKNOWLEDGEMENTS FOR INCORPORATED SOFTWARE\
+\f0\b \ul LICENSES AND ACKNOWLEDGEMENTS FOR INCORPORATED SOFTWARE\
-\b0 \ulnone \
+\f1\b0 \ulnone \
This installer incorporates portions of the following third-party software:\
\
-\f2 $THIRD_PARTY_LIBS\
+\f3 $THIRD_PARTY_LIBS\
\
-\f0 For licenses and acknowledgements for these and other third-party software incorporated in this Python distribution, please refer to the on-line documentation {\field{\*\fldinst{HYPERLINK "https://docs.python.org/$VERSION/license.html#licenses-and-acknowledgements-for-incorporated-software"}}{\fldrslt here}}.\
+\f1 For licenses and acknowledgements for these and other third-party software incorporated in this Python distribution, please refer to the on-line documentation {\field{\*\fldinst{HYPERLINK "https://docs.python.org/$VERSION/license.html#licenses-and-acknowledgements-for-incorporated-software"}}{\fldrslt here}}.\
\
\
\
-{\rtf1\ansi\ansicpg1252\cocoartf1671\cocoasubrtf500
+{\rtf1\ansi\ansicpg1252\cocoartf1671\cocoasubrtf600
{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fswiss\fcharset0 Helvetica-Bold;\f2\fswiss\fcharset0 Helvetica-Oblique;
\f3\fmodern\fcharset0 CourierNewPSMT;}
{\colortbl;\red255\green255\blue255;}
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
\f0\fs24 \cf0 This package will install Python $FULL_VERSION for macOS $MACOSX_DEPLOYMENT_TARGET for the following architecture(s): $ARCHITECTURES.\
-\
-\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
-
-\f1\b \cf0 \ul \ulc0 Which installer variant should I use?
-\f0\b0 \ulnone \
-\
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\partightenfactor0
-
-\f1\b \cf0 CHANGED in 3.7.4:
-\f0\b0 The
-\f1\b 10.6+ 64-/32-bit installer variant is being deprecated
-\f0\b0 .
-\f1\b Python 3.8.0
-\f0\b0 will
-\f1\b not
-\f0\b0 include a binary installer for 10.6+ and
-\f1\b future bugfix releases of 3.7.x
-\f0\b0 may not, either. Mac OS X 10.6 Snow Leopard was released in 2009 and has not been supported by Apple for many years including lack of security updates. It is becoming increasingly difficult to ensure new Python features and bug fixes are compatible with such old systems especially with Apple's deprecation and removal of 32-bit support in recent and upcoming macOS releases. We believe that there is now very little usage of this installer variant and so we would like to focus our resources on supporting newer systems. We do not plan to intentionally break Python support on 10.6 and we will consider bug fixes for problems found when building from source on 10.6. \
-\
+\cf0 \
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
-\cf0 For Python.3.7, python.org currently provides two installer variants for download: one that installs a
-\f2\i 64-bit-only
-\f0\i0 Python capable of running on
-\f2\i macOS 10.9 (Mavericks)
-\f0\i0 or later; and one that installs a
-\f2\i 64-bit/32-bit Intel
-\f0\i0 Python capable of running on
-\f2\i macOS 10.6 (Snow Leopard)
-\f0\i0 or later. (This ReadMe was installed with the
-\f2\i $MACOSX_DEPLOYMENT_TARGET
-\f0\i0 variant.) If you are running on macOS 10.9 or later and if you have no need for compatibility with older systems, use the 10.9 variant. Use the 10.6 variant if you are running on macOS 10.6 through 10.8 or if you want to produce standalone applications that can run on systems from 10.6. The Pythons installed by these installers are built with private copies of some third-party libraries not included with or newer than those in macOS itself. The list of these libraries varies by installer variant and is included at the end of the License.rtf file.
-\f1\b \ul \
-\
-Certificate verification and OpenSSL\
+
+\f1\b \cf0 \ul Certificate verification and OpenSSL\
\f0\b0 \ulnone \
-\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\partightenfactor0
-\cf0 This variant of Python 3.7 includes its own private copy of OpenSSL 1.1.1. The deprecated Apple-supplied OpenSSL libraries are no longer used. This means that the trust certificates in system and user keychains managed by the
+This package includes its own private copy of OpenSSL 1.1.1. The trust certificates in system and user keychains managed by the
\f2\i Keychain Access
\f0\i0 application and the
\f2\i security
-\f0\i0 command line utility are no longer used as defaults by the Python
+\f0\i0 command line utility are not used as defaults by the Python
\f3 ssl
\f0 module. A sample command script is included in
\f3 /Applications/Python 3.7
\f0 to install a curated bundle of default root certificates from the third-party
\f3 certifi
-\f0 package ({\field{\*\fldinst{HYPERLINK "https://pypi.org/project/certifi/"}}{\fldrslt https://pypi.org/project/certifi/}}). If you choose to use
-\f3 certifi
-\f0 , you should consider subscribing to the{\field{\*\fldinst{HYPERLINK "https://certifi.io/en/latest/"}}{\fldrslt project's email update service}} to be notified when the certificate bundle is updated.\
-\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
-\cf0 \
+\f0 package ({\field{\*\fldinst{HYPERLINK "https://pypi.org/project/certifi/"}}{\fldrslt https://pypi.org/project/certifi/}}). Double-click on
+\f3 Install Certificates
+\f0 to run it.\
+\
The bundled
\f3 pip
-\f0 included with this installer has its own default certificate store for verifying download connections.\
-\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\partightenfactor0
+\f0 has its own default certificate store for verifying download connections.\
+\
-\f1\b \cf0 \
-CHANGED in 3.7.4:
-\f0\b0 OpenSSL has been updated from 1.1.0 to 1.1.1.\
+\f1\b \ul Which installer variant should I use?
+\f0\b0 \ulnone \
+\
+\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\partightenfactor0
+\cf0 In almost all cases, you should use the
+\f1\b macOS 64-bit installer for OS X 10.9 and later
+\f0\b0 .\
+\
+The legacy
+\f1\b macOS 64-bit/32-bit installer for Mac OS X 10.6 and later
+\f0\b0 variant is now deprecated.
+\f1\b Python 3.8.0
+\f0\b0 will
+\f1\b not
+\f0\b0 include a binary installer for the 10.6+ variant and
+\f1\b future bugfix releases of 3.7.x
+\f0\b0 may not, either. macOS 10.6 Snow Leopard was released in 2009 and has not been supported by Apple for many years including lack of security updates. It is becoming increasingly difficult to ensure new Python features and bug fixes are compatible with such old systems. Note that, due to recent Apple installer packaging changes, the 10.6+ installer pkg we provide can no longer be opened by the Apple system installer application on 10.6; 10.7 and 10.8 are not affected. We believe that there is now very little usage of this installer variant and so we would like to focus our resources on supporting newer systems. We do not plan to intentionally break Python support on 10.6 through 10.8 and we will consider bug fixes for problems found when building from source on those systems.
+\f1\b macOS 10.15 Catalina
+\f0\b0 removes support for running 32-bit architecture programs; we do not recommend trying to use the 10.6+ variant on it and it may not install on 10.15 systems without intervention. \
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
-\cf0 \
-\f1\b \ul Using IDLE or other Tk applications
+\f1\b \cf0 \ul \
+Using IDLE or other Tk applications
\f0\b0 \ulnone \
\
-Both installer variants now come with their own private version of Tcl/Tk 8.6. They no longer use system-supplied or third-party supplied versions of Tcl/Tk as in previous releases.\
+This package includes its own private version of Tcl/Tk 8.6. It does not use any system-supplied or third-party supplied versions of Tcl/Tk.\
+\
+\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
+\cf0 Due to new security checks on macOS 10.15 Catalina, when launching IDLE macOS may open a window with a message
+\f1\b "Python" would like to access files in your Documents folder
+\f0\b0 . This is normal as IDLE uses your
+\f1\b Documents
+\f0\b0 folder as its default when opening and saving files; you can still choose other locations in the
+\f1\b Open
+\f0\b0 and
+\f1\b Save
+\f0\b0 file dialog windows. Click on the
+\f1\b OK
+\f0\b0 button to proceed.\
+\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
-\f1\b \ul \
+\f1\b \cf0 \ul \ulc0 \
Other changes\
\
-\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\partightenfactor0
-\cf0 \ulnone CHANGED in 3.7.4:
-\f0\b0 SQLite has been updated from 3.22.0 to 3.28.0
-\f1\b \ul \ulc0 \
-\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
-\f0\b0 \cf0 \ulnone \
-For other changes in this release, see the
+\f0\b0 \ulnone For other changes in this release, see the
\f2\i What's new
\f0\i0 section in the {\field{\*\fldinst{HYPERLINK "https://www.python.org/doc/"}}{\fldrslt Documentation Set}} for this release and its
\f2\i Release Notes
\f0\i0 link at {\field{\*\fldinst{HYPERLINK "https://www.python.org/downloads/"}}{\fldrslt https://www.python.org/downloads/}}.\
-
-\f1\b \ul \
-Python 3 and Python 2 Co-existence\
-
-\f0\b0 \ulnone \
-Python.org Python $VERSION and 2.7.x versions can both be installed on your system and will not conflict. Command names for Python 3 contain a 3 in them,
-\f3 python3
-\f0 (or
-\f3 python$VERSION
-\f0 ),
-\f3 idle3
-\f0 (or i
-\f3 dle$VERSION
-\f0 ),
-\f3 pip3
-\f0 (or
-\f3 pip$VERSION
-\f0 ), etc. Python 2.7 command names contain a 2 or no digit:
-\f3 python2
-\f0 (or
-\f3 python2.7
-\f0 or
-\f3 python
-\f0 ),
-\f3 idle2
-\f0 (or
-\f3 idle2.7
-\f0 or
-\f3 idle
-\f0 ), etc.\
}
\ No newline at end of file
-{\rtf1\ansi\ansicpg1252\cocoartf1671\cocoasubrtf500
+{\rtf1\ansi\ansicpg1252\cocoartf1671\cocoasubrtf600
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fswiss\fcharset0 Helvetica-Bold;\f2\fmodern\fcharset0 CourierNewPSMT;
}
{\colortbl;\red255\green255\blue255;}
{\*\expandedcolortbl;;}
-\paperw11905\paperh16837\margl1440\margr1440\vieww12200\viewh10880\viewkind0
+\paperw11905\paperh16837\margl1440\margr1440\vieww12380\viewh10900\viewkind0
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\partightenfactor0
\f0\fs24 \cf0 This package will install
\
\f1\b Python for macOS
-\f0\b0 consists of the Python programming language interpreter, plus a set of programs to allow easy access to it for macOS users including an integrated development environment
+\f0\b0 consists of the {\field{\*\fldinst{HYPERLINK "https://www.python.org"}}{\fldrslt Python}} programming language interpreter and its batteries-included standard library to allow easy access to macOS features. It also includes the Python integrated development environment,
\f1\b IDLE
-\f0\b0 .\
+\f0\b0 . You can also use the included
+\f1\b pip
+\f0\b0 to download and install third-party packages from the {\field{\*\fldinst{HYPERLINK "https://pypi.org"}}{\fldrslt Python Package Index}}. \
\
At the end of this install, click on
\f2 Install Certificates
-\f0 for SSL root certificates\
-\
-
-\f1\b NEW in 3.7.0:
-\f0\b0 two installer variants (10.9+ 64-bit-only, 10.6+ 64-/32-bit), built-in Tcl/Tk 8.6 support (no additional third-party downloads!), OpenSSL 1.1, and more!\
-
-\f1\b \
-CHANGED in 3.7.4:
-\f0\b0 OpenSSL 1.1.1, SQLite 3.28.0, 10.6+ 64-/32-bit installer variant deprecated\
+\f0 to install a set of current SSL root certificates.\
}
\ No newline at end of file
+++ /dev/null
-=========================
-Python on Mac OS X README
-=========================
-
-:Authors:
- Jack Jansen (2004-07),
- Ronald Oussoren (2010-04),
- Ned Deily (2012-06)
-
-:Version: 3.4.0
-
-This document provides a quick overview of some Mac OS X specific features in
-the Python distribution.
-
-OS X specific arguments to configure
-====================================
-
-* ``--enable-framework[=DIR]``
-
- If this argument is specified the build will create a Python.framework rather
- than a traditional Unix install. See the section
- _`Building and using a framework-based Python on Mac OS X` for more
- information on frameworks.
-
- If the optional directory argument is specified the framework is installed
- into that directory. This can be used to install a python framework into
- your home directory::
-
- $ ./configure --enable-framework=/Users/ronald/Library/Frameworks
- $ make && make install
-
- This will install the framework itself in ``/Users/ronald/Library/Frameworks``,
- the applications in a subdirectory of ``/Users/ronald/Applications`` and the
- command-line tools in ``/Users/ronald/bin``.
-
-* ``--with-framework-name=NAME``
-
- Specify the name for the python framework, defaults to ``Python``. This option
- is only valid when ``--enable-framework`` is specified.
-
-* ``--enable-universalsdk[=PATH]``
-
- Create a universal binary build of Python. This can be used with both
- regular and framework builds.
-
- The optional argument specifies which OS X SDK should be used to perform the
- build. If xcodebuild is available and configured, this defaults to
- the Xcode default MacOS X SDK, otherwise ``/Developer/SDKs/MacOSX.10.4u.sdk``
- if available or ``/`` if not. When building on OS X 10.5 or later, you can
- specify ``/`` to use the installed system headers rather than an SDK. As of
- OS X 10.9, you should install the optional system headers from the Command
- Line Tools component using ``xcode-select``::
-
- $ sudo xcode-select --install
-
- See the section _`Building and using a universal binary of Python on Mac OS X`
- for more information.
-
-* ``--with-universal-archs=VALUE``
-
- Specify the kind of universal binary that should be created. This option is
- only valid when ``--enable-universalsdk`` is specified. The default is
- ``32-bit`` if a building with a SDK that supports PPC, otherwise defaults
- to ``intel``.
-
-
-Building and using a universal binary of Python on Mac OS X
-===========================================================
-
-1. What is a universal binary
------------------------------
-
-A universal binary build of Python contains object code for more than one
-CPU architecture. A universal OS X executable file or library combines the
-architecture-specific code into one file and can therefore run at native
-speed on all supported architectures. Universal files were introduced in
-OS X 10.4 to add support for Intel-based Macs to the existing PowerPC (PPC)
-machines. In OS X 10.5 support was extended to 64-bit Intel and 64-bit PPC
-architectures. It is possible to build Python with various combinations
-of architectures depending on the build tools and OS X version in use.
-
-2. How do I build a universal binary
-------------------------------------
-
-You can enable universal binaries by specifying the "--enable-universalsdk"
-flag to configure::
-
- $ ./configure --enable-universalsdk
- $ make
- $ make install
-
-This flag can be used with a framework build of python, but also with a classic
-unix build. Universal builds were first supported with OS X 10.4 with Xcode 2.1
-and the 10.4u SDK. Starting with Xcode 3 and OS X 10.5, more configurations are
-available.
-
-In general, universal builds depend on specific features provided by the
-Apple-supplied compilers and other build tools included in Apple's Xcode
-development tools. You should install Xcode and the command line tools
-component appropriate for the OS X release you are running on. See the
-Python Developer's Guide (https://devguide.python.org/setup/)
-for more information.
-
-2.1 Flavors of universal binaries
-.................................
-
-It is possible to build a number of flavors of the universal binary build,
-the default is a 32-bit only binary (i386 and ppc) in build environments that
-support ppc (10.4 with Xcode 2, 10.5 and 10.6 with Xcode 3) or an
-Intel-32/-64-bit binary (i386 and X86_64) in build environments that do not
-support ppc (Xcode 4 on 10.6 and later systems). The flavor can be specified
-using the configure option ``--with-universal-archs=VALUE``. The following
-values are available:
-
- * ``intel``: ``i386``, ``x86_64``
-
- * ``intel-32``: ``i386``
-
- * ``32-bit``: ``ppc``, ``i386``
-
- * ``3-way``: ``i386``, ``x86_64``, ``ppc``
-
- * ``64-bit``: ``ppc64``, ``x86_64``
-
- * ``all``: ``ppc``, ``ppc64``, ``i386``, ``x86_64``
-
-To build a universal binary that includes a 64-bit architecture, you must build
-on a system running OS X 10.5 or later. The ``all`` and ``64-bit`` flavors can
-only be built with a 10.5 SDK because ``ppc64`` support was only included with
-OS X 10.5. Although legacy ``ppc`` support was included with Xcode 3 on OS X
-10.6, it was removed in Xcode 4, versions of which were released on OS X 10.6
-and which is the standard for OS X 10.7. To summarize, the
-following combinations of SDKs and universal-archs flavors are available:
-
- * 10.4u SDK with Xcode 2 supports ``32-bit`` only
-
- * 10.5 SDK with Xcode 3.1.x supports all flavors
-
- * 10.6 SDK with Xcode 3.2.x supports ``intel``, ``3-way``, and ``32-bit``
-
- * 10.6 SDK with Xcode 4 supports ``intel`` only
-
- * 10.7 and 10.8 SDKs with Xcode 4 support ``intel`` only
-
- * 10.8 and 10.9 SDKs with Xcode 5 support ``intel`` only
-
-The makefile for a framework build will also install ``python3.4-32``
-binaries when the universal architecture includes at least one 32-bit
-architecture (that is, for all flavors but ``64-bit``).
-
-Running a specific architecture
-...............................
-
-You can run code using a specific architecture using the ``arch`` command::
-
- $ arch -i386 python
-
-Or to explicitly run in 32-bit mode, regardless of the machine hardware::
-
- $ arch -i386 -ppc python
-
-NOTE: When you're using a framework install of Python this requires at least
-Python 2.7 or 3.2, in earlier versions the python (and pythonw) commands are
-wrapper tools that execute the real interpreter without ensuring that the
-real interpreter runs with the same architecture.
-
-Using ``arch`` is not a perfect solution as the selected architecture will
-not automatically carry through to subprocesses launched by programs and tests
-under that Python. If you want to ensure that Python interpreters launched in
-subprocesses also run in 32-bit-mode if the main interpreter does, use
-a ``python3.4-32`` binary and use the value of ``sys.executable`` as the
-``subprocess`` ``Popen`` executable value.
-
-Building and using a framework-based Python on Mac OS X.
-========================================================
-
-
-1. Why would I want a framework Python instead of a normal static Python?
---------------------------------------------------------------------------
-
-The main reason is because you want to create GUI programs in Python. With the
-exception of X11/XDarwin-based GUI toolkits all GUI programs need to be run
-from a Mac OS X application bundle (".app").
-
-While it is technically possible to create a .app without using frameworks you
-will have to do the work yourself if you really want this.
-
-A second reason for using frameworks is that they put Python-related items in
-only two places: "/Library/Framework/Python.framework" and
-"/Applications/Python <VERSION>" where ``<VERSION>`` can be e.g. "3.4",
-"2.7", etc. This simplifies matters for users installing
-Python from a binary distribution if they want to get rid of it again. Moreover,
-due to the way frameworks work, a user without admin privileges can install a
-binary distribution in his or her home directory without recompilation.
-
-2. How does a framework Python differ from a normal static Python?
-------------------------------------------------------------------
-
-In everyday use there is no difference, except that things are stored in
-a different place. If you look in /Library/Frameworks/Python.framework
-you will see lots of relative symlinks, see the Apple documentation for
-details. If you are used to a normal unix Python file layout go down to
-Versions/Current and you will see the familiar bin and lib directories.
-
-3. Do I need extra packages?
-----------------------------
-
-Yes, probably. If you want Tkinter support you need to get the OS X AquaTk
-distribution, this is installed by default on Mac OS X 10.4 or later. Be
-aware, though, that the Cocoa-based AquaTk's supplied starting with OS X
-10.6 have proven to be unstable. If possible, you should consider
-installing a newer version before building on OS X 10.6 or later, such as
-the ActiveTcl 8.5. See http://www.python.org/download/mac/tcltk/. If you
-are building with an SDK, ensure that the newer Tcl and Tk frameworks are
-seen in the SDK's ``Library/Frameworks`` directory; you may need to
-manually create symlinks to their installed location, ``/Library/Frameworks``.
-If you want wxPython you need to get that.
-If you want Cocoa you need to get PyObjC.
-
-4. How do I build a framework Python?
--------------------------------------
-
-This directory contains a Makefile that will create a couple of python-related
-applications (full-blown OS X .app applications, that is) in
-"/Applications/Python <VERSION>", and a hidden helper application Python.app
-inside the Python.framework, and unix tools including "python" into
-/usr/local/bin. In addition it has a target "installmacsubtree" that installs
-the relevant portions of the Mac subtree into the Python.framework.
-
-It is normally invoked indirectly through the main Makefile, as the last step
-in the sequence
-
- 1. ./configure --enable-framework
-
- 2. make
-
- 3. make install
-
-This sequence will put the framework in ``/Library/Framework/Python.framework``,
-the applications in ``/Applications/Python <VERSION>`` and the unix tools in
-``/usr/local/bin``.
-
-Installing in another place, for instance ``$HOME/Library/Frameworks`` if you
-have no admin privileges on your machine, is possible. This can be accomplished
-by configuring with ``--enable-framework=$HOME/Library/Frameworks``.
-The other two directories will then also be installed in your home directory,
-at ``$HOME/Applications/Python-<VERSION>`` and ``$HOME/bin``.
-
-If you want to install some part, but not all, read the main Makefile. The
-frameworkinstall is composed of a couple of sub-targets that install the
-framework itself, the Mac subtree, the applications and the unix tools.
-
-There is an extra target frameworkinstallextras that is not part of the
-normal frameworkinstall which installs the Tools directory into
-"/Applications/Python <VERSION>", this is useful for binary
-distributions.
-
-What do all these programs do?
-===============================
-
-"IDLE.app" is an integrated development environment for Python: editor,
-debugger, etc.
-
-"Python Launcher.app" is a helper application that will handle things when you
-double-click a .py, .pyc or .pyw file. For the first two it creates a Terminal
-window and runs the scripts with the normal command-line Python. For the
-latter it runs the script in the Python.app interpreter so the script can do
-GUI-things. Keep the ``Option`` key depressed while dragging or double-clicking
-a script to set runtime options. These options can be set persistently
-through Python Launcher's preferences dialog.
-
-The program ``pythonx.x`` runs python scripts from the command line.
-Previously, various compatibility aliases were also installed, including
-``pythonwx.x`` which in early releases of Python on OS X was required to run
-GUI programs. As of 3.4.0, the ``pythonwx.x`` aliases are no longer installed.
-
-How do I create a binary distribution?
-======================================
-
-Download and unpack the source release from http://www.python.org/download/.
-Go to the directory ``Mac/BuildScript``. There you will find a script
-``build-installer.py`` that does all the work. This will download and build
-a number of 3rd-party libaries, configures and builds a framework Python,
-installs it, creates the installer package files and then packs this in a
-DMG image. The script also builds an HTML copy of the current Python
-documentation set for this release for inclusion in the framework. The
-installer package will create links to the documentation for use by IDLE,
-pydoc, shell users, and Finder user.
-
-The script will build a universal binary so you'll therefore have to run this
-script on Mac OS X 10.4 or later and with Xcode 2.1 or later installed.
-However, the Python build process itself has several build dependencies not
-available out of the box with OS X 10.4 so you may have to install
-additional software beyond what is provided with Xcode 2. OS X 10.5
-provides a recent enough system Python (in ``/usr/bin``) to build
-the Python documentation set. It should be possible to use SDKs and/or older
-versions of Xcode to build installers that are compatible with older systems
-on a newer system but this may not be completely foolproof so the resulting
-executables, shared libraries, and ``.so`` bundles should be carefully
-examined and tested on all supported systems for proper dynamic linking
-dependencies. It is safest to build the distribution on a system running the
-minimum OS X version supported.
-
-All of this is normally done completely isolated in /tmp/_py, so it does not
-use your normal build directory nor does it install into /.
-
-Because of the way the script locates the files it needs you have to run it
-from within the BuildScript directory. The script accepts a number of
-command-line arguments, run it with --help for more information.
-
-Configure warnings
-==================
-
-The configure script sometimes emits warnings like the one below::
-
- configure: WARNING: libintl.h: present but cannot be compiled
- configure: WARNING: libintl.h: check for missing prerequisite headers?
- configure: WARNING: libintl.h: see the Autoconf documentation
- configure: WARNING: libintl.h: section "Present But Cannot Be Compiled"
- configure: WARNING: libintl.h: proceeding with the preprocessor's result
- configure: WARNING: libintl.h: in the future, the compiler will take precedence
- configure: WARNING: ## -------------------------------------- ##
- configure: WARNING: ## Report this to http://bugs.python.org/ ##
- configure: WARNING: ## -------------------------------------- ##
-
-This almost always means you are trying to build a universal binary for
-Python and have libraries in ``/usr/local`` that don't contain the required
-architectures. Temporarily move ``/usr/local`` aside to finish the build.
-
-
-Uninstalling a framework install, including the binary installer
-================================================================
-
-Uninstalling a framework can be done by manually removing all bits that got installed.
-That's true for both installations from source and installations using the binary installer.
-OS X does not provide a central uninstaller.
-
-The main bit of a framework install is the framework itself, installed in
-``/Library/Frameworks/Python.framework``. This can contain multiple versions
-of Python, if you want to remove just one version you have to remove the
-version-specific subdirectory: ``/Library/Frameworks/Python.framework/Versions/X.Y``.
-If you do that, ensure that ``/Library/Frameworks/Python.framework/Versions/Current``
-is a symlink that points to an installed version of Python.
-
-A framework install also installs some applications in ``/Applications/Python X.Y``,
-
-And lastly a framework installation installs files in ``/usr/local/bin``, all of
-them symbolic links to files in ``/Library/Frameworks/Python.framework/Versions/X.Y/bin``.
-
-
-Resources
-=========
-
- * http://www.python.org/download/mac/
-
- * http://www.python.org/community/sigs/current/pythonmac-sig/
-
- * https://devguide.python.org/
--- /dev/null
+======================
+Python on macOS README
+======================
+
+:Authors:
+ Jack Jansen (2004-07),
+ Ronald Oussoren (2010-04),
+ Ned Deily (2012-06)
+
+This document provides a quick overview of some macOS specific features in
+the Python distribution.
+
+macOS specific arguments to configure
+=====================================
+
+* ``--enable-framework[=DIR]``
+
+ If this argument is specified the build will create a Python.framework rather
+ than a traditional Unix install. See the section
+ _`Building and using a framework-based Python on macOS` for more
+ information on frameworks.
+
+ If the optional directory argument is specified the framework is installed
+ into that directory. This can be used to install a python framework into
+ your home directory::
+
+ $ ./configure --enable-framework=/Users/ronald/Library/Frameworks
+ $ make && make install
+
+ This will install the framework itself in ``/Users/ronald/Library/Frameworks``,
+ the applications in a subdirectory of ``/Users/ronald/Applications`` and the
+ command-line tools in ``/Users/ronald/bin``.
+
+* ``--with-framework-name=NAME``
+
+ Specify the name for the python framework, defaults to ``Python``. This option
+ is only valid when ``--enable-framework`` is specified.
+
+* ``--enable-universalsdk[=PATH]``
+
+ Create a universal binary build of Python. This can be used with both
+ regular and framework builds.
+
+ The optional argument specifies which macOS SDK should be used to perform the
+ build. In most cases on current systems, you do not need to specify PATH or
+ you can just use ``/``; the default MacOSX SDK for the active Xcode or Command
+ Line Tools developer directory will be used. See the macOS ``xcrun`` man page
+ for more information. Current versions of macOS and Xcode no longer install
+ system header files in their traditional locations, like ``/usr/include`` and
+ ``/System/Library/Frameworks``; instead they are found within a MacOSX SDK.
+ The Apple-supplied build tools handle this transparently and current
+ versiona of Python now handle this as well. So it is no longer necessary,
+ and since macOS 10.14, no longer possible to force the installation of system
+ headers with ``xcode-select``.
+
+* ``--with-universal-archs=VALUE``
+
+ Specify the kind of universal binary that should be created. This option is
+ only valid when ``--enable-universalsdk`` is specified. The default is
+ ``32-bit`` if building with a SDK that supports PPC, otherwise defaults
+ to ``intel``. Note that ``intel`` means a universal build of both 32-bit
+ and 64-bit binaries and that may not be what you want; for example,
+ as of macOS 10.15 Catalina, 32-bit execution is no longer supported by
+ the operating system. Thus it is best to either explicitly specify
+ values for ``--with-universal-archs``:
+
+ ``--enable-universalsdk --with-universal-archs=intel-64``
+
+ or avoid using either.
+
+
+Building and using a universal binary of Python on macOS
+========================================================
+
+1. What is a universal binary
+-----------------------------
+
+A universal binary build of Python contains object code for more than one
+CPU architecture. A universal macOS executable file or library combines the
+architecture-specific code into one file and can therefore run at native
+speed on all supported architectures. Universal files were introduced in
+macOS 10.4 to add support for Intel-based Macs to the existing PowerPC (PPC)
+machines. In macOS 10.5 support was extended to 64-bit Intel and 64-bit PPC
+architectures. It is possible to build Python with various combinations
+of architectures depending on the build tools and macOS version in use.
+Note that PPC support was removed in macOS 10.7 and 32-bit Intel support
+was removed in macOS 10.15. So currently as of macOS 10.15, macOS only
+supports one execution architecture, 64-bit Intel (``x86_64``).
+
+2. How do I build a universal binary
+------------------------------------
+
+You can enable universal binaries by specifying the "--enable-universalsdk"
+flag to configure::
+
+ $ ./configure --enable-universalsdk
+ $ make
+ $ make install
+
+This flag can be used with a framework build of python, but also with a classic
+unix build. Universal builds were first supported with macOS 10.4 with Xcode 2.1
+and the 10.4u SDK. Starting with Xcode 3 and macOS 10.5, more configurations are
+available.
+
+In general, universal builds depend on specific features provided by the
+Apple-supplied compilers and other build tools included in Apple's Xcode
+development tools. You should install Xcode or the command line tools
+component appropriate for the macOS release you are running on. See the
+Python Developer's Guide (https://devguide.python.org/setup/)
+for more information.
+
+2.1 Flavors of universal binaries
+.................................
+
+It is possible to build a number of flavors of the universal binary build,
+the default is a 32-bit only binary (i386 and ppc) in build environments that
+support ppc (10.4 with Xcode 2, 10.5 and 10.6 with Xcode 3) or an
+Intel-32/-64-bit binary (i386 and X86_64) in build environments that do not
+support ppc (Xcode 4 on 10.6 and later systems). The flavor can be specified
+using the configure option ``--with-universal-archs=VALUE``. The following
+values are available:
+
+ * ``intel``: ``i386``, ``x86_64``
+
+ * ``intel-32``: ``i386``
+
+ * ``intel-64``: ``x86_64``
+
+ * ``32-bit``: ``ppc``, ``i386``
+
+ * ``3-way``: ``i386``, ``x86_64``, ``ppc``
+
+ * ``64-bit``: ``ppc64``, ``x86_64``
+
+ * ``all``: ``ppc``, ``ppc64``, ``i386``, ``x86_64``
+
+To build a universal binary that includes a 64-bit architecture, you must build
+on a system running macOS 10.5 or later. The ``all`` and ``64-bit`` flavors can
+only be built with a 10.5 SDK because ``ppc64`` support was only included with
+macOS 10.5. Although legacy ``ppc`` support was included with Xcode 3 on macOS
+10.6, it was removed in Xcode 4, versions of which were released on macOS 10.6
+and which is the standard for macOS 10.7. To summarize, the
+following combinations of SDKs and universal-archs flavors are available:
+
+ * 10.4u SDK with Xcode 2 supports ``32-bit`` only
+
+ * 10.5 SDK with Xcode 3.1.x supports all flavors
+
+ * 10.6 SDK with Xcode 3.2.x supports ``intel``, ``intel-32``,
+ ``intel-64``, ``3-way``, and ``32-bit``
+
+ * 10.6 SDK with Xcode 4 supports ``intel``, ``intel-32``, and ``intel-64``
+
+ * 10.7 through 10.14 SDKs support ``intel``, ``intel-32``, and ``intel-64``
+
+ * 10.15 and later SDKs support ``intel-64`` only
+
+The makefile for a framework build will also install ``python3.x-32``
+binaries when the universal architecture includes at least one 32-bit
+architecture (that is, for all flavors but ``64-bit`` and ``intel-64``).
+
+Running a specific architecture
+...............................
+
+You can run code using a specific architecture using the ``arch`` command::
+
+ $ arch -i386 python
+
+Or to explicitly run in 32-bit mode, regardless of the machine hardware::
+
+ $ arch -i386 -ppc python
+
+Using ``arch`` is not a perfect solution as the selected architecture will
+not automatically carry through to subprocesses launched by programs and tests
+under that Python. If you want to ensure that Python interpreters launched in
+subprocesses also run in 32-bit-mode if the main interpreter does, use
+a ``python3.x-32`` binary and use the value of ``sys.executable`` as the
+``subprocess`` ``Popen`` executable value.
+
+Building and using a framework-based Python on macOS
+====================================================
+
+
+1. Why would I want a framework Python instead of a normal static Python?
+--------------------------------------------------------------------------
+
+The main reason is because you want to create GUI programs in Python. With the
+exception of X11/XDarwin-based GUI toolkits all GUI programs need to be run
+from a macOS application bundle (".app").
+
+While it is technically possible to create a .app without using frameworks you
+will have to do the work yourself if you really want this.
+
+A second reason for using frameworks is that they put Python-related items in
+only two places: "/Library/Framework/Python.framework" and
+"/Applications/Python <VERSION>" where ``<VERSION>`` can be e.g. "3.8",
+"2.7", etc. This simplifies matters for users installing
+Python from a binary distribution if they want to get rid of it again. Moreover,
+due to the way frameworks work, usera without admin privileges can install a
+binary distribution in their home directory without recompilation.
+
+2. How does a framework Python differ from a normal static Python?
+------------------------------------------------------------------
+
+In everyday use there is no difference, except that things are stored in
+a different place. If you look in /Library/Frameworks/Python.framework
+you will see lots of relative symlinks, see the Apple documentation for
+details. If you are used to a normal unix Python file layout go down to
+Versions/Current and you will see the familiar bin and lib directories.
+
+3. Do I need extra packages?
+----------------------------
+
+Yes, probably. If you want Tkinter support you need to get the macOS AquaTk
+distribution, this is installed by default on macOS 10.4 or later. Be
+aware, though, that the Cocoa-based AquaTk's supplied starting with macOS
+10.6 have proven to be unstable. If possible, you should consider
+installing a newer version before building on macOS 10.6 or later, such as
+the ActiveTcl 8.6. See http://www.python.org/download/mac/tcltk/. If you
+are building with an SDK, ensure that the newer Tcl and Tk frameworks are
+seen in the SDK's ``Library/Frameworks`` directory; you may need to
+manually create symlinks to their installed location, ``/Library/Frameworks``.
+If you want wxPython you need to get that.
+If you want Cocoa you need to get PyObjC.
+
+4. How do I build a framework Python?
+-------------------------------------
+
+This directory contains a Makefile that will create a couple of python-related
+applications (full-blown macOS .app applications, that is) in
+"/Applications/Python <VERSION>", and a hidden helper application Python.app
+inside the Python.framework, and unix tools including "python" into
+/usr/local/bin. In addition it has a target "installmacsubtree" that installs
+the relevant portions of the Mac subtree into the Python.framework.
+
+It is normally invoked indirectly through the main Makefile, as the last step
+in the sequence
+
+ 1. ./configure --enable-framework
+
+ 2. make
+
+ 3. make install
+
+This sequence will put the framework in ``/Library/Framework/Python.framework``,
+the applications in ``/Applications/Python <VERSION>`` and the unix tools in
+``/usr/local/bin``.
+
+Installing in another place, for instance ``$HOME/Library/Frameworks`` if you
+have no admin privileges on your machine, is possible. This can be accomplished
+by configuring with ``--enable-framework=$HOME/Library/Frameworks``.
+The other two directories will then also be installed in your home directory,
+at ``$HOME/Applications/Python-<VERSION>`` and ``$HOME/bin``.
+
+If you want to install some part, but not all, read the main Makefile. The
+frameworkinstall is composed of a couple of sub-targets that install the
+framework itself, the Mac subtree, the applications and the unix tools.
+
+There is an extra target frameworkinstallextras that is not part of the
+normal frameworkinstall which installs the Tools directory into
+"/Applications/Python <VERSION>", this is useful for binary
+distributions.
+
+What do all these programs do?
+===============================
+
+"IDLE.app" is an integrated development environment for Python: editor,
+debugger, etc.
+
+"Python Launcher.app" is a helper application that will handle things when you
+double-click a .py, .pyc or .pyw file. For the first two it creates a Terminal
+window and runs the scripts with the normal command-line Python. For the
+latter it runs the script in the Python.app interpreter so the script can do
+GUI-things. Keep the ``Option`` key depressed while dragging or double-clicking
+a script to set runtime options. These options can be set persistently
+through Python Launcher's preferences dialog.
+
+The program ``pythonx.x`` runs python scripts from the command line.
+Previously, various compatibility aliases were also installed, including
+``pythonwx.x`` which in early releases of Python on macOS was required to run
+GUI programs. As of 3.4.0, the ``pythonwx.x`` aliases are no longer installed.
+
+How do I create a binary distribution?
+======================================
+
+Download and unpack the source release from http://www.python.org/download/.
+Go to the directory ``Mac/BuildScript``. There you will find a script
+``build-installer.py`` that does all the work. This will download and build
+a number of 3rd-party libaries, configures and builds a framework Python,
+installs it, creates the installer package files and then packs this in a
+DMG image. The script also builds an HTML copy of the current Python
+documentation set for this release for inclusion in the framework. The
+installer package will create links to the documentation for use by IDLE,
+pydoc, shell users, and Finder user.
+
+The script will build a universal binary so you'll therefore have to run this
+script on macOS 10.4 or later and with Xcode 2.1 or later installed.
+However, the Python build process itself has several build dependencies not
+available out of the box with macOS 10.4 so you may have to install
+additional software beyond what is provided with Xcode 2.
+It should be possible to use SDKs and/or older
+versions of Xcode to build installers that are compatible with older systems
+on a newer system but this may not be completely foolproof so the resulting
+executables, shared libraries, and ``.so`` bundles should be carefully
+examined and tested on all supported systems for proper dynamic linking
+dependencies. It is safest to build the distribution on a system running the
+minimum macOS version supported.
+
+All of this is normally done completely isolated in /tmp/_py, so it does not
+use your normal build directory nor does it install into /.
+
+Because of the way the script locates the files it needs you have to run it
+from within the BuildScript directory. The script accepts a number of
+command-line arguments, run it with --help for more information.
+
+Configure warnings
+==================
+
+The configure script sometimes emits warnings like the one below::
+
+ configure: WARNING: libintl.h: present but cannot be compiled
+ configure: WARNING: libintl.h: check for missing prerequisite headers?
+ configure: WARNING: libintl.h: see the Autoconf documentation
+ configure: WARNING: libintl.h: section "Present But Cannot Be Compiled"
+ configure: WARNING: libintl.h: proceeding with the preprocessor's result
+ configure: WARNING: libintl.h: in the future, the compiler will take precedence
+ configure: WARNING: ## -------------------------------------- ##
+ configure: WARNING: ## Report this to http://bugs.python.org/ ##
+ configure: WARNING: ## -------------------------------------- ##
+
+This almost always means you are trying to build a universal binary for
+Python and have libraries in ``/usr/local`` that don't contain the required
+architectures. Temporarily move ``/usr/local`` aside to finish the build.
+
+
+Uninstalling a framework install, including the binary installer
+================================================================
+
+Uninstalling a framework can be done by manually removing all bits that got installed.
+That's true for both installations from source and installations using the binary installer.
+macOS does not provide a central uninstaller.
+
+The main bit of a framework install is the framework itself, installed in
+``/Library/Frameworks/Python.framework``. This can contain multiple versions
+of Python, if you want to remove just one version you have to remove the
+version-specific subdirectory: ``/Library/Frameworks/Python.framework/Versions/X.Y``.
+If you do that, ensure that ``/Library/Frameworks/Python.framework/Versions/Current``
+is a symlink that points to an installed version of Python.
+
+A framework install also installs some applications in ``/Applications/Python X.Y``,
+
+And lastly a framework installation installs files in ``/usr/local/bin``, all of
+them symbolic links to files in ``/Library/Frameworks/Python.framework/Versions/X.Y/bin``.
+
+
+Resources
+=========
+
+ * http://www.python.org/download/mac/
+
+ * http://www.python.org/community/sigs/current/pythonmac-sig/
+
+ * https://devguide.python.org/
Parser/pgenmain.o
PARSER_HEADERS= \
- $(srcdir)/Parser/parser.h \
+ $(srcdir)/Include/grammar.h \
$(srcdir)/Include/parsetok.h \
+ $(srcdir)/Parser/parser.h \
$(srcdir)/Parser/tokenizer.h
PGENOBJS= $(POBJS) $(PGOBJS)
$(srcdir)/Include/opcode.h.new
$(UPDATE_FILE) $(srcdir)/Include/opcode.h $(srcdir)/Include/opcode.h.new
-Python/compile.o Python/symtable.o Python/ast_unparse.o Python/ast.o: $(srcdir)/Include/graminit.h $(srcdir)/Include/Python-ast.h
+Python/compile.o Python/symtable.o Python/ast_unparse.o Python/ast.o Python/future.o Parser/parsetok.o: $(srcdir)/Include/graminit.h $(srcdir)/Include/Python-ast.h
Python/getplatform.o: $(srcdir)/Python/getplatform.c
$(CC) -c $(PY_CORE_CFLAGS) -DPLATFORM='"$(MACHDEP)"' -o $@ $(srcdir)/Python/getplatform.c
$(srcdir)/Include/accu.h \
$(srcdir)/Include/asdl.h \
$(srcdir)/Include/ast.h \
- $(srcdir)/Include/bltinmodule.h \
$(srcdir)/Include/bitset.h \
+ $(srcdir)/Include/bltinmodule.h \
$(srcdir)/Include/boolobject.h \
- $(srcdir)/Include/bytes_methods.h \
$(srcdir)/Include/bytearrayobject.h \
+ $(srcdir)/Include/bytes_methods.h \
$(srcdir)/Include/bytesobject.h \
$(srcdir)/Include/cellobject.h \
$(srcdir)/Include/ceval.h \
$(srcdir)/Include/codecs.h \
$(srcdir)/Include/compile.h \
$(srcdir)/Include/complexobject.h \
+ $(srcdir)/Include/context.h \
$(srcdir)/Include/descrobject.h \
$(srcdir)/Include/dictobject.h \
$(srcdir)/Include/dtoa.h \
$(srcdir)/Include/node.h \
$(srcdir)/Include/object.h \
$(srcdir)/Include/objimpl.h \
+ $(srcdir)/Include/odictobject.h \
$(srcdir)/Include/opcode.h \
$(srcdir)/Include/osdefs.h \
$(srcdir)/Include/osmodule.h \
$(srcdir)/Include/pyfpe.h \
$(srcdir)/Include/pyhash.h \
$(srcdir)/Include/pylifecycle.h \
- $(srcdir)/Include/pymath.h \
+ $(srcdir)/Include/pymacconfig.h \
$(srcdir)/Include/pymacro.h \
+ $(srcdir)/Include/pymath.h \
$(srcdir)/Include/pymem.h \
$(srcdir)/Include/pyport.h \
$(srcdir)/Include/pystate.h \
- $(srcdir)/Include/context.h \
$(srcdir)/Include/pystrcmp.h \
- $(srcdir)/Include/pystrtod.h \
$(srcdir)/Include/pystrhex.h \
+ $(srcdir)/Include/pystrtod.h \
$(srcdir)/Include/pythonrun.h \
$(srcdir)/Include/pythread.h \
$(srcdir)/Include/pytime.h \
$(srcdir)/Include/structseq.h \
$(srcdir)/Include/symtable.h \
$(srcdir)/Include/sysmodule.h \
+ $(srcdir)/Include/token.h \
$(srcdir)/Include/traceback.h \
$(srcdir)/Include/tupleobject.h \
$(srcdir)/Include/ucnhash.h \
.PHONY: test testall testuniversal buildbottest pythoninfo
+# Remove "test_python_*" directories of previous failed test jobs.
+# Pass TESTOPTS options because it can contain --tempdir option.
+cleantest: build_all
+ $(TESTRUNNER) $(TESTOPTS) --cleanup
+
# Run a basic set of regression tests.
# This excludes some tests that are particularly resource-intensive.
test: @DEF_MAKE_RULE@ platform
Michele Angrisano
Ankur Ankan
Heidi Annexstad
+David Antonini
Ramchandra Apte
Éric Araujo
Alexandru Ardelean
Daniel Black
Jonathan Black
Renaud Blanch
+Justin Blanchard
Mike Bland
Martin Bless
Pablo Bleyer
Garvit Khatri
Vivek Khera
Dhiru Kholia
+Artem Khramov
Akshit Khurana
Sanyam Khurana
Mads Kiilerich
Mark Levinson
Mark Levitt
Ivan Levkivskyi
+Ben Lewis
William Lewis
Akira Li
Robert Li
Abhilash Raj
Shorya Raj
Dhushyanth Ramasamy
+Ashwin Ramaswami
Jeff Ramnani
Bayard Randel
Varpu Rantala
Yann Sionneau
George Sipe
J. Sipprell
+Ngalim Siregar
Kragen Sitaker
Kaartic Sivaraam
Ville Skyttä
Andrew Svetlov
Paul Swartz
Al Sweigart
+Sviatoslav Sydorenko
Thenault Sylvain
Péter Szabó
John Szakmeister
Hector Urtubia
Lukas Vacek
Ville Vainio
+Yann Vaginay
Andi Vajda
Case Van Horsen
John Mark Vandenberg
Yuxiao Zeng
Uwe Zessin
Cheng Zhang
+George Zhang
Kai Zhu
Tarek Ziadé
Jelle Zijlstra
Peter Åstrand
Zheao Li
Geoff Shannon
+Ngalim Siregar
Python News
+++++++++++
+What's New in Python 3.7.5 final?
+=================================
+
+*Release date: 2019-10-14*
+
+Library
+-------
+
+- bpo-38368: Prevent ctypes crash when handling arrays in structs/unions.
+
+- bpo-38449: Revert GH-15522, which introduces a regression in
+ :meth:`mimetypes.guess_type` due to improper handling of filenames as
+ urls.
+
+Windows
+-------
+
+- bpo-38344: Fix syntax in activate.bat.
+
+
+What's New in Python 3.7.5 release candidate 1?
+===============================================
+
+*Release date: 2019-10-01*
+
+Security
+--------
+
+- bpo-38243: Escape the server title of
+ :class:`xmlrpc.server.DocXMLRPCServer` when rendering the document page as
+ HTML. (Contributed by Dong-hee Na in :issue:`38243`.)
+
+- bpo-38174: Update vendorized expat library version to 2.2.8, which
+ resolves CVE-2019-15903.
+
+- bpo-37764: Fixes email._header_value_parser.get_unstructured going into an
+ infinite loop for a specific case in which the email header does not have
+ trailing whitespace, and the case in which it contains an invalid encoded
+ word. Patch by Ashwin Ramaswami.
+
+- bpo-37461: Fix an infinite loop when parsing specially crafted email
+ headers. Patch by Abhilash Raj.
+
+- bpo-34155: Fix parsing of invalid email addresses with more than one ``@``
+ (e.g. a@b@c.com.) to not return the part before 2nd ``@`` as valid email
+ address. Patch by maxking & jpic.
+
+Core and Builtins
+-----------------
+
+- bpo-36871: Improve error handling for the assert_has_calls method of
+ mocks. Fixed a bug where any errors encountered while binding the expected
+ calls to the mock's spec were silently swallowed, leading to misleading
+ error output.
+
+- bpo-38013: Allow to call ``async_generator_athrow().throw(...)`` even for
+ non-started async generator helper. It fixes annoying warning at the end
+ of :func:`asyncio.run` call.
+
+- bpo-38124: Fix an off-by-one error in PyState_AddModule that could cause
+ out-of-bounds memory access.
+
+- bpo-36946: Fix possible signed integer overflow when handling slices.
+ Patch by hongweipeng.
+
+- bpo-37409: Ensure explicit relative imports from interactive sessions and
+ scripts (having no parent package) always raise ImportError, rather than
+ treating the current module as the package. Patch by Ben Lewis.
+
+- bpo-36311: Decoding bytes objects larger than 2GiB is faster and no longer
+ fails when a multibyte characters spans a chunk boundary.
+
+- bpo-37467: Fix :func:`sys.excepthook` and :c:func:`PyErr_Display` if a
+ filename is a bytes string. For example, for a SyntaxError exception where
+ the filename attribute is a bytes string.
+
+- bpo-37417: :meth:`bytearray.extend` now correctly handles errors that
+ arise during iteration. Patch by Brandt Bucher.
+
+- bpo-20523: ``pdb.Pdb`` supports ~/.pdbrc in Windows 7. Patch by Tim Hopper
+ and Dan Lidral-Porter.
+
+Library
+-------
+
+- bpo-38019: Correctly handle pause/resume reading of closed asyncio unix
+ pipe.
+
+- bpo-38216: Allow the rare code that wants to send invalid http requests
+ from the `http.client` library a way to do so. The fixes for bpo-30458
+ led to breakage for some projects that were relying on this ability to
+ test their own behavior in the face of bad requests.
+
+- bpo-38191: Constructor of :class:`~typing.NamedTuple` type now accepts
+ arbitrary keyword argument names, including "cls", "self", "typename" and
+ "fields".
+
+- bpo-38185: Fixed case-insensitive string comparison in
+ :class:`sqlite3.Row` indexing.
+
+- bpo-38175: Fix a memory leak in comparison of :class:`sqlite3.Row`
+ objects.
+
+- bpo-33936: _hashlib no longer calls obsolete OpenSSL initialization
+ function with OpenSSL 1.1.0+.
+
+- bpo-34706: Preserve subclassing in inspect.Signature.from_callable.
+
+- bpo-38059: inspect.py now uses sys.exit() instead of exit()
+
+- bpo-38006: weakref.WeakValueDictionary defines a local remove() function
+ used as callback for weak references. This function was created with a
+ closure. Modify the implementation to avoid the closure.
+
+- bpo-34410: Fixed a crash in the :func:`tee` iterator when re-enter it.
+ RuntimeError is now raised in this case.
+
+- bpo-37965: Fix C compiler warning caused by
+ distutils.ccompiler.CCompiler.has_function.
+
+- bpo-36205: Fix the rusage implementation of time.process_time() to
+ correctly report the sum of the system and user CPU time.
+
+- bpo-22347: Update mimetypes.guess_type to allow proper parsing of URLs
+ with only a host name. Patch by Dong-hee Na.
+
+- bpo-37950: Fix :func:`ast.dump` when call with incompletely initialized
+ node.
+
+- bpo-37915: Fix a segmentation fault that appeared when comparing instances
+ of ``datetime.timezone`` and ``datetime.tzinfo`` objects. Patch by Pablo
+ Galindo.
+
+- bpo-37885: venv: Don't generate unset variable warning on deactivate.
+
+- bpo-37868: Fix dataclasses.is_dataclass when given an instance that never
+ raises AttributeError in __getattr__. That is, an object that returns
+ something for __dataclass_fields__ even if it's not a dataclass.
+
+- bpo-37811: Fix ``socket`` module's ``socket.connect(address)`` function
+ being unable to establish connection in case of interrupted system call.
+ The problem was observed on all OSes which ``poll(2)`` system call can
+ take only non-negative integers and -1 as a timeout value.
+
+- bpo-21131: Fix ``faulthandler.register(chain=True)`` stack. faulthandler
+ now allocates a dedicated stack of ``SIGSTKSZ*2`` bytes, instead of just
+ ``SIGSTKSZ`` bytes. Calling the previous signal handler in faulthandler
+ signal handler uses more than ``SIGSTKSZ`` bytes of stack memory on some
+ platforms.
+
+- bpo-34621: Fixed unpickle-ability in older Python versions (<3.7) of UUID
+ objects with ``is_safe`` set to ``SafeUUID.unknown``.
+
+- bpo-37738: Fix the implementation of curses ``addch(str, color_pair)``:
+ pass the color pair to ``setcchar()``, instead of always passing 0 as the
+ color pair.
+
+- bpo-37723: Fix performance regression on regular expression parsing with
+ huge character sets. Patch by Yann Vaginay.
+
+- bpo-32178: Fix IndexError in :mod:`email` package when trying to parse
+ invalid address fields starting with ``:``.
+
+- bpo-37685: Fixed comparisons of :class:`datetime.timedelta` and
+ :class:`datetime.timezone`.
+
+- bpo-37695: Correct :func:`curses.unget_wch` error message. Patch by
+ Anthony Sottile.
+
+- bpo-29553: Fixed :meth:`argparse.ArgumentParser.format_usage` for mutually
+ exclusive groups. Patch by Andrew Nester.
+
+- bpo-37664: Update wheels bundled with ensurepip (pip 19.2.3 and setuptools
+ 41.2.0)
+
+- bpo-37642: Allowed the pure Python implementation of
+ :class:`datetime.timezone` to represent sub-minute offsets close to
+ minimum and maximum boundaries, specifically in the ranges (23:59, 24:00)
+ and (-23:59, 24:00). Patch by Ngalim Siregar
+
+- bpo-37491: Fix ``IndexError`` when parsing email headers with unexpectedly
+ ending bare-quoted string value. Patch by Abhilash Raj.
+
+- bpo-18378: Recognize "UTF-8" as a valid value for LC_CTYPE in
+ locale._parse_localename.
+
+- bpo-37579: Return :exc:`NotImplemented` in Python implementation of
+ ``__eq__`` for :class:`~datetime.timedelta` and :class:`~datetime.time`
+ when the other object being compared is not of the same type to match C
+ implementation. Patch by Karthikeyan Singaravelan.
+
+- bpo-21478: Record calls to parent when autospecced object is attached to a
+ mock using :func:`unittest.mock.attach_mock`. Patch by Karthikeyan
+ Singaravelan.
+
+- bpo-37531: "python3 -m test -jN --timeout=TIMEOUT" now kills a worker
+ process if it runs longer than *TIMEOUT* seconds.
+
+- bpo-37482: Fix serialization of display name in originator or destination
+ address fields with both encoded words and special chars.
+
+- bpo-37424: Fixes a possible hang when using a timeout on
+ `subprocess.run()` while capturing output. If the child process spawned
+ its own children or otherwise connected its stdout or stderr handles with
+ another process, we could hang after the timeout was reached and our child
+ was killed when attempting to read final output from the pipes.
+
+- bpo-37421: Fix :func:`multiprocessing.util.get_temp_dir` finalizer: clear
+ also the 'tempdir' configuration of the current process, so next call to
+ ``get_temp_dir()`` will create a new temporary directory, rather than
+ reusing the removed temporary directory.
+
+- bpo-37420: :func:`os.sched_setaffinity` now correctly handles errors that
+ arise during iteration over its ``mask`` argument. Patch by Brandt Bucher.
+
+- bpo-29412: Fix IndexError in parsing a header value ending unexpectedly.
+ Patch by Abhilash Raj.
+
+- bpo-37372: Fix error unpickling datetime.time objects from Python 2 with
+ seconds>=24. Patch by Justin Blanchard.
+
+- bpo-27860: Fix ``IPv4Interface`` and ``IPv6Interface`` didn't accept
+ string mask when the argument is tuple.
+
+- bpo-33972: Email with single part but content-type set to ``multipart/*``
+ doesn't raise AttributeError anymore.
+
+- bpo-21872: Fix :mod:`lzma`: module decompresses data incompletely. When
+ decompressing a FORMAT_ALONE format file, and it doesn't have the end
+ marker, sometimes the last one to dozens bytes can't be output. Patch by
+ Ma Lin.
+
+- bpo-12144: Ensure cookies with ``expires`` attribute are handled in
+ :meth:`CookieJar.make_cookies`.
+
+- bpo-37163: :func:`dataclasses.replace` now supports the field named "obj".
+
+- bpo-36871: Ensure method signature is used instead of constructor
+ signature of a class while asserting mock object against method calls.
+ Patch by Karthikeyan Singaravelan.
+
+- bpo-36564: Fix infinite loop in email header folding logic that would be
+ triggered when an email policy's max_line_length is not long enough to
+ include the required markup and any values in the message. Patch by Paul
+ Ganssle
+
+- bpo-35168: :attr:`shlex.shlex.punctuation_chars` is now a read-only
+ property.
+
+- bpo-20504: Fixes a bug in :mod:`cgi` module when a multipart/form-data
+ request has no `Content-Length` header.
+
+- bpo-4963: Fixed non-deterministic behavior related to mimetypes extension
+ mapping and module reinitialization.
+
+Documentation
+-------------
+
+- bpo-26868: Fix example usage of :c:func:`PyModule_AddObject` to properly
+ handle errors.
+
+- bpo-37979: Added a link to dateutil.parser.isoparse in the
+ datetime.fromisoformat documentation. Patch by Paul Ganssle
+
+- bpo-37937: Mention ``frame.f_trace`` in :func:`sys.settrace` docs.
+
+- bpo-37726: Stop recommending getopt in the tutorial for command line
+ argument parsing and promote argparse.
+
+- bpo-32910: Remove implementation-specific behaviour of how venv's
+ Deactivate works.
+
+- bpo-37256: Fix wording of arguments for :class:`Request` in
+ :mod:`urllib.request`
+
+- bpo-37284: Add a brief note to indicate that any new
+ ``sys.implementation`` required attributes must go through the PEP
+ process.
+
+- bpo-30088: Documented that :class:`mailbox.Maildir` constructor doesn't
+ attempt to verify the maildir folder layout correctness. Patch by
+ Sviatoslav Sydorenko.
+
+- bpo-37487: Fix PyList_GetItem index description to include 0.
+
+- bpo-37478: Added possible exceptions to the description of os.chdir().
+
+- bpo-37004: In the documentation for difflib, a note was added explicitly
+ warning that the results of SequenceMatcher's ratio method may depend on
+ the order of the input strings.
+
+- bpo-35803: Document and test that ``tempfile`` functions may accept a
+ :term:`path-like object` for the ``dir`` argument. Patch by Anthony
+ Sottile.
+
+- bpo-34293: Fix the Doc/Makefile regarding PAPER environment variable and
+ PDF builds
+
+Tests
+-----
+
+- bpo-38239: Fix test_gdb for Link Time Optimization (LTO) builds.
+
+- bpo-38275: test_ssl now handles disabled TLS/SSL versions better.
+ OpenSSL's crypto policy and run-time settings are recognized and tests for
+ disabled versions are skipped. Tests also accept more TLS minimum_versions
+ for platforms that override OpenSSL's default with strict settings.
+
+- bpo-38271: The private keys for test_ssl were encrypted with 3DES in
+ traditional PKCS#5 format. 3DES and the digest algorithm of PKCS#5 are
+ blocked by some strict crypto policies. Use PKCS#8 format with AES256
+ encryption instead.
+
+- bpo-37123: Multiprocessing test test_mymanager() now also expects
+ -SIGTERM, not only exitcode 0. BaseManager._finalize_manager() sends
+ SIGTERM to the manager process if it takes longer than 1 second to stop,
+ which happens on slow buildbots.
+
+- bpo-38212: Multiprocessing tests: increase
+ test_queue_feeder_donot_stop_onexc() timeout from 1 to 60 seconds.
+
+- bpo-38117: Test with OpenSSL 1.1.1d
+
+- bpo-37805: Add tests for json.dump(..., skipkeys=True). Patch by Dong-hee
+ Na.
+
+- bpo-37531: Enhance regrtest multiprocess timeout: write a message when
+ killing a worker process, catch popen.kill() and popen.wait() exceptions,
+ put a timeout on the second call to popen.communicate().
+
+- bpo-37335: Improve locale coercion tests by using codec lookup instead of
+ more fragile replace().
+
+- bpo-37411: Fix test_wsgiref.testEnviron() to no longer depend on the
+ environment variables (don't fail if "X" variable is set).
+
+- bpo-37400: Fix test_os.test_chown(): use os.getgroups() rather than
+ grp.getgrall() to get groups. Rename also the test to test_chown_gid().
+
+- bpo-37359: Add --cleanup option to python3 -m test to remove
+ ``test_python_*`` directories of previous failed jobs. Add "make
+ cleantest" to run ``python3 -m test --cleanup``.
+
+- bpo-37362: test_gdb no longer fails if it gets an "unexpected" message on
+ stderr: it now ignores stderr. The purpose of test_gdb is to test that
+ python-gdb.py commands work as expected, not to test gdb.
+
+- bpo-36919: Make ``test_source_encoding.test_issue2301`` implementation
+ independent. The test will work now for both CPython and IronPython.
+
+- bpo-34720: Assert m_state != NULL to mimic GC traversal functions that do
+ not correctly handle module creation when the module state has not been
+ created.
+
+- bpo-34347: Fix ``test_utf8_mode.test_cmd_line`` for AIX. Patch by M. Felt
+
+Build
+-----
+
+- bpo-38301: In Solaris family, we must be sure to use ``-D_REENTRANT``.
+ Patch by Jesús Cea Avión.
+
+- bpo-36002: Locate ``llvm-profdata`` and ``llvm-ar`` binaries using
+ ``AC_PATH_TOOL`` rather than ``AC_PATH_TARGET_TOOL``.
+
+- bpo-37936: The :file:`.gitignore` file no longer applies to any files that
+ are in fact tracked in the Git repository. Patch by Greg Price.
+
+Windows
+-------
+
+- bpo-38117: Update bundled OpenSSL to 1.1.1d
+
+- bpo-36634: venv activate.bat now works when the existing variables contain
+ double quote characters.
+
+- bpo-38087: Fix case sensitivity in test_pathlib and test_ntpath.
+
+- bpo-38088: Fixes distutils not finding vcruntime140.dll with only the v142
+ toolset installed.
+
+- bpo-37283: Ensure command-line and unattend.xml setting override
+ previously detected states in Windows installer.
+
+- bpo-37705: Improve the implementation of ``winerror_to_errno()``.
+
+- bpo-37549: :func:`os.dup` no longer fails for standard streams on Windows
+ 7.
+
+- bpo-37702: Fix memory leak on Windows in creating an SSLContext object or
+ running urllib.request.urlopen('https://...').
+
+- bpo-10945: Officially drop support for creating bdist_wininst installers
+ on non-Windows systems.
+
+- bpo-37445: Include the ``FORMAT_MESSAGE_IGNORE_INSERTS`` flag in
+ ``FormatMessageW()`` calls.
+
+- bpo-37380: Don't collect unfinished processes with ``subprocess._active``
+ on Windows to cleanup later. Patch by Ruslan Kuprieiev.
+
+- bpo-32587: Make :data:`winreg.REG_MULTI_SZ` support zero-length strings.
+
+macOS
+-----
+
+- bpo-38117: Updated OpenSSL to 1.1.1d in macOS installer.
+
+- bpo-38089: Move Azure Pipelines to latest VM versions and make macOS tests
+ optional
+
+IDLE
+----
+
+- bpo-35379: When exiting IDLE, catch any AttributeError. One happens when
+ EditorWindow.close is called twice. Printing a traceback, when IDLE is
+ run from a terminal, is useless and annoying.
+
+- bpo-38183: To avoid problems, test_idle ignores the user config directory.
+ It no longer tries to create or access .idlerc or any files within. Users
+ must run IDLE to discover problems with saving settings.
+
+- bpo-38077: IDLE no longer adds 'argv' to the user namespace when
+ initializing it. This bug only affected 3.7.4 and 3.8.0b2 to 3.8.0b4.
+
+- bpo-38041: Shell restart lines now fill the window width, always start
+ with '=', and avoid wrapping unnecessarily. The line will still wrap if
+ the included file name is long relative to the width.
+
+- bpo-35771: To avoid occasional spurious test_idle failures on slower
+ machines, increase the ``hover_delay`` in test_tooltip.
+
+- bpo-37824: Properly handle user input warnings in IDLE shell. Cease
+ turning SyntaxWarnings into SyntaxErrors.
+
+- bpo-37929: IDLE Settings dialog now closes properly when there is no shell
+ window.
+
+- bpo-37902: Add mousewheel scrolling for IDLE module, path, and stack
+ browsers. Patch by George Zhang.
+
+- bpo-37849: Fixed completions list appearing too high or low when shown
+ above the current line.
+
+- bpo-36419: Refactor IDLE autocomplete and improve testing.
+
+- bpo-37748: Reorder the Run menu. Put the most common choice, Run Module,
+ at the top.
+
+- bpo-37692: Improve highlight config sample with example shell interaction
+ and better labels for shell elements.
+
+- bpo-37628: Settings dialog no longer expands with font size.
+
+- bpo-37627: Initialize the Customize Run dialog with the command line
+ arguments most recently entered before. The user can optionally edit
+ before submitting them.
+
+- bpo-33610: Fix code context not showing the correct context when first
+ toggled on.
+
+- bpo-37530: Optimize code context to reduce unneeded background activity.
+ Font and highlight changes now occur along with text changes instead of
+ after a random delay.
+
+- bpo-27452: Cleanup ``config.py`` by inlining ``RemoveFile`` and
+ simplifying the handling of ``file`` in ``CreateConfigHandlers``.
+
+- bpo-37325: Fix tab focus traversal order for help source and custom run
+ dialogs.
+
+- bpo-17535: Add optional line numbers for IDLE editor windows. Windows
+ open without line numbers unless set otherwise in the General tab of the
+ configuration dialog.
+
+- bpo-26806: To compensate for stack frames added by IDLE and avoid possible
+ problems with low recursion limits, add 30 to limits in the user code
+ execution process. Subtract 30 when reporting recursion limits to make
+ this addition mostly transparent.
+
+- bpo-36390: Gather Format menu functions into format.py. Combine
+ paragraph.py, rstrip.py, and format methods from editor.py.
+
+Tools/Demos
+-----------
+
+- bpo-37803: pdb's ``--help`` and ``--version`` long options now work.
+
+- bpo-37675: 2to3 now works when run from a zipped standard library.
+
+
What's New in Python 3.7.4 final?
=================================
'<<force-open-calltip>>', '<<flash-paren>>', '<<format-paragraph>>',
'<<run-module>>', '<<check-module>>', and '<<zoom-height>>'. Any (global)
customizations made before 3.6.3 will not affect their keyset-specific
- customization after 3.6.3. and vice versa.
-
- Inital patch by Charles Wohlganger.
+ customization after 3.6.3. and vice versa. Initial patch by Charles
+ Wohlganger.
- bpo-31206: IDLE: Factor HighPage(Frame) class from ConfigDialog. Patch by
Cheryl Sabella.
- bpo-26624: Adds validation of ucrtbase[d].dll version with warning for old
versions.
-- bpo-17603: Avoid error about nonexistant fileblocks.o file by using a
+- bpo-17603: Avoid error about nonexistent fileblocks.o file by using a
lower-level check for st_blocks in struct stat.
- bpo-26079: Fixing the build output folder for tix-8.4.3.6. Patch by Bjoern
- bpo-26624: Adds validation of ucrtbase[d].dll version with warning for old
versions.
-- bpo-17603: Avoid error about nonexistant fileblocks.o file by using a
+- bpo-17603: Avoid error about nonexistent fileblocks.o file by using a
lower-level check for st_blocks in struct stat.
- bpo-26079: Fixing the build output folder for tix-8.4.3.6. Patch by Bjoern
if (c == '\0') {
Py_DECREF(lineobj);
PyErr_Format(_csvstate_global->error_obj,
- "line contains NULL byte");
+ "line contains NUL");
goto err;
}
if (parse_process_char(self, c) < 0) {
*/
StgDictObject *v = PyObject_stgdict(value);
assert(v); /* Cannot be NULL for pointer or array objects */
- if (PyObject_IsSubclass(v->proto, typedict->proto)) {
+ int ret = PyObject_IsSubclass(v->proto, typedict->proto);
+ if (ret < 0) {
+ return NULL;
+ }
+ if (ret) {
Py_INCREF(value);
return value;
}
PyObject *np;
StgDictObject *stgdict, *itemdict;
PyObject *proto;
- Py_ssize_t i, len, cur;
+ Py_ssize_t i, len;
+ size_t cur;
/* Since pointers have no length, and we want to apply
different semantics to negative indices than normal
((volatile TestReg *)&in)->second = 0x0badf00d;
}
+/*
+ * See bpo-22273. Structs containing arrays should work on Linux 64-bit.
+ */
+
+typedef struct {
+ unsigned char data[16];
+} Test2;
+
+EXPORT(int)
+_testfunc_array_in_struct1(Test2 in)
+{
+ int result = 0;
+
+ for (unsigned i = 0; i < 16; i++)
+ result += in.data[i];
+ /* As the structure is passed by value, changes to it shouldn't be
+ * reflected in the caller.
+ */
+ memset(in.data, 0, sizeof(in.data));
+ return result;
+}
+
+typedef struct {
+ double data[2];
+} Test3;
+
+typedef struct {
+ float data[2];
+ float more_data[2];
+} Test3B;
+
+EXPORT(double)
+_testfunc_array_in_struct2(Test3 in)
+{
+ double result = 0;
+
+ for (unsigned i = 0; i < 2; i++)
+ result += in.data[i];
+ /* As the structure is passed by value, changes to it shouldn't be
+ * reflected in the caller.
+ */
+ memset(in.data, 0, sizeof(in.data));
+ return result;
+}
+
+EXPORT(double)
+_testfunc_array_in_struct2a(Test3B in)
+{
+ double result = 0;
+
+ for (unsigned i = 0; i < 2; i++)
+ result += in.data[i];
+ for (unsigned i = 0; i < 2; i++)
+ result += in.more_data[i];
+ /* As the structure is passed by value, changes to it shouldn't be
+ * reflected in the caller.
+ */
+ memset(in.data, 0, sizeof(in.data));
+ return result;
+}
EXPORT(void)testfunc_array(int values[4])
{
static void LoadPython(void)
{
if (!Py_IsInitialized()) {
- PyEval_InitThreads();
Py_Initialize();
+ PyEval_InitThreads();
}
}
{
WCHAR *lpMsgBuf;
DWORD n;
- n = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ n = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
code,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
int pack = 0;
Py_ssize_t ffi_ofs;
int big_endian;
+ int arrays_seen = 0;
/* HACK Alert: I cannot be bothered to fix ctypes.com, so there has to
be a way to use the old, broken sematics: _fields_ are not extended
Py_XDECREF(pair);
return -1;
}
+ if (PyCArrayTypeObject_Check(desc))
+ arrays_seen = 1;
dict = PyType_stgdict(desc);
if (dict == NULL) {
Py_DECREF(pair);
stgdict->align = total_align;
stgdict->length = len; /* ADD ffi_ofs? */
+#define MAX_STRUCT_SIZE 16
+
+ if (arrays_seen && (size <= MAX_STRUCT_SIZE)) {
+ /*
+ * See bpo-22273. Arrays are normally treated as pointers, which is
+ * fine when an array name is being passed as parameter, but not when
+ * passing structures by value that contain arrays. On 64-bit Linux,
+ * small structures passed by value are passed in registers, and in
+ * order to do this, libffi needs to know the true type of the array
+ * members of structs. Treating them as pointers breaks things.
+ *
+ * By small structures, we mean ones that are 16 bytes or less. In that
+ * case, there can't be more than 16 elements after unrolling arrays,
+ * as we (will) disallow bitfields. So we can collect the true ffi_type
+ * values in a fixed-size local array on the stack and, if any arrays
+ * were seen, replace the ffi_type_pointer.elements with a more
+ * accurate set, to allow libffi to marshal them into registers
+ * correctly. It means one more loop over the fields, but if we got
+ * here, the structure is small, so there aren't too many of those.
+ *
+ * Although the passing in registers is specific to 64-bit Linux, the
+ * array-in-struct vs. pointer problem is general. But we restrict the
+ * type transformation to small structs nonetheless.
+ *
+ * Note that although a union may be small in terms of memory usage, it
+ * could contain many overlapping declarations of arrays, e.g.
+ *
+ * union {
+ * unsigned int_8 foo [16];
+ * unsigned uint_8 bar [16];
+ * unsigned int_16 baz[8];
+ * unsigned uint_16 bozz[8];
+ * unsigned int_32 fizz[4];
+ * unsigned uint_32 buzz[4];
+ * }
+ *
+ * which is still only 16 bytes in size. We need to convert this into
+ * the following equivalent for libffi:
+ *
+ * union {
+ * struct { int_8 e1; int_8 e2; ... int_8 e_16; } f1;
+ * struct { uint_8 e1; uint_8 e2; ... uint_8 e_16; } f2;
+ * struct { int_16 e1; int_16 e2; ... int_16 e_8; } f3;
+ * struct { uint_16 e1; uint_16 e2; ... uint_16 e_8; } f4;
+ * struct { int_32 e1; int_32 e2; ... int_32 e_4; } f5;
+ * struct { uint_32 e1; uint_32 e2; ... uint_32 e_4; } f6;
+ * }
+ *
+ * So the struct/union needs setting up as follows: all non-array
+ * elements copied across as is, and all array elements replaced with
+ * an equivalent struct which has as many fields as the array has
+ * elements, plus one NULL pointer.
+ */
+
+ Py_ssize_t num_ffi_type_pointers = 0; /* for the dummy fields */
+ Py_ssize_t num_ffi_types = 0; /* for the dummy structures */
+ size_t alloc_size; /* total bytes to allocate */
+ void *type_block; /* to hold all the type information needed */
+ ffi_type **element_types; /* of this struct/union */
+ ffi_type **dummy_types; /* of the dummy struct elements */
+ ffi_type *structs; /* point to struct aliases of arrays */
+ Py_ssize_t element_index; /* index into element_types for this */
+ Py_ssize_t dummy_index = 0; /* index into dummy field pointers */
+ Py_ssize_t struct_index = 0; /* index into dummy structs */
+
+ /* first pass to see how much memory to allocate */
+ for (i = 0; i < len; ++i) {
+ PyObject *name, *desc;
+ PyObject *pair = PySequence_GetItem(fields, i);
+ StgDictObject *dict;
+ int bitsize = 0;
+
+ if (pair == NULL) {
+ return -1;
+ }
+ if (!PyArg_ParseTuple(pair, "UO|i", &name, &desc, &bitsize)) {
+ PyErr_SetString(PyExc_TypeError,
+ "'_fields_' must be a sequence of (name, C type) pairs");
+ Py_DECREF(pair);
+ return -1;
+ }
+ dict = PyType_stgdict(desc);
+ if (dict == NULL) {
+ Py_DECREF(pair);
+ PyErr_Format(PyExc_TypeError,
+ "second item in _fields_ tuple (index %zd) must be a C type",
+ i);
+ return -1;
+ }
+ if (!PyCArrayTypeObject_Check(desc)) {
+ /* Not an array. Just need an ffi_type pointer. */
+ num_ffi_type_pointers++;
+ }
+ else {
+ /* It's an array. */
+ Py_ssize_t length = dict->length;
+ StgDictObject *edict;
+
+ edict = PyType_stgdict(dict->proto);
+ if (edict == NULL) {
+ Py_DECREF(pair);
+ PyErr_Format(PyExc_TypeError,
+ "second item in _fields_ tuple (index %zd) must be a C type",
+ i);
+ return -1;
+ }
+ /*
+ * We need one extra ffi_type to hold the struct, and one
+ * ffi_type pointer per array element + one for a NULL to
+ * mark the end.
+ */
+ num_ffi_types++;
+ num_ffi_type_pointers += length + 1;
+ }
+ Py_DECREF(pair);
+ }
+
+ /*
+ * At this point, we know we need storage for some ffi_types and some
+ * ffi_type pointers. We'll allocate these in one block.
+ * There are three sub-blocks of information: the ffi_type pointers to
+ * this structure/union's elements, the ffi_type_pointers to the
+ * dummy fields standing in for array elements, and the
+ * ffi_types representing the dummy structures.
+ */
+ alloc_size = (ffi_ofs + 1 + len + num_ffi_type_pointers) * sizeof(ffi_type *) +
+ num_ffi_types * sizeof(ffi_type);
+ type_block = PyMem_Malloc(alloc_size);
+
+ if (type_block == NULL) {
+ PyErr_NoMemory();
+ return -1;
+ }
+ /*
+ * the first block takes up ffi_ofs + len + 1 which is the pointers *
+ * for this struct/union. The second block takes up
+ * num_ffi_type_pointers, so the sum of these is ffi_ofs + len + 1 +
+ * num_ffi_type_pointers as allocated above. The last bit is the
+ * num_ffi_types structs.
+ */
+ element_types = (ffi_type **) type_block;
+ dummy_types = &element_types[ffi_ofs + len + 1];
+ structs = (ffi_type *) &dummy_types[num_ffi_type_pointers];
+
+ if (num_ffi_types > 0) {
+ memset(structs, 0, num_ffi_types * sizeof(ffi_type));
+ }
+ if (ffi_ofs && (basedict != NULL)) {
+ memcpy(element_types,
+ basedict->ffi_type_pointer.elements,
+ ffi_ofs * sizeof(ffi_type *));
+ }
+ element_index = ffi_ofs;
+
+ /* second pass to actually set the type pointers */
+ for (i = 0; i < len; ++i) {
+ PyObject *name, *desc;
+ PyObject *pair = PySequence_GetItem(fields, i);
+ StgDictObject *dict;
+ int bitsize = 0;
+
+ if (pair == NULL) {
+ PyMem_Free(type_block);
+ return -1;
+ }
+ /* In theory, we made this call in the first pass, so it *shouldn't*
+ * fail. However, you never know, and the code above might change
+ * later - keeping the check in here is a tad defensive but it
+ * will affect program size only slightly and performance hardly at
+ * all.
+ */
+ if (!PyArg_ParseTuple(pair, "UO|i", &name, &desc, &bitsize)) {
+ PyErr_SetString(PyExc_TypeError,
+ "'_fields_' must be a sequence of (name, C type) pairs");
+ Py_DECREF(pair);
+ PyMem_Free(type_block);
+ return -1;
+ }
+ dict = PyType_stgdict(desc);
+ /* Possibly this check could be avoided, but see above comment. */
+ if (dict == NULL) {
+ Py_DECREF(pair);
+ PyMem_Free(type_block);
+ PyErr_Format(PyExc_TypeError,
+ "second item in _fields_ tuple (index %zd) must be a C type",
+ i);
+ return -1;
+ }
+ assert(element_index < (ffi_ofs + len)); /* will be used below */
+ if (!PyCArrayTypeObject_Check(desc)) {
+ /* Not an array. Just copy over the element ffi_type. */
+ element_types[element_index++] = &dict->ffi_type_pointer;
+ }
+ else {
+ int length = dict->length;
+ StgDictObject *edict;
+
+ edict = PyType_stgdict(dict->proto);
+ if (edict == NULL) {
+ Py_DECREF(pair);
+ PyMem_Free(type_block);
+ PyErr_Format(PyExc_TypeError,
+ "second item in _fields_ tuple (index %zd) must be a C type",
+ i);
+ return -1;
+ }
+ element_types[element_index++] = &structs[struct_index];
+ structs[struct_index].size = length * edict->ffi_type_pointer.size;
+ structs[struct_index].alignment = edict->ffi_type_pointer.alignment;
+ structs[struct_index].type = FFI_TYPE_STRUCT;
+ structs[struct_index].elements = &dummy_types[dummy_index];
+ ++struct_index;
+ /* Copy over the element's type, length times. */
+ while (length > 0) {
+ assert(dummy_index < (num_ffi_type_pointers));
+ dummy_types[dummy_index++] = &edict->ffi_type_pointer;
+ length--;
+ }
+ assert(dummy_index < (num_ffi_type_pointers));
+ dummy_types[dummy_index++] = NULL;
+ }
+ Py_DECREF(pair);
+ }
+
+ element_types[element_index] = NULL;
+ /*
+ * Replace the old elements with the new, taking into account
+ * base class elements where necessary.
+ */
+ assert(stgdict->ffi_type_pointer.elements);
+ PyMem_Free(stgdict->ffi_type_pointer.elements);
+ stgdict->ffi_type_pointer.elements = element_types;
+ }
+
/* We did check that this flag was NOT set above, it must not
have been set until now. */
if (stgdict->flags & DICTFLAG_FINAL) {
/* Utility Functions */
+static inline int
+color_pair_to_attr(short color_number)
+{
+ return ((int)color_number << 8);
+}
+
+static inline short
+attr_to_color_pair(int attr)
+{
+ return (short)((attr & A_COLOR) >> 8);
+}
+
/*
* Check the return code from a curses function and return None
* or raise an exception as appropriate. These are exported using the
if (type == 2) {
funcname = "add_wch";
wstr[1] = L'\0';
- setcchar(&wcval, wstr, attr, 0, NULL);
+ setcchar(&wcval, wstr, attr, attr_to_color_pair(attr), NULL);
if (coordinates_group)
rtn = mvwadd_wch(cwself->win,y,x, &wcval);
else {
PyCursesInitialisedColor;
if (!PyArg_ParseTuple(args, "i:color_pair", &n)) return NULL;
- return PyLong_FromLong((long) (n << 8));
+ return PyLong_FromLong(color_pair_to_attr(n));
}
static PyObject *
return NULL;
}
- return PyLong_FromLong((long) ((n & A_COLOR) >> 8));
+ return PyLong_FromLong(attr_to_color_pair(n));
}
static PyObject *
wchar_t buffer[2];
if (PyUnicode_AsWideChar(obj, buffer, 2) != 1) {
PyErr_Format(PyExc_TypeError,
- "expect bytes or str of length 1, or int, "
+ "expect str of length 1 or int, "
"got a str of length %zi",
PyUnicode_GET_LENGTH(obj));
return 0;
}
else {
PyErr_Format(PyExc_TypeError,
- "expect bytes or str of length 1, or int, got %s",
+ "expect str of length 1 or int, got %s",
Py_TYPE(obj)->tp_name);
return 0;
}
#include "datetime.h"
#undef Py_BUILD_CORE
+#define PyTimezone_Check(op) PyObject_TypeCheck(op, &PyDateTime_TimeZoneType)
+
/*[clinic input]
module datetime
class datetime.datetime "PyDateTime_DateTime *" "&PyDateTime_DateTimeType"
Py_INCREF(PyDateTime_TimeZone_UTC);
return PyDateTime_TimeZone_UTC;
}
- if ((GET_TD_DAYS(offset) == -1 && GET_TD_SECONDS(offset) == 0) ||
+ if ((GET_TD_DAYS(offset) == -1 &&
+ GET_TD_SECONDS(offset) == 0 &&
+ GET_TD_MICROSECONDS(offset) < 1) ||
GET_TD_DAYS(offset) < -1 || GET_TD_DAYS(offset) >= 1) {
PyErr_Format(PyExc_ValueError, "offset must be a timedelta"
" strictly between -timedelta(hours=24) and"
if (offset == Py_None || offset == NULL)
return offset;
if (PyDelta_Check(offset)) {
- if ((GET_TD_DAYS(offset) == -1 && GET_TD_SECONDS(offset) == 0) ||
+ if ((GET_TD_DAYS(offset) == -1 &&
+ GET_TD_SECONDS(offset) == 0 &&
+ GET_TD_MICROSECONDS(offset) < 1) ||
GET_TD_DAYS(offset) < -1 || GET_TD_DAYS(offset) >= 1) {
Py_DECREF(offset);
PyErr_Format(PyExc_ValueError, "offset must be a timedelta"
{
if (op != Py_EQ && op != Py_NE)
Py_RETURN_NOTIMPLEMENTED;
- if (Py_TYPE(other) != &PyDateTime_TimeZoneType) {
- if (op == Py_EQ)
- Py_RETURN_FALSE;
- else
- Py_RETURN_TRUE;
+ if (!PyTimezone_Check(other)) {
+ Py_RETURN_NOTIMPLEMENTED;
}
return delta_richcompare(self->offset, other->offset, op);
}
return NULL;
}
if (PyUnicode_GET_LENGTH(state) == _PyDateTime_TIME_DATASIZE &&
- (0x7F & PyUnicode_READ_CHAR(state, 2)) < 24)
+ (0x7F & PyUnicode_READ_CHAR(state, 0)) < 24)
{
state = PyUnicode_AsLatin1String(state);
if (state == NULL) {
PyDateTime_TimeZone_UTC = x;
CAPI.TimeZone_UTC = PyDateTime_TimeZone_UTC;
+ /* bpo-37642: These attributes are rounded to the nearest minute for backwards
+ * compatibility, even though the constructor will accept a wider range of
+ * values. This may change in the future.*/
delta = new_delta(-1, 60, 0, 1); /* -23:59 */
if (delta == NULL)
return NULL;
{
PyObject *m, *openssl_md_meth_names;
-#ifndef OPENSSL_VERSION_1_1
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
/* Load all digest algorithms and initialize cpuid */
OPENSSL_add_all_algorithms_noconf();
ERR_load_crypto_strings();
PyObject *result;
lzma_stream *lzs = &d->lzs;
- if (lzs->avail_in == 0)
- return PyBytes_FromStringAndSize(NULL, 0);
-
if (max_length < 0 || max_length >= INITIAL_BUFFER_SIZE)
result = PyBytes_FromStringAndSize(NULL, INITIAL_BUFFER_SIZE);
else
Py_BEGIN_ALLOW_THREADS
lzret = lzma_code(lzs, LZMA_RUN);
data_size = (char *)lzs->next_out - PyBytes_AS_STRING(result);
+ if (lzret == LZMA_BUF_ERROR && lzs->avail_in == 0 && lzs->avail_out > 0)
+ lzret = LZMA_OK; /* That wasn't a real error */
Py_END_ALLOW_THREADS
+
if (catch_lzma_error(lzret))
goto error;
if (lzret == LZMA_GET_CHECK || lzret == LZMA_NO_CHECK)
if (lzret == LZMA_STREAM_END) {
d->eof = 1;
break;
- } else if (lzs->avail_in == 0) {
- break;
} else if (lzs->avail_out == 0) {
+ /* Need to check lzs->avail_out before lzs->avail_in.
+ Maybe lzs's internal state still have a few bytes
+ can be output, grow the output buffer and continue
+ if max_lengh < 0. */
if (data_size == max_length)
break;
if (grow_buffer(&result, max_length) == -1)
goto error;
lzs->next_out = (uint8_t *)PyBytes_AS_STRING(result) + data_size;
lzs->avail_out = PyBytes_GET_SIZE(result) - data_size;
+ } else if (lzs->avail_in == 0) {
+ break;
}
}
if (data_size != PyBytes_GET_SIZE(result))
}
else if (lzs->avail_in == 0) {
lzs->next_in = NULL;
- d->needs_input = 1;
+
+ if (lzs->avail_out == 0) {
+ /* (avail_in==0 && avail_out==0)
+ Maybe lzs's internal state still have a few bytes can
+ be output, try to output them next time. */
+ d->needs_input = 0;
+
+ /* if max_length < 0, lzs->avail_out always > 0 */
+ assert(max_length >= 0);
+ } else {
+ /* Input buffer exhausted, output buffer has space. */
+ d->needs_input = 1;
+ }
}
else {
d->needs_input = 0;
/* How many bytes do we need? There are nbits >> 3 full
* bytes of data, and nbits & 7 leftover bits. If there
* are any leftover bits, then we clearly need another
- * byte. Wnat's not so obvious is that we *probably*
+ * byte. What's not so obvious is that we *probably*
* need another byte even if there aren't any leftovers:
* the most-significant bit of the most-significant byte
* acts like a sign bit, and it's usually got a sense
return item;
}
+static int
+equal_ignore_case(PyObject *left, PyObject *right)
+{
+ int eq = PyObject_RichCompareBool(left, right, Py_EQ);
+ if (eq) { /* equal or error */
+ return eq;
+ }
+ if (!PyUnicode_Check(left) || !PyUnicode_Check(right)) {
+ return 0;
+ }
+ if (!PyUnicode_IS_ASCII(left) || !PyUnicode_IS_ASCII(right)) {
+ return 0;
+ }
+
+ Py_ssize_t len = PyUnicode_GET_LENGTH(left);
+ if (PyUnicode_GET_LENGTH(right) != len) {
+ return 0;
+ }
+ const Py_UCS1 *p1 = PyUnicode_1BYTE_DATA(left);
+ const Py_UCS1 *p2 = PyUnicode_1BYTE_DATA(right);
+ for (; len; len--, p1++, p2++) {
+ if (Py_TOLOWER(*p1) != Py_TOLOWER(*p2)) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
PyObject* pysqlite_row_subscript(pysqlite_Row* self, PyObject* idx)
{
Py_ssize_t _idx;
- const char *key;
Py_ssize_t nitems, i;
- const char *compare_key;
-
- const char *p1;
- const char *p2;
-
PyObject* item;
if (PyLong_Check(idx)) {
Py_XINCREF(item);
return item;
} else if (PyUnicode_Check(idx)) {
- key = PyUnicode_AsUTF8(idx);
- if (key == NULL)
- return NULL;
-
nitems = PyTuple_Size(self->description);
for (i = 0; i < nitems; i++) {
PyObject *obj;
obj = PyTuple_GET_ITEM(self->description, i);
obj = PyTuple_GET_ITEM(obj, 0);
- compare_key = PyUnicode_AsUTF8(obj);
- if (!compare_key) {
+ int eq = equal_ignore_case(idx, obj);
+ if (eq < 0) {
return NULL;
}
-
- p1 = key;
- p2 = compare_key;
-
- while (1) {
- if ((*p1 == (char)0) || (*p2 == (char)0)) {
- break;
- }
-
- if ((*p1 | 0x20) != (*p2 | 0x20)) {
- break;
- }
-
- p1++;
- p2++;
- }
-
- if ((*p1 == (char)0) && (*p2 == (char)0)) {
+ if (eq) {
/* found item */
item = PyTuple_GetItem(self->data, i);
Py_INCREF(item);
return item;
}
-
}
PyErr_SetString(PyExc_IndexError, "No item with that key");
if (opid != Py_EQ && opid != Py_NE)
Py_RETURN_NOTIMPLEMENTED;
- if (PyType_IsSubtype(Py_TYPE(_other), &pysqlite_RowType)) {
+ if (PyObject_TypeCheck(_other, &pysqlite_RowType)) {
pysqlite_Row *other = (pysqlite_Row *)_other;
- PyObject *res = PyObject_RichCompare(self->description, other->description, opid);
- if ((opid == Py_EQ && res == Py_True)
- || (opid == Py_NE && res == Py_False)) {
- Py_DECREF(res);
+ int eq = PyObject_RichCompareBool(self->description, other->description, Py_EQ);
+ if (eq < 0) {
+ return NULL;
+ }
+ if (eq) {
return PyObject_RichCompare(self->data, other->data, opid);
}
+ return PyBool_FromLong(opid != Py_EQ);
}
Py_RETURN_NOTIMPLEMENTED;
}
goto fail0;
}
- x = PEM_read_bio_X509_AUX(cert,NULL, NULL, NULL);
+ x = PEM_read_bio_X509(cert, NULL, NULL, NULL);
if (x == NULL) {
PyErr_SetString(PySSLErrorObject,
"Error decoding PEM-encoded file");
}
return PyErr_SetFromWindowsErr(error);
}
- retval = PySet_New(NULL);
+ retval = PyFrozenSet_New(NULL);
if (retval == NULL) {
goto error;
}
if (result) {
++storesAdded;
}
+ CertCloseStore(hSystemStore, 0); /* flag must be 0 */
}
}
if (storesAdded == 0) {
return hCollectionStore;
}
-/* code from Objects/listobject.c */
-
-static int
-list_contains(PyListObject *a, PyObject *el)
-{
- Py_ssize_t i;
- int cmp;
-
- for (i = 0, cmp = 0 ; cmp == 0 && i < Py_SIZE(a); ++i)
- cmp = PyObject_RichCompareBool(el, PyList_GET_ITEM(a, i),
- Py_EQ);
- return cmp;
-}
-
/*[clinic input]
_ssl.enum_certificates
store_name: str
PyObject *keyusage = NULL, *cert = NULL, *enc = NULL, *tup = NULL;
PyObject *result = NULL;
- result = PyList_New(0);
+ result = PySet_New(NULL);
if (result == NULL) {
return NULL;
}
enc = NULL;
PyTuple_SET_ITEM(tup, 2, keyusage);
keyusage = NULL;
- if (!list_contains((PyListObject*)result, tup)) {
- if (PyList_Append(result, tup) < 0) {
- Py_CLEAR(result);
- break;
- }
+ if (PySet_Add(result, tup) == -1) {
+ Py_CLEAR(result);
+ Py_CLEAR(tup);
+ break;
}
Py_CLEAR(tup);
}
return PyErr_SetFromWindowsErr(GetLastError());
}
- return result;
+ /* convert set to list */
+ if (result == NULL) {
+ return NULL;
+ } else {
+ PyObject *lst = PySequence_List(result);
+ Py_DECREF(result);
+ return lst;
+ }
}
/*[clinic input]
PyObject *crl = NULL, *enc = NULL, *tup = NULL;
PyObject *result = NULL;
- result = PyList_New(0);
+ result = PySet_New(NULL);
if (result == NULL) {
return NULL;
}
PyTuple_SET_ITEM(tup, 1, enc);
enc = NULL;
- if (!list_contains((PyListObject*)result, tup)) {
- if (PyList_Append(result, tup) < 0) {
- Py_CLEAR(result);
- break;
- }
+ if (PySet_Add(result, tup) == -1) {
+ Py_CLEAR(result);
+ Py_CLEAR(tup);
+ break;
}
Py_CLEAR(tup);
}
Py_XDECREF(result);
return PyErr_SetFromWindowsErr(GetLastError());
}
- return result;
+ /* convert set to list */
+ if (result == NULL) {
+ return NULL;
+ } else {
+ PyObject *lst = PySequence_List(result);
+ Py_DECREF(result);
+ return lst;
+ }
}
#endif /* _MSC_VER */
testmultiphase_state *m_state;
m_state = PyModule_GetState(self);
+
+ /* The following assertion mimics any traversal function that doesn't correctly handle
+ * the case during module creation where the module state hasn't been created yet.
+ *
+ * The check that it is used to test only runs in debug mode, so it is OK that the
+ * assert() will get compiled out in fully optimised release builds.
+ */
+ assert(m_state != NULL);
Py_VISIT(m_state->integer);
return 0;
}
*/
/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
-/* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML,
-/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
-/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
-/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
-/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
-/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
-/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
-/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
-/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
-/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
-/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
-/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
-/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
-/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
-/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
-/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
-/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
+ /* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+ /* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
+ /* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML,
+ /* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+ /* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+ /* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+ /* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+ /* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
+ /* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
+ /* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
+ /* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
+ /* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+ /* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+ /* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
+ /* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
+ /* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+ /* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+ /* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
+ /* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
+ /* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+ /* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+ /* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+ /* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
#ifndef Expat_INCLUDED
#define Expat_INCLUDED 1
-#ifdef __VMS
-/* 0 1 2 3 0 1 2 3
- 1234567890123456789012345678901 1234567890123456789012345678901 */
-#define XML_SetProcessingInstructionHandler XML_SetProcessingInstrHandler
-#define XML_SetUnparsedEntityDeclHandler XML_SetUnparsedEntDeclHandler
-#define XML_SetStartNamespaceDeclHandler XML_SetStartNamespcDeclHandler
-#define XML_SetExternalEntityRefHandlerArg XML_SetExternalEntRefHandlerArg
-#endif
-
#include <stdlib.h>
#include "expat_external.h"
typedef struct XML_ParserStruct *XML_Parser;
typedef unsigned char XML_Bool;
-#define XML_TRUE ((XML_Bool) 1)
-#define XML_FALSE ((XML_Bool) 0)
+#define XML_TRUE ((XML_Bool)1)
+#define XML_FALSE ((XML_Bool)0)
/* The XML_Status enum gives the possible return values for several
API functions. The preprocessor #defines are included so this
typedef struct XML_cp XML_Content;
struct XML_cp {
- enum XML_Content_Type type;
- enum XML_Content_Quant quant;
- XML_Char * name;
- unsigned int numchildren;
- XML_Content * children;
+ enum XML_Content_Type type;
+ enum XML_Content_Quant quant;
+ XML_Char *name;
+ unsigned int numchildren;
+ XML_Content *children;
};
-
/* This is called for an element declaration. See above for
description of the model argument. It's the caller's responsibility
to free model when finished with it.
*/
-typedef void (XMLCALL *XML_ElementDeclHandler) (void *userData,
- const XML_Char *name,
- XML_Content *model);
+typedef void(XMLCALL *XML_ElementDeclHandler)(void *userData,
+ const XML_Char *name,
+ XML_Content *model);
XMLPARSEAPI(void)
-XML_SetElementDeclHandler(XML_Parser parser,
- XML_ElementDeclHandler eldecl);
+XML_SetElementDeclHandler(XML_Parser parser, XML_ElementDeclHandler eldecl);
/* The Attlist declaration handler is called for *each* attribute. So
a single Attlist declaration with multiple attributes declared will
value will be NULL in the case of "#REQUIRED". If "isrequired" is
true and default is non-NULL, then this is a "#FIXED" default.
*/
-typedef void (XMLCALL *XML_AttlistDeclHandler) (
- void *userData,
- const XML_Char *elname,
- const XML_Char *attname,
- const XML_Char *att_type,
- const XML_Char *dflt,
- int isrequired);
+typedef void(XMLCALL *XML_AttlistDeclHandler)(
+ void *userData, const XML_Char *elname, const XML_Char *attname,
+ const XML_Char *att_type, const XML_Char *dflt, int isrequired);
XMLPARSEAPI(void)
-XML_SetAttlistDeclHandler(XML_Parser parser,
- XML_AttlistDeclHandler attdecl);
+XML_SetAttlistDeclHandler(XML_Parser parser, XML_AttlistDeclHandler attdecl);
/* The XML declaration handler is called for *both* XML declarations
and text declarations. The way to distinguish is that the version
was no standalone parameter in the declaration, that it was given
as no, or that it was given as yes.
*/
-typedef void (XMLCALL *XML_XmlDeclHandler) (void *userData,
- const XML_Char *version,
- const XML_Char *encoding,
- int standalone);
+typedef void(XMLCALL *XML_XmlDeclHandler)(void *userData,
+ const XML_Char *version,
+ const XML_Char *encoding,
+ int standalone);
XMLPARSEAPI(void)
-XML_SetXmlDeclHandler(XML_Parser parser,
- XML_XmlDeclHandler xmldecl);
-
+XML_SetXmlDeclHandler(XML_Parser parser, XML_XmlDeclHandler xmldecl);
typedef struct {
void *(*malloc_fcn)(size_t size);
XMLPARSEAPI(XML_Parser)
XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator);
-
/* Constructs a new parser using the memory management suite referred to
by memsuite. If memsuite is NULL, then use the standard library memory
suite. If namespaceSeparator is non-NULL it creates a parser with
/* atts is array of name/value pairs, terminated by 0;
names and values are 0 terminated.
*/
-typedef void (XMLCALL *XML_StartElementHandler) (void *userData,
- const XML_Char *name,
- const XML_Char **atts);
-
-typedef void (XMLCALL *XML_EndElementHandler) (void *userData,
- const XML_Char *name);
+typedef void(XMLCALL *XML_StartElementHandler)(void *userData,
+ const XML_Char *name,
+ const XML_Char **atts);
+typedef void(XMLCALL *XML_EndElementHandler)(void *userData,
+ const XML_Char *name);
/* s is not 0 terminated. */
-typedef void (XMLCALL *XML_CharacterDataHandler) (void *userData,
- const XML_Char *s,
- int len);
+typedef void(XMLCALL *XML_CharacterDataHandler)(void *userData,
+ const XML_Char *s, int len);
/* target and data are 0 terminated */
-typedef void (XMLCALL *XML_ProcessingInstructionHandler) (
- void *userData,
- const XML_Char *target,
- const XML_Char *data);
+typedef void(XMLCALL *XML_ProcessingInstructionHandler)(void *userData,
+ const XML_Char *target,
+ const XML_Char *data);
/* data is 0 terminated */
-typedef void (XMLCALL *XML_CommentHandler) (void *userData,
- const XML_Char *data);
+typedef void(XMLCALL *XML_CommentHandler)(void *userData, const XML_Char *data);
-typedef void (XMLCALL *XML_StartCdataSectionHandler) (void *userData);
-typedef void (XMLCALL *XML_EndCdataSectionHandler) (void *userData);
+typedef void(XMLCALL *XML_StartCdataSectionHandler)(void *userData);
+typedef void(XMLCALL *XML_EndCdataSectionHandler)(void *userData);
/* This is called for any characters in the XML document for which
there is no applicable handler. This includes both characters that
default handler: for example, a comment might be split between
multiple calls.
*/
-typedef void (XMLCALL *XML_DefaultHandler) (void *userData,
- const XML_Char *s,
- int len);
+typedef void(XMLCALL *XML_DefaultHandler)(void *userData, const XML_Char *s,
+ int len);
/* This is called for the start of the DOCTYPE declaration, before
any DTD or internal subset is parsed.
*/
-typedef void (XMLCALL *XML_StartDoctypeDeclHandler) (
- void *userData,
- const XML_Char *doctypeName,
- const XML_Char *sysid,
- const XML_Char *pubid,
- int has_internal_subset);
+typedef void(XMLCALL *XML_StartDoctypeDeclHandler)(void *userData,
+ const XML_Char *doctypeName,
+ const XML_Char *sysid,
+ const XML_Char *pubid,
+ int has_internal_subset);
/* This is called for the start of the DOCTYPE declaration when the
closing > is encountered, but after processing any external
subset.
*/
-typedef void (XMLCALL *XML_EndDoctypeDeclHandler)(void *userData);
+typedef void(XMLCALL *XML_EndDoctypeDeclHandler)(void *userData);
/* This is called for entity declarations. The is_parameter_entity
argument will be non-zero if the entity is a parameter entity, zero
Note that is_parameter_entity can't be changed to XML_Bool, since
that would break binary compatibility.
*/
-typedef void (XMLCALL *XML_EntityDeclHandler) (
- void *userData,
- const XML_Char *entityName,
- int is_parameter_entity,
- const XML_Char *value,
- int value_length,
- const XML_Char *base,
- const XML_Char *systemId,
- const XML_Char *publicId,
- const XML_Char *notationName);
+typedef void(XMLCALL *XML_EntityDeclHandler)(
+ void *userData, const XML_Char *entityName, int is_parameter_entity,
+ const XML_Char *value, int value_length, const XML_Char *base,
+ const XML_Char *systemId, const XML_Char *publicId,
+ const XML_Char *notationName);
XMLPARSEAPI(void)
-XML_SetEntityDeclHandler(XML_Parser parser,
- XML_EntityDeclHandler handler);
+XML_SetEntityDeclHandler(XML_Parser parser, XML_EntityDeclHandler handler);
/* OBSOLETE -- OBSOLETE -- OBSOLETE
This handler has been superseded by the EntityDeclHandler above.
entityName, systemId and notationName arguments will never be
NULL. The other arguments may be.
*/
-typedef void (XMLCALL *XML_UnparsedEntityDeclHandler) (
- void *userData,
- const XML_Char *entityName,
- const XML_Char *base,
- const XML_Char *systemId,
- const XML_Char *publicId,
- const XML_Char *notationName);
+typedef void(XMLCALL *XML_UnparsedEntityDeclHandler)(
+ void *userData, const XML_Char *entityName, const XML_Char *base,
+ const XML_Char *systemId, const XML_Char *publicId,
+ const XML_Char *notationName);
/* This is called for a declaration of notation. The base argument is
whatever was set by XML_SetBase. The notationName will never be
NULL. The other arguments can be.
*/
-typedef void (XMLCALL *XML_NotationDeclHandler) (
- void *userData,
- const XML_Char *notationName,
- const XML_Char *base,
- const XML_Char *systemId,
- const XML_Char *publicId);
+typedef void(XMLCALL *XML_NotationDeclHandler)(void *userData,
+ const XML_Char *notationName,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId);
/* When namespace processing is enabled, these are called once for
each namespace declaration. The call to the start and end element
declaration handlers. For an xmlns attribute, prefix will be
NULL. For an xmlns="" attribute, uri will be NULL.
*/
-typedef void (XMLCALL *XML_StartNamespaceDeclHandler) (
- void *userData,
- const XML_Char *prefix,
- const XML_Char *uri);
+typedef void(XMLCALL *XML_StartNamespaceDeclHandler)(void *userData,
+ const XML_Char *prefix,
+ const XML_Char *uri);
-typedef void (XMLCALL *XML_EndNamespaceDeclHandler) (
- void *userData,
- const XML_Char *prefix);
+typedef void(XMLCALL *XML_EndNamespaceDeclHandler)(void *userData,
+ const XML_Char *prefix);
/* This is called if the document is not standalone, that is, it has an
external subset or a reference to a parameter entity, but does not
conditions above this handler will only be called if the referenced
entity was actually read.
*/
-typedef int (XMLCALL *XML_NotStandaloneHandler) (void *userData);
+typedef int(XMLCALL *XML_NotStandaloneHandler)(void *userData);
/* This is called for a reference to an external parsed general
entity. The referenced entity is not automatically parsed. The
Note that unlike other handlers the first argument is the parser,
not userData.
*/
-typedef int (XMLCALL *XML_ExternalEntityRefHandler) (
- XML_Parser parser,
- const XML_Char *context,
- const XML_Char *base,
- const XML_Char *systemId,
- const XML_Char *publicId);
+typedef int(XMLCALL *XML_ExternalEntityRefHandler)(XML_Parser parser,
+ const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId);
/* This is called in two situations:
1) An entity reference is encountered for which no declaration
the event would be out of sync with the reporting of the
declarations or attribute values
*/
-typedef void (XMLCALL *XML_SkippedEntityHandler) (
- void *userData,
- const XML_Char *entityName,
- int is_parameter_entity);
+typedef void(XMLCALL *XML_SkippedEntityHandler)(void *userData,
+ const XML_Char *entityName,
+ int is_parameter_entity);
/* This structure is filled in by the XML_UnknownEncodingHandler to
provide information to the parser about encodings that are unknown
typedef struct {
int map[256];
void *data;
- int (XMLCALL *convert)(void *data, const char *s);
- void (XMLCALL *release)(void *data);
+ int(XMLCALL *convert)(void *data, const char *s);
+ void(XMLCALL *release)(void *data);
} XML_Encoding;
/* This is called for an encoding that is unknown to the parser.
If info does not describe a suitable encoding, then the parser will
return an XML_UNKNOWN_ENCODING error.
*/
-typedef int (XMLCALL *XML_UnknownEncodingHandler) (
- void *encodingHandlerData,
- const XML_Char *name,
- XML_Encoding *info);
+typedef int(XMLCALL *XML_UnknownEncodingHandler)(void *encodingHandlerData,
+ const XML_Char *name,
+ XML_Encoding *info);
XMLPARSEAPI(void)
-XML_SetElementHandler(XML_Parser parser,
- XML_StartElementHandler start,
+XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start,
XML_EndElementHandler end);
XMLPARSEAPI(void)
-XML_SetStartElementHandler(XML_Parser parser,
- XML_StartElementHandler handler);
+XML_SetStartElementHandler(XML_Parser parser, XML_StartElementHandler handler);
XMLPARSEAPI(void)
-XML_SetEndElementHandler(XML_Parser parser,
- XML_EndElementHandler handler);
+XML_SetEndElementHandler(XML_Parser parser, XML_EndElementHandler handler);
XMLPARSEAPI(void)
XML_SetCharacterDataHandler(XML_Parser parser,
XML_SetProcessingInstructionHandler(XML_Parser parser,
XML_ProcessingInstructionHandler handler);
XMLPARSEAPI(void)
-XML_SetCommentHandler(XML_Parser parser,
- XML_CommentHandler handler);
+XML_SetCommentHandler(XML_Parser parser, XML_CommentHandler handler);
XMLPARSEAPI(void)
XML_SetCdataSectionHandler(XML_Parser parser,
default handler, or to the skipped entity handler, if one is set.
*/
XMLPARSEAPI(void)
-XML_SetDefaultHandler(XML_Parser parser,
- XML_DefaultHandler handler);
+XML_SetDefaultHandler(XML_Parser parser, XML_DefaultHandler handler);
/* This sets the default handler but does not inhibit expansion of
internal entities. The entity reference will not be passed to the
default handler.
*/
XMLPARSEAPI(void)
-XML_SetDefaultHandlerExpand(XML_Parser parser,
- XML_DefaultHandler handler);
+XML_SetDefaultHandlerExpand(XML_Parser parser, XML_DefaultHandler handler);
XMLPARSEAPI(void)
-XML_SetDoctypeDeclHandler(XML_Parser parser,
- XML_StartDoctypeDeclHandler start,
+XML_SetDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start,
XML_EndDoctypeDeclHandler end);
XMLPARSEAPI(void)
XML_StartDoctypeDeclHandler start);
XMLPARSEAPI(void)
-XML_SetEndDoctypeDeclHandler(XML_Parser parser,
- XML_EndDoctypeDeclHandler end);
+XML_SetEndDoctypeDeclHandler(XML_Parser parser, XML_EndDoctypeDeclHandler end);
XMLPARSEAPI(void)
XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
XML_UnparsedEntityDeclHandler handler);
XMLPARSEAPI(void)
-XML_SetNotationDeclHandler(XML_Parser parser,
- XML_NotationDeclHandler handler);
+XML_SetNotationDeclHandler(XML_Parser parser, XML_NotationDeclHandler handler);
XMLPARSEAPI(void)
XML_SetNamespaceDeclHandler(XML_Parser parser,
instead of the parser object.
*/
XMLPARSEAPI(void)
-XML_SetExternalEntityRefHandlerArg(XML_Parser parser,
- void *arg);
+XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg);
XMLPARSEAPI(void)
XML_SetSkippedEntityHandler(XML_Parser parser,
XMLPARSEAPI(enum XML_Error)
XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD);
-
/* Sets the base to be used for resolving relative URIs in system
identifiers in declarations. Resolving relative identifiers is
left to the application: this value will be passed through as the
info->valueEnd - info->valueStart = 4 bytes.
*/
typedef struct {
- XML_Index nameStart; /* Offset to beginning of the attribute name. */
- XML_Index nameEnd; /* Offset after the attribute name's last byte. */
- XML_Index valueStart; /* Offset to beginning of the attribute value. */
- XML_Index valueEnd; /* Offset after the attribute value's last byte. */
+ XML_Index nameStart; /* Offset to beginning of the attribute name. */
+ XML_Index nameEnd; /* Offset after the attribute name's last byte. */
+ XML_Index valueStart; /* Offset to beginning of the attribute value. */
+ XML_Index valueEnd; /* Offset after the attribute value's last byte. */
} XML_AttrInfo;
/* Returns an array of XML_AttrInfo structures for the attribute/value pairs
(resumable = 0) an already suspended parser. Some call-backs may
still follow because they would otherwise get lost. Examples:
- endElementHandler() for empty elements when stopped in
- startElementHandler(),
- - endNameSpaceDeclHandler() when stopped in endElementHandler(),
+ startElementHandler(),
+ - endNameSpaceDeclHandler() when stopped in endElementHandler(),
and possibly others.
Can be called from most handlers, including DTD related call-backs,
except when parsing an external parameter entity and resumable != 0.
Returns XML_STATUS_OK when successful, XML_STATUS_ERROR otherwise.
- Possible error codes:
+ Possible error codes:
- XML_ERROR_SUSPENDED: when suspending an already suspended parser.
- XML_ERROR_FINISHED: when the parser has already finished.
- XML_ERROR_SUSPEND_PE: when suspending while parsing an external PE.
- When resumable != 0 (true) then parsing is suspended, that is,
- XML_Parse() and XML_ParseBuffer() return XML_STATUS_SUSPENDED.
+ When resumable != 0 (true) then parsing is suspended, that is,
+ XML_Parse() and XML_ParseBuffer() return XML_STATUS_SUSPENDED.
Otherwise, parsing is aborted, that is, XML_Parse() and XML_ParseBuffer()
return XML_STATUS_ERROR with error code XML_ERROR_ABORTED.
the externalEntityRefHandler() to call XML_StopParser() on the parent
parser (recursively), if one wants to stop parsing altogether.
- When suspended, parsing can be resumed by calling XML_ResumeParser().
+ When suspended, parsing can be resumed by calling XML_ResumeParser().
*/
XMLPARSEAPI(enum XML_Status)
XML_StopParser(XML_Parser parser, XML_Bool resumable);
/* Resumes parsing after it has been suspended with XML_StopParser().
Must not be called from within a handler call-back. Returns same
status codes as XML_Parse() or XML_ParseBuffer().
- Additional error code XML_ERROR_NOT_SUSPENDED possible.
+ Additional error code XML_ERROR_NOT_SUSPENDED possible.
*Note*:
This must be called on the most deeply nested child parser instance
XMLPARSEAPI(enum XML_Status)
XML_ResumeParser(XML_Parser parser);
-enum XML_Parsing {
- XML_INITIALIZED,
- XML_PARSING,
- XML_FINISHED,
- XML_SUSPENDED
-};
+enum XML_Parsing { XML_INITIALIZED, XML_PARSING, XML_FINISHED, XML_SUSPENDED };
typedef struct {
enum XML_Parsing parsing;
Otherwise returns a new XML_Parser object.
*/
XMLPARSEAPI(XML_Parser)
-XML_ExternalEntityParserCreate(XML_Parser parser,
- const XML_Char *context,
+XML_ExternalEntityParserCreate(XML_Parser parser, const XML_Char *context,
const XML_Char *encoding);
enum XML_ParamEntityParsing {
Note: If parser == NULL, the function will do nothing and return 0.
*/
XMLPARSEAPI(int)
-XML_SetHashSalt(XML_Parser parser,
- unsigned long hash_salt);
+XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt);
/* If XML_Parse or XML_ParseBuffer have returned XML_STATUS_ERROR, then
XML_GetErrorCode returns information about the error.
be within the relevant markup. When called outside of the callback
functions, the position indicated will be just past the last parse
event (regardless of whether there was an associated callback).
-
+
They may also be called after returning from a call to XML_Parse
or XML_ParseBuffer. If the return value is XML_STATUS_ERROR then
the location is the location of the character at which the error
the handler that makes the call.
*/
XMLPARSEAPI(const char *)
-XML_GetInputContext(XML_Parser parser,
- int *offset,
- int *size);
+XML_GetInputContext(XML_Parser parser, int *offset, int *size);
/* For backwards compatibility with previous versions. */
-#define XML_GetErrorLineNumber XML_GetCurrentLineNumber
+#define XML_GetErrorLineNumber XML_GetCurrentLineNumber
#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber
-#define XML_GetErrorByteIndex XML_GetCurrentByteIndex
+#define XML_GetErrorByteIndex XML_GetCurrentByteIndex
/* Frees the content model passed to the element declaration handler */
XMLPARSEAPI(void)
};
typedef struct {
- enum XML_FeatureEnum feature;
- const XML_LChar *name;
- long int value;
+ enum XML_FeatureEnum feature;
+ const XML_LChar *name;
+ long int value;
} XML_Feature;
XMLPARSEAPI(const XML_Feature *)
XML_GetFeatureList(void);
-
/* Expat follows the semantic versioning convention.
See http://semver.org.
*/
#define XML_MAJOR_VERSION 2
#define XML_MINOR_VERSION 2
-#define XML_MICRO_VERSION 7
+#define XML_MICRO_VERSION 8
#ifdef __cplusplus
}
/* External API definitions */
-#if defined(_MSC_EXTENSIONS) && !defined(__BEOS__) && !defined(__CYGWIN__)
-# define XML_USE_MSC_EXTENSIONS 1
-#endif
-
/* Expat tries very hard to make the API boundary very specifically
defined. There are two macros defined to control this boundary;
each of these can be defined before including this header to
compiled with the cdecl calling convention as the default since
system headers may assume the cdecl convention.
*/
+
+/* Namespace external symbols to allow multiple libexpat version to
+ co-exist. */
+#include "pyexpatns.h"
+
#ifndef XMLCALL
-# if defined(_MSC_VER)
-# define XMLCALL __cdecl
-# elif defined(__GNUC__) && defined(__i386) && !defined(__INTEL_COMPILER)
-# define XMLCALL __attribute__((cdecl))
-# else
+# if defined(_MSC_VER)
+# define XMLCALL __cdecl
+# elif defined(__GNUC__) && defined(__i386) && ! defined(__INTEL_COMPILER)
+# define XMLCALL __attribute__((cdecl))
+# else
/* For any platform which uses this definition and supports more than
one calling convention, we need to extend this definition to
declare the convention used on that platform, if it's possible to
pre-processor and how to specify the same calling convention as the
platform's malloc() implementation.
*/
-# define XMLCALL
-# endif
-#endif /* not defined XMLCALL */
-
-/* Namespace external symbols to allow multiple libexpat version to
- co-exist. */
-#include "pyexpatns.h"
-
+# define XMLCALL
+# endif
+#endif /* not defined XMLCALL */
-#if !defined(XML_STATIC) && !defined(XMLIMPORT)
-# ifndef XML_BUILDING_EXPAT
+#if ! defined(XML_STATIC) && ! defined(XMLIMPORT)
+# ifndef XML_BUILDING_EXPAT
/* using Expat from an application */
-# ifdef XML_USE_MSC_EXTENSIONS
-# define XMLIMPORT __declspec(dllimport)
-# endif
+# if defined(_MSC_EXTENSIONS) && ! defined(__BEOS__) && ! defined(__CYGWIN__)
+# define XMLIMPORT __declspec(dllimport)
+# endif
-# endif
-#endif /* not defined XML_STATIC */
+# endif
+#endif /* not defined XML_STATIC */
#ifndef XML_ENABLE_VISIBILITY
-# define XML_ENABLE_VISIBILITY 0
+# define XML_ENABLE_VISIBILITY 0
#endif
-#if !defined(XMLIMPORT) && XML_ENABLE_VISIBILITY
-# define XMLIMPORT __attribute__ ((visibility ("default")))
+#if ! defined(XMLIMPORT) && XML_ENABLE_VISIBILITY
+# define XMLIMPORT __attribute__((visibility("default")))
#endif
/* If we didn't define it above, define it away: */
#ifndef XMLIMPORT
-# define XMLIMPORT
+# define XMLIMPORT
#endif
-#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96))
-# define XML_ATTR_MALLOC __attribute__((__malloc__))
+#if defined(__GNUC__) \
+ && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96))
+# define XML_ATTR_MALLOC __attribute__((__malloc__))
#else
-# define XML_ATTR_MALLOC
+# define XML_ATTR_MALLOC
#endif
-#if defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
-# define XML_ATTR_ALLOC_SIZE(x) __attribute__((__alloc_size__(x)))
+#if defined(__GNUC__) \
+ && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
+# define XML_ATTR_ALLOC_SIZE(x) __attribute__((__alloc_size__(x)))
#else
-# define XML_ATTR_ALLOC_SIZE(x)
+# define XML_ATTR_ALLOC_SIZE(x)
#endif
#define XMLPARSEAPI(type) XMLIMPORT type XMLCALL
#endif
#ifdef XML_UNICODE_WCHAR_T
-# ifndef XML_UNICODE
-# define XML_UNICODE
-# endif
-# if defined(__SIZEOF_WCHAR_T__) && (__SIZEOF_WCHAR_T__ != 2)
-# error "sizeof(wchar_t) != 2; Need -fshort-wchar for both Expat and libc"
-# endif
+# ifndef XML_UNICODE
+# define XML_UNICODE
+# endif
+# if defined(__SIZEOF_WCHAR_T__) && (__SIZEOF_WCHAR_T__ != 2)
+# error "sizeof(wchar_t) != 2; Need -fshort-wchar for both Expat and libc"
+# endif
#endif
-#ifdef XML_UNICODE /* Information is UTF-16 encoded. */
-# ifdef XML_UNICODE_WCHAR_T
+#ifdef XML_UNICODE /* Information is UTF-16 encoded. */
+# ifdef XML_UNICODE_WCHAR_T
typedef wchar_t XML_Char;
typedef wchar_t XML_LChar;
-# else
+# else
typedef unsigned short XML_Char;
typedef char XML_LChar;
-# endif /* XML_UNICODE_WCHAR_T */
-#else /* Information is UTF-8 encoded. */
+# endif /* XML_UNICODE_WCHAR_T */
+#else /* Information is UTF-8 encoded. */
typedef char XML_Char;
typedef char XML_LChar;
-#endif /* XML_UNICODE */
+#endif /* XML_UNICODE */
-#ifdef XML_LARGE_SIZE /* Use large integers for file/stream positions. */
-# if defined(XML_USE_MSC_EXTENSIONS) && _MSC_VER < 1400
-typedef __int64 XML_Index;
-typedef unsigned __int64 XML_Size;
-# else
+#ifdef XML_LARGE_SIZE /* Use large integers for file/stream positions. */
typedef long long XML_Index;
typedef unsigned long long XML_Size;
-# endif
#else
typedef long XML_Index;
typedef unsigned long XML_Size;
/* Like asciitab.h, except that 0xD has code BT_S rather than BT_CR */
/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
-/* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML,
-/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
-/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
-/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
-/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
-/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
-/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
-/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
-/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
-/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
-/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
-/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
-/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
-/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
-/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
-/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
-/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
+ /* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+ /* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
+ /* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML,
+ /* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+ /* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+ /* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+ /* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+ /* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
+ /* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
+ /* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
+ /* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
+ /* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+ /* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+ /* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
+ /* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
+ /* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+ /* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+ /* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
+ /* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
+ /* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+ /* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+ /* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+ /* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#if defined(__GNUC__) && defined(__i386__) && !defined(__MINGW32__)
+#if defined(__GNUC__) && defined(__i386__) && ! defined(__MINGW32__)
/* We'll use this version by default only where we know it helps.
regparm() generates warnings on Solaris boxes. See SF bug #692878.
#define FASTCALL __attribute__((stdcall, regparm(3)))
and let's try this:
*/
-#define FASTCALL __attribute__((regparm(3)))
-#define PTRFASTCALL __attribute__((regparm(3)))
+# define FASTCALL __attribute__((regparm(3)))
+# define PTRFASTCALL __attribute__((regparm(3)))
#endif
/* Using __fastcall seems to have an unexpected negative effect under
/* Make sure all of these are defined if they aren't already. */
#ifndef FASTCALL
-#define FASTCALL
+# define FASTCALL
#endif
#ifndef PTRCALL
-#define PTRCALL
+# define PTRCALL
#endif
#ifndef PTRFASTCALL
-#define PTRFASTCALL
+# define PTRFASTCALL
#endif
#ifndef XML_MIN_SIZE
-#if !defined(__cplusplus) && !defined(inline)
-#ifdef __GNUC__
-#define inline __inline
-#endif /* __GNUC__ */
-#endif
+# if ! defined(__cplusplus) && ! defined(inline)
+# ifdef __GNUC__
+# define inline __inline
+# endif /* __GNUC__ */
+# endif
#endif /* XML_MIN_SIZE */
#ifdef __cplusplus
-#define inline inline
+# define inline inline
#else
-#ifndef inline
-#define inline
-#endif
+# ifndef inline
+# define inline
+# endif
#endif
#ifndef UNUSED_P
-# ifdef __GNUC__
-# define UNUSED_P(p) UNUSED_ ## p __attribute__((__unused__))
-# else
-# define UNUSED_P(p) UNUSED_ ## p
-# endif
+# define UNUSED_P(p) (void)p
#endif
-
#ifdef __cplusplus
extern "C" {
#endif
-
#ifdef XML_ENABLE_VISIBILITY
-#if XML_ENABLE_VISIBILITY
-__attribute__ ((visibility ("default")))
-#endif
+# if XML_ENABLE_VISIBILITY
+__attribute__((visibility("default")))
+# endif
#endif
void
-_INTERNAL_trim_to_complete_utf8_characters(const char * from, const char ** fromLimRef);
-
+_INTERNAL_trim_to_complete_utf8_characters(const char *from,
+ const char **fromLimRef);
#ifdef __cplusplus
}
*/
/* 0x80 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
-/* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME,
-/* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
-/* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
-/* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
-/* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
-/* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
-/* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+ /* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+ /* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+ /* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+ /* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+ /* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+ /* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+ /* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+ /* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+ /* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
+ /* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+ /* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+ /* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME,
+ /* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
+ /* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+ /* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+ /* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+ /* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+ /* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+++ /dev/null
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 2016 - 2017, Steve Holme, <steve_holme@hotmail.com>.
- * Copyright (C) 2017, Expat development team
- *
- * All rights reserved.
- * Licensed under the MIT license:
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
- * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
- * THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of a copyright holder shall
- * not be used in advertising or otherwise to promote the sale, use or other
- * dealings in this Software without prior written authorization of the
- * copyright holder.
- *
- ***************************************************************************/
-
-#if defined(_WIN32)
-
-#include <windows.h>
-#include <tchar.h>
-
-
-HMODULE _Expat_LoadLibrary(LPCTSTR filename);
-
-
-#if !defined(LOAD_WITH_ALTERED_SEARCH_PATH)
-#define LOAD_WITH_ALTERED_SEARCH_PATH 0x00000008
-#endif
-
-#if !defined(LOAD_LIBRARY_SEARCH_SYSTEM32)
-#define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
-#endif
-
-/* We use our own typedef here since some headers might lack these */
-typedef HMODULE (APIENTRY *LOADLIBRARYEX_FN)(LPCTSTR, HANDLE, DWORD);
-
-/* See function definitions in winbase.h */
-#ifdef UNICODE
-# ifdef _WIN32_WCE
-# define LOADLIBARYEX L"LoadLibraryExW"
-# else
-# define LOADLIBARYEX "LoadLibraryExW"
-# endif
-#else
-# define LOADLIBARYEX "LoadLibraryExA"
-#endif
-
-
-/*
- * _Expat_LoadLibrary()
- *
- * This is used to dynamically load DLLs using the most secure method available
- * for the version of Windows that we are running on.
- *
- * Parameters:
- *
- * filename [in] - The filename or full path of the DLL to load. If only the
- * filename is passed then the DLL will be loaded from the
- * Windows system directory.
- *
- * Returns the handle of the module on success; otherwise NULL.
- */
-HMODULE _Expat_LoadLibrary(LPCTSTR filename)
-{
- HMODULE hModule = NULL;
- LOADLIBRARYEX_FN pLoadLibraryEx = NULL;
-
- /* Get a handle to kernel32 so we can access it's functions at runtime */
- HMODULE hKernel32 = GetModuleHandle(TEXT("kernel32"));
- if(!hKernel32)
- return NULL; /* LCOV_EXCL_LINE */
-
- /* Attempt to find LoadLibraryEx() which is only available on Windows 2000
- and above */
- pLoadLibraryEx = (LOADLIBRARYEX_FN) GetProcAddress(hKernel32, LOADLIBARYEX);
-
- /* Detect if there's already a path in the filename and load the library if
- there is. Note: Both back slashes and forward slashes have been supported
- since the earlier days of DOS at an API level although they are not
- supported by command prompt */
- if(_tcspbrk(filename, TEXT("\\/"))) {
- /** !checksrc! disable BANNEDFUNC 1 **/
- hModule = pLoadLibraryEx ?
- pLoadLibraryEx(filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) :
- LoadLibrary(filename);
- }
- /* Detect if KB2533623 is installed, as LOAD_LIBARY_SEARCH_SYSTEM32 is only
- supported on Windows Vista, Windows Server 2008, Windows 7 and Windows
- Server 2008 R2 with this patch or natively on Windows 8 and above */
- else if(pLoadLibraryEx && GetProcAddress(hKernel32, "AddDllDirectory")) {
- /* Load the DLL from the Windows system directory */
- hModule = pLoadLibraryEx(filename, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
- }
- else {
- /* Attempt to get the Windows system path */
- UINT systemdirlen = GetSystemDirectory(NULL, 0);
- if(systemdirlen) {
- /* Allocate space for the full DLL path (Room for the null terminator
- is included in systemdirlen) */
- size_t filenamelen = _tcslen(filename);
- TCHAR *path = malloc(sizeof(TCHAR) * (systemdirlen + 1 + filenamelen));
- if(path && GetSystemDirectory(path, systemdirlen)) {
- /* Calculate the full DLL path */
- _tcscpy(path + _tcslen(path), TEXT("\\"));
- _tcscpy(path + _tcslen(path), filename);
-
- /* Load the DLL from the Windows system directory */
- /** !checksrc! disable BANNEDFUNC 1 **/
- hModule = pLoadLibraryEx ?
- pLoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) :
- LoadLibrary(path);
-
- }
- free(path);
- }
- }
-
- return hModule;
-}
-
-#else /* defined(_WIN32) */
-
-/* ISO C requires a translation unit to contain at least one declaration
- [-Wempty-translation-unit] */
-typedef int _TRANSLATION_UNIT_LOAD_LIBRARY_C_NOT_EMTPY;
-
-#endif /* defined(_WIN32) */
*/
static const unsigned namingBitmap[] = {
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
-0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
-0x00000000, 0x04000000, 0x87FFFFFE, 0x07FFFFFE,
-0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF,
-0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF,
-0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF,
-0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF,
-0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD,
-0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF,
-0xFFFF0003, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF,
-0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE,
-0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF,
-0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000,
-0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060,
-0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003,
-0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003,
-0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000,
-0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001,
-0xFFF99FE0, 0x23CDFDFF, 0xB0000000, 0x00000003,
-0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000,
-0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003,
-0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003,
-0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000,
-0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000,
-0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF,
-0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB,
-0x40000000, 0xF580C900, 0x00000007, 0x02010800,
-0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
-0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF,
-0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF,
-0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF,
-0x00000000, 0x00004C40, 0x00000000, 0x00000000,
-0x00000007, 0x00000000, 0x00000000, 0x00000000,
-0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF,
-0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF,
-0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
-0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000,
-0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
-0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000,
-0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE,
-0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF,
-0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF,
-0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000,
-0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003,
-0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD,
-0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF,
-0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF,
-0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE,
-0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF,
-0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF,
-0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF,
-0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF,
-0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF,
-0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0,
-0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1,
-0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3,
-0xD63DC7EC, 0xC3BFC718, 0x00803DC7, 0x0000FF80,
-0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3,
-0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3,
-0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000,
-0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000,
-0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF,
-0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x1FFF0000, 0x00000002,
-0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF,
-0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x04000000,
+ 0x87FFFFFE, 0x07FFFFFE, 0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF,
+ 0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFE00F, 0xFC31FFFF, 0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD,
+ 0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, 0xFFFF0003, 0xFFFFFFFF,
+ 0xFFFF199F, 0x033FCFFF, 0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE,
+ 0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF, 0x00000000, 0x07FFFFFE,
+ 0x000007FE, 0xFFFE0000, 0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060,
+ 0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003, 0xFFF99FE0, 0x03C5FDFF,
+ 0xB0000000, 0x00030003, 0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000,
+ 0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001, 0xFFF99FE0, 0x23CDFDFF,
+ 0xB0000000, 0x00000003, 0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000,
+ 0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003, 0xFFFDDFE0, 0x03EFFDFF,
+ 0x40000000, 0x00000003, 0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFE, 0x000D7FFF,
+ 0x0000003F, 0x00000000, 0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000,
+ 0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF, 0x0007DAED, 0x50000000,
+ 0x82315001, 0x002C62AB, 0x40000000, 0xF580C900, 0x00000007, 0x02010800,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0FFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0x03FFFFFF, 0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF,
+ 0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF, 0x00000000, 0x00004C40,
+ 0x00000000, 0x00000000, 0x00000007, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF, 0x001FFFFF, 0xFFFFFFFE,
+ 0xFFFFFFFF, 0x07FFFFFF, 0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000000F,
+ 0x00000000, 0x00000000, 0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE,
+ 0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF, 0x00FFFFFF, 0x00000000,
+ 0xFFFF0000, 0xFFFFFFFF, 0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003, 0xFFFFD7C0, 0xFFFFFFFB,
+ 0x547F7FFF, 0x000FFFFD, 0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF,
+ 0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, 0x00000000, 0xFFFE0000,
+ 0x027FFFFF, 0xFFFFFFFE, 0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF,
+ 0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF, 0xFFFFFFFF, 0x7CFFFFFF,
+ 0xFFEF7FFF, 0x03FF3DFF, 0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF,
+ 0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF, 0xFFF987E4, 0xD36DFDFF,
+ 0x5E003987, 0x001FFFC0, 0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1,
+ 0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3, 0xD63DC7EC, 0xC3BFC718,
+ 0x00803DC7, 0x0000FF80, 0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3,
+ 0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3, 0xFFFDDFEC, 0xC3FFFDFF,
+ 0x00803DCF, 0x0000FFC3, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000, 0xFEF02596, 0x3BFF6CAE,
+ 0x03FF3F5F, 0x00000000, 0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF,
+ 0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1FFF0000, 0x00000002,
+ 0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF, 0x661FFFFF, 0xFFFFFFFE,
+ 0xFFFFFFFF, 0x77FFFFFF,
};
static const unsigned char nmstrtPages[] = {
-0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00,
-0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13,
-0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, 0x00, 0x14, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
};
static const unsigned char namePages[] = {
-0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00,
-0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
-0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13,
-0x26, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00, 0x00, 0x1F, 0x20, 0x21,
+ 0x22, 0x23, 0x24, 0x25, 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, 0x26, 0x14, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
};
* --------------------------------------------------------------------------
* HISTORY:
*
+ * 2019-08-03 (Sebastian Pipping)
+ * - Mark part of sip24_valid as to be excluded from clang-format
+ * - Re-format code using clang-format 9
+ *
* 2018-07-08 (Anton Maklakov)
* - Add "fall through" markers for GCC's -Wimplicit-fallthrough
*
#include <stddef.h> /* size_t */
#if defined(_WIN32) && defined(_MSC_VER) && (_MSC_VER < 1600)
- /* For vs2003/7.1 up to vs2008/9.0; _MSC_VER 1600 is vs2010/10.0 */
- typedef unsigned __int8 uint8_t;
- typedef unsigned __int32 uint32_t;
- typedef unsigned __int64 uint64_t;
+/* For vs2003/7.1 up to vs2008/9.0; _MSC_VER 1600 is vs2010/10.0 */
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
#else
- #include <stdint.h> /* uint64_t uint32_t uint8_t */
+# include <stdint.h> /* uint64_t uint32_t uint8_t */
#endif
-
/*
* Workaround to not require a C++11 compiler for using ULL suffix
* if this code is included and compiled as C++; related GCC warning is:
* warning: use of C++11 long long integer constant [-Wlong-long]
*/
-#define _SIP_ULL(high, low) (((uint64_t)high << 32) | low)
-
-
-#define SIP_ROTL(x, b) (uint64_t)(((x) << (b)) | ( (x) >> (64 - (b))))
+#define _SIP_ULL(high, low) (((uint64_t)high << 32) | low)
-#define SIP_U32TO8_LE(p, v) \
- (p)[0] = (uint8_t)((v) >> 0); (p)[1] = (uint8_t)((v) >> 8); \
- (p)[2] = (uint8_t)((v) >> 16); (p)[3] = (uint8_t)((v) >> 24);
+#define SIP_ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
-#define SIP_U64TO8_LE(p, v) \
- SIP_U32TO8_LE((p) + 0, (uint32_t)((v) >> 0)); \
- SIP_U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
+#define SIP_U32TO8_LE(p, v) \
+ (p)[0] = (uint8_t)((v) >> 0); \
+ (p)[1] = (uint8_t)((v) >> 8); \
+ (p)[2] = (uint8_t)((v) >> 16); \
+ (p)[3] = (uint8_t)((v) >> 24);
-#define SIP_U8TO64_LE(p) \
- (((uint64_t)((p)[0]) << 0) | \
- ((uint64_t)((p)[1]) << 8) | \
- ((uint64_t)((p)[2]) << 16) | \
- ((uint64_t)((p)[3]) << 24) | \
- ((uint64_t)((p)[4]) << 32) | \
- ((uint64_t)((p)[5]) << 40) | \
- ((uint64_t)((p)[6]) << 48) | \
- ((uint64_t)((p)[7]) << 56))
+#define SIP_U64TO8_LE(p, v) \
+ SIP_U32TO8_LE((p) + 0, (uint32_t)((v) >> 0)); \
+ SIP_U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
+#define SIP_U8TO64_LE(p) \
+ (((uint64_t)((p)[0]) << 0) | ((uint64_t)((p)[1]) << 8) \
+ | ((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) \
+ | ((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) \
+ | ((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56))
-#define SIPHASH_INITIALIZER { 0, 0, 0, 0, { 0 }, 0, 0 }
+#define SIPHASH_INITIALIZER \
+ { 0, 0, 0, 0, {0}, 0, 0 }
struct siphash {
- uint64_t v0, v1, v2, v3;
+ uint64_t v0, v1, v2, v3;
- unsigned char buf[8], *p;
- uint64_t c;
+ unsigned char buf[8], *p;
+ uint64_t c;
}; /* struct siphash */
-
#define SIP_KEYLEN 16
struct sipkey {
- uint64_t k[2];
+ uint64_t k[2];
}; /* struct sipkey */
-#define sip_keyof(k) sip_tokey(&(struct sipkey){ { 0 } }, (k))
+#define sip_keyof(k) sip_tokey(&(struct sipkey){{0}}, (k))
-static struct sipkey *sip_tokey(struct sipkey *key, const void *src) {
- key->k[0] = SIP_U8TO64_LE((const unsigned char *)src);
- key->k[1] = SIP_U8TO64_LE((const unsigned char *)src + 8);
- return key;
+static struct sipkey *
+sip_tokey(struct sipkey *key, const void *src) {
+ key->k[0] = SIP_U8TO64_LE((const unsigned char *)src);
+ key->k[1] = SIP_U8TO64_LE((const unsigned char *)src + 8);
+ return key;
} /* sip_tokey() */
-
#ifdef SIPHASH_TOBIN
-#define sip_binof(v) sip_tobin((unsigned char[8]){ 0 }, (v))
+# define sip_binof(v) sip_tobin((unsigned char[8]){0}, (v))
-static void *sip_tobin(void *dst, uint64_t u64) {
- SIP_U64TO8_LE((unsigned char *)dst, u64);
- return dst;
+static void *
+sip_tobin(void *dst, uint64_t u64) {
+ SIP_U64TO8_LE((unsigned char *)dst, u64);
+ return dst;
} /* sip_tobin() */
-#endif /* SIPHASH_TOBIN */
-
+#endif /* SIPHASH_TOBIN */
-static void sip_round(struct siphash *H, const int rounds) {
- int i;
+static void
+sip_round(struct siphash *H, const int rounds) {
+ int i;
- for (i = 0; i < rounds; i++) {
- H->v0 += H->v1;
- H->v1 = SIP_ROTL(H->v1, 13);
- H->v1 ^= H->v0;
- H->v0 = SIP_ROTL(H->v0, 32);
+ for (i = 0; i < rounds; i++) {
+ H->v0 += H->v1;
+ H->v1 = SIP_ROTL(H->v1, 13);
+ H->v1 ^= H->v0;
+ H->v0 = SIP_ROTL(H->v0, 32);
- H->v2 += H->v3;
- H->v3 = SIP_ROTL(H->v3, 16);
- H->v3 ^= H->v2;
+ H->v2 += H->v3;
+ H->v3 = SIP_ROTL(H->v3, 16);
+ H->v3 ^= H->v2;
- H->v0 += H->v3;
- H->v3 = SIP_ROTL(H->v3, 21);
- H->v3 ^= H->v0;
+ H->v0 += H->v3;
+ H->v3 = SIP_ROTL(H->v3, 21);
+ H->v3 ^= H->v0;
- H->v2 += H->v1;
- H->v1 = SIP_ROTL(H->v1, 17);
- H->v1 ^= H->v2;
- H->v2 = SIP_ROTL(H->v2, 32);
- }
+ H->v2 += H->v1;
+ H->v1 = SIP_ROTL(H->v1, 17);
+ H->v1 ^= H->v2;
+ H->v2 = SIP_ROTL(H->v2, 32);
+ }
} /* sip_round() */
+static struct siphash *
+sip24_init(struct siphash *H, const struct sipkey *key) {
+ H->v0 = _SIP_ULL(0x736f6d65U, 0x70736575U) ^ key->k[0];
+ H->v1 = _SIP_ULL(0x646f7261U, 0x6e646f6dU) ^ key->k[1];
+ H->v2 = _SIP_ULL(0x6c796765U, 0x6e657261U) ^ key->k[0];
+ H->v3 = _SIP_ULL(0x74656462U, 0x79746573U) ^ key->k[1];
-static struct siphash *sip24_init(struct siphash *H,
- const struct sipkey *key) {
- H->v0 = _SIP_ULL(0x736f6d65U, 0x70736575U) ^ key->k[0];
- H->v1 = _SIP_ULL(0x646f7261U, 0x6e646f6dU) ^ key->k[1];
- H->v2 = _SIP_ULL(0x6c796765U, 0x6e657261U) ^ key->k[0];
- H->v3 = _SIP_ULL(0x74656462U, 0x79746573U) ^ key->k[1];
+ H->p = H->buf;
+ H->c = 0;
- H->p = H->buf;
- H->c = 0;
-
- return H;
+ return H;
} /* sip24_init() */
+#define sip_endof(a) (&(a)[sizeof(a) / sizeof *(a)])
-#define sip_endof(a) (&(a)[sizeof (a) / sizeof *(a)])
-
-static struct siphash *sip24_update(struct siphash *H, const void *src,
- size_t len) {
- const unsigned char *p = (const unsigned char *)src, *pe = p + len;
- uint64_t m;
+static struct siphash *
+sip24_update(struct siphash *H, const void *src, size_t len) {
+ const unsigned char *p = (const unsigned char *)src, *pe = p + len;
+ uint64_t m;
- do {
- while (p < pe && H->p < sip_endof(H->buf))
- *H->p++ = *p++;
+ do {
+ while (p < pe && H->p < sip_endof(H->buf))
+ *H->p++ = *p++;
- if (H->p < sip_endof(H->buf))
- break;
+ if (H->p < sip_endof(H->buf))
+ break;
- m = SIP_U8TO64_LE(H->buf);
- H->v3 ^= m;
- sip_round(H, 2);
- H->v0 ^= m;
+ m = SIP_U8TO64_LE(H->buf);
+ H->v3 ^= m;
+ sip_round(H, 2);
+ H->v0 ^= m;
- H->p = H->buf;
- H->c += 8;
- } while (p < pe);
+ H->p = H->buf;
+ H->c += 8;
+ } while (p < pe);
- return H;
+ return H;
} /* sip24_update() */
-
-static uint64_t sip24_final(struct siphash *H) {
- const char left = (char)(H->p - H->buf);
- uint64_t b = (H->c + left) << 56;
-
- switch (left) {
- case 7: b |= (uint64_t)H->buf[6] << 48;
- /* fall through */
- case 6: b |= (uint64_t)H->buf[5] << 40;
- /* fall through */
- case 5: b |= (uint64_t)H->buf[4] << 32;
- /* fall through */
- case 4: b |= (uint64_t)H->buf[3] << 24;
- /* fall through */
- case 3: b |= (uint64_t)H->buf[2] << 16;
- /* fall through */
- case 2: b |= (uint64_t)H->buf[1] << 8;
- /* fall through */
- case 1: b |= (uint64_t)H->buf[0] << 0;
- /* fall through */
- case 0: break;
- }
-
- H->v3 ^= b;
- sip_round(H, 2);
- H->v0 ^= b;
- H->v2 ^= 0xff;
- sip_round(H, 4);
-
- return H->v0 ^ H->v1 ^ H->v2 ^ H->v3;
+static uint64_t
+sip24_final(struct siphash *H) {
+ const char left = (char)(H->p - H->buf);
+ uint64_t b = (H->c + left) << 56;
+
+ switch (left) {
+ case 7:
+ b |= (uint64_t)H->buf[6] << 48;
+ /* fall through */
+ case 6:
+ b |= (uint64_t)H->buf[5] << 40;
+ /* fall through */
+ case 5:
+ b |= (uint64_t)H->buf[4] << 32;
+ /* fall through */
+ case 4:
+ b |= (uint64_t)H->buf[3] << 24;
+ /* fall through */
+ case 3:
+ b |= (uint64_t)H->buf[2] << 16;
+ /* fall through */
+ case 2:
+ b |= (uint64_t)H->buf[1] << 8;
+ /* fall through */
+ case 1:
+ b |= (uint64_t)H->buf[0] << 0;
+ /* fall through */
+ case 0:
+ break;
+ }
+
+ H->v3 ^= b;
+ sip_round(H, 2);
+ H->v0 ^= b;
+ H->v2 ^= 0xff;
+ sip_round(H, 4);
+
+ return H->v0 ^ H->v1 ^ H->v2 ^ H->v3;
} /* sip24_final() */
-
-static uint64_t siphash24(const void *src, size_t len,
- const struct sipkey *key) {
- struct siphash state = SIPHASH_INITIALIZER;
- return sip24_final(sip24_update(sip24_init(&state, key), src, len));
+static uint64_t
+siphash24(const void *src, size_t len, const struct sipkey *key) {
+ struct siphash state = SIPHASH_INITIALIZER;
+ return sip24_final(sip24_update(sip24_init(&state, key), src, len));
} /* siphash24() */
-
/*
* SipHash-2-4 output with
* k = 00 01 02 ...
* ...
* in = 00 01 02 ... 3e (63 bytes)
*/
-static int sip24_valid(void) {
- static const unsigned char vectors[64][8] = {
- { 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, },
- { 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, },
- { 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, },
- { 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, },
- { 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, },
- { 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, },
- { 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, },
- { 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, },
- { 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, },
- { 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, },
- { 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, },
- { 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, },
- { 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, },
- { 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, },
- { 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, },
- { 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, },
- { 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, },
- { 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, },
- { 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, },
- { 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, },
- { 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, },
- { 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, },
- { 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, },
- { 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, },
- { 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, },
- { 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, },
- { 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, },
- { 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, },
- { 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, },
- { 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, },
- { 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, },
- { 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, },
- { 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, },
- { 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, },
- { 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, },
- { 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, },
- { 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, },
- { 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, },
- { 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, },
- { 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, },
- { 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, },
- { 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, },
- { 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, },
- { 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, },
- { 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, },
- { 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, },
- { 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, },
- { 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, },
- { 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, },
- { 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, },
- { 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, },
- { 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, },
- { 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, },
- { 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, },
- { 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, },
- { 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, },
- { 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, },
- { 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, },
- { 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, },
- { 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, },
- { 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, },
- { 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, },
- { 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, },
- { 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, }
- };
- unsigned char in[64];
- struct sipkey k;
- size_t i;
-
- sip_tokey(&k, "\000\001\002\003\004\005\006\007\010\011"
- "\012\013\014\015\016\017");
-
- for (i = 0; i < sizeof in; ++i) {
- in[i] = (unsigned char)i;
-
- if (siphash24(in, i, &k) != SIP_U8TO64_LE(vectors[i]))
- return 0;
- }
-
- return 1;
+static int
+sip24_valid(void) {
+ /* clang-format off */
+ static const unsigned char vectors[64][8] = {
+ { 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, },
+ { 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, },
+ { 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, },
+ { 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, },
+ { 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, },
+ { 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, },
+ { 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, },
+ { 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, },
+ { 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, },
+ { 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, },
+ { 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, },
+ { 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, },
+ { 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, },
+ { 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, },
+ { 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, },
+ { 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, },
+ { 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, },
+ { 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, },
+ { 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, },
+ { 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, },
+ { 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, },
+ { 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, },
+ { 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, },
+ { 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, },
+ { 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, },
+ { 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, },
+ { 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, },
+ { 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, },
+ { 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, },
+ { 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, },
+ { 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, },
+ { 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, },
+ { 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, },
+ { 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, },
+ { 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, },
+ { 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, },
+ { 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, },
+ { 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, },
+ { 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, },
+ { 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, },
+ { 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, },
+ { 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, },
+ { 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, },
+ { 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, },
+ { 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, },
+ { 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, },
+ { 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, },
+ { 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, },
+ { 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, },
+ { 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, },
+ { 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, },
+ { 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, },
+ { 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, },
+ { 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, },
+ { 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, },
+ { 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, },
+ { 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, },
+ { 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, },
+ { 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, },
+ { 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, },
+ { 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, },
+ { 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, },
+ { 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, },
+ { 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, }
+ };
+ /* clang-format on */
+
+ unsigned char in[64];
+ struct sipkey k;
+ size_t i;
+
+ sip_tokey(&k, "\000\001\002\003\004\005\006\007\010\011"
+ "\012\013\014\015\016\017");
+
+ for (i = 0; i < sizeof in; ++i) {
+ in[i] = (unsigned char)i;
+
+ if (siphash24(in, i, &k) != SIP_U8TO64_LE(vectors[i]))
+ return 0;
+ }
+
+ return 1;
} /* sip24_valid() */
-
#ifdef SIPHASH_MAIN
-#include <stdio.h>
+# include <stdio.h>
-int main(void) {
- const int ok = sip24_valid();
+int
+main(void) {
+ const int ok = sip24_valid();
- if (ok)
- puts("OK");
- else
- puts("FAIL");
+ if (ok)
+ puts("OK");
+ else
+ puts("FAIL");
- return !ok;
+ return ! ok;
} /* main() */
#endif /* SIPHASH_MAIN */
-
#endif /* SIPHASH_H */
*/
/* 0x80 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0x84 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0x88 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0x8C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0x90 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0x94 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0x98 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0x9C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0xA0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0xA4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0xA8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0xAC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0xB0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0xB4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0xB8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0xBC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
-/* 0xC0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
-/* 0xC4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
-/* 0xC8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
-/* 0xCC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
-/* 0xD0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
-/* 0xD4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
-/* 0xD8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
-/* 0xDC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
-/* 0xE0 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
-/* 0xE4 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
-/* 0xE8 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
-/* 0xEC */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
-/* 0xF0 */ BT_LEAD4, BT_LEAD4, BT_LEAD4, BT_LEAD4,
-/* 0xF4 */ BT_LEAD4, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0xF8 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
-/* 0xFC */ BT_NONXML, BT_NONXML, BT_MALFORM, BT_MALFORM,
+ /* 0x84 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+ /* 0x88 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+ /* 0x8C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+ /* 0x90 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+ /* 0x94 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+ /* 0x98 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+ /* 0x9C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+ /* 0xA0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+ /* 0xA4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+ /* 0xA8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+ /* 0xAC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+ /* 0xB0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+ /* 0xB4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+ /* 0xB8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+ /* 0xBC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+ /* 0xC0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+ /* 0xC4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+ /* 0xC8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+ /* 0xCC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+ /* 0xD0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+ /* 0xD4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+ /* 0xD8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+ /* 0xDC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+ /* 0xE0 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+ /* 0xE4 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+ /* 0xE8 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+ /* 0xEC */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+ /* 0xF0 */ BT_LEAD4, BT_LEAD4, BT_LEAD4, BT_LEAD4,
+ /* 0xF4 */ BT_LEAD4, BT_NONXML, BT_NONXML, BT_NONXML,
+ /* 0xF8 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+ /* 0xFC */ BT_NONXML, BT_NONXML, BT_MALFORM, BT_MALFORM,
#include <memory.h>
#include <string.h>
+#if defined(HAVE_EXPAT_CONFIG_H) /* e.g. MinGW */
+# include <expat_config.h>
+#else /* !defined(HAVE_EXPAT_CONFIG_H) */
-#if defined(HAVE_EXPAT_CONFIG_H) /* e.g. MinGW */
-# include <expat_config.h>
-#else /* !defined(HAVE_EXPAT_CONFIG_H) */
-
-
-#define XML_NS 1
-#define XML_DTD 1
-#define XML_CONTEXT_BYTES 1024
+# define XML_NS 1
+# define XML_DTD 1
+# define XML_CONTEXT_BYTES 1024
/* we will assume all Windows platforms are little endian */
-#define BYTEORDER 1234
+# define BYTEORDER 1234
#endif /* !defined(HAVE_EXPAT_CONFIG_H) */
-
#endif /* ndef WINCONFIG_H */
-/* 69df5be70289a11fb834869ce4a91c23c1d9dd04baffcbd10e86742d149a080c (2.2.7+)
+/* f2d0ab6d1d4422a08cf1cf3bbdfba96b49dea42fb5ff4615e03a2a25c306e769 (2.2.8+)
__ __ _
___\ \/ /_ __ __ _| |_
/ _ \\ /| '_ \ / _` | __|
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#if !defined(_GNU_SOURCE)
-# define _GNU_SOURCE 1 /* syscall prototype */
+#if ! defined(_GNU_SOURCE)
+# define _GNU_SOURCE 1 /* syscall prototype */
+#endif
+
+#ifdef _WIN32
+/* force stdlib to define rand_s() */
+# define _CRT_RAND_S
#endif
#include <stddef.h>
-#include <string.h> /* memset(), memcpy() */
+#include <string.h> /* memset(), memcpy() */
#include <assert.h>
-#include <limits.h> /* UINT_MAX */
-#include <stdio.h> /* fprintf */
-#include <stdlib.h> /* getenv */
+#include <limits.h> /* UINT_MAX */
+#include <stdio.h> /* fprintf */
+#include <stdlib.h> /* getenv, rand_s */
#ifdef _WIN32
-#define getpid GetCurrentProcessId
+# define getpid GetCurrentProcessId
#else
-#include <sys/time.h> /* gettimeofday() */
-#include <sys/types.h> /* getpid() */
-#include <unistd.h> /* getpid() */
-#include <fcntl.h> /* O_RDONLY */
-#include <errno.h>
+# include <sys/time.h> /* gettimeofday() */
+# include <sys/types.h> /* getpid() */
+# include <unistd.h> /* getpid() */
+# include <fcntl.h> /* O_RDONLY */
+# include <errno.h>
#endif
#define XML_BUILDING_EXPAT 1
#ifdef _WIN32
-#include "winconfig.h"
+# include "winconfig.h"
#elif defined(HAVE_EXPAT_CONFIG_H)
-#include <expat_config.h>
+# include <expat_config.h>
#endif /* ndef _WIN32 */
#include "ascii.h"
#include "siphash.h"
#if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
-# if defined(HAVE_GETRANDOM)
-# include <sys/random.h> /* getrandom */
-# else
-# include <unistd.h> /* syscall */
-# include <sys/syscall.h> /* SYS_getrandom */
-# endif
-# if ! defined(GRND_NONBLOCK)
-# define GRND_NONBLOCK 0x0001
-# endif /* defined(GRND_NONBLOCK) */
-#endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
-
-#if defined(HAVE_LIBBSD) \
+# if defined(HAVE_GETRANDOM)
+# include <sys/random.h> /* getrandom */
+# else
+# include <unistd.h> /* syscall */
+# include <sys/syscall.h> /* SYS_getrandom */
+# endif
+# if ! defined(GRND_NONBLOCK)
+# define GRND_NONBLOCK 0x0001
+# endif /* defined(GRND_NONBLOCK) */
+#endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
+
+#if defined(HAVE_LIBBSD) \
&& (defined(HAVE_ARC4RANDOM_BUF) || defined(HAVE_ARC4RANDOM))
-# include <bsd/stdlib.h>
+# include <bsd/stdlib.h>
#endif
-#if defined(_WIN32) && !defined(LOAD_LIBRARY_SEARCH_SYSTEM32)
-# define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
+#if defined(_WIN32) && ! defined(LOAD_LIBRARY_SEARCH_SYSTEM32)
+# define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
#endif
-#if !defined(HAVE_GETRANDOM) && !defined(HAVE_SYSCALL_GETRANDOM) \
- && !defined(HAVE_ARC4RANDOM_BUF) && !defined(HAVE_ARC4RANDOM) \
- && !defined(XML_DEV_URANDOM) \
- && !defined(_WIN32) \
- && !defined(XML_POOR_ENTROPY)
-# error \
- You do not have support for any sources of high quality entropy \
+#if ! defined(HAVE_GETRANDOM) && ! defined(HAVE_SYSCALL_GETRANDOM) \
+ && ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) \
+ && ! defined(XML_DEV_URANDOM) && ! defined(_WIN32) \
+ && ! defined(XML_POOR_ENTROPY)
+# error You do not have support for any sources of high quality entropy \
enabled. For end user security, that is probably not what you want. \
\
Your options include: \
* libbsd (arc4random_buf): HAVE_ARC4RANDOM_BUF + HAVE_LIBBSD, \
* libbsd (arc4random): HAVE_ARC4RANDOM + HAVE_LIBBSD, \
* Linux / BSD / macOS (/dev/urandom): XML_DEV_URANDOM \
- * Windows (RtlGenRandom): _WIN32. \
+ * Windows (rand_s): _WIN32. \
\
If insist on not using any of these, bypass this error by defining \
XML_POOR_ENTROPY; you have been warned. \
to the build system, please open a bug. Thank you!
#endif
-
#ifdef XML_UNICODE
-#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
-#define XmlConvert XmlUtf16Convert
-#define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
-#define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
-#define XmlEncode XmlUtf16Encode
+# define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
+# define XmlConvert XmlUtf16Convert
+# define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
+# define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
+# define XmlEncode XmlUtf16Encode
/* Using pointer subtraction to convert to integer type. */
-#define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((char *)(s) - (char *)NULL) & 1))
+# define MUST_CONVERT(enc, s) \
+ (! (enc)->isUtf16 || (((char *)(s) - (char *)NULL) & 1))
typedef unsigned short ICHAR;
#else
-#define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
-#define XmlConvert XmlUtf8Convert
-#define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
-#define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
-#define XmlEncode XmlUtf8Encode
-#define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
+# define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
+# define XmlConvert XmlUtf8Convert
+# define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
+# define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
+# define XmlEncode XmlUtf8Encode
+# define MUST_CONVERT(enc, s) (! (enc)->isUtf8)
typedef char ICHAR;
#endif
-
#ifndef XML_NS
-#define XmlInitEncodingNS XmlInitEncoding
-#define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
-#undef XmlGetInternalEncodingNS
-#define XmlGetInternalEncodingNS XmlGetInternalEncoding
-#define XmlParseXmlDeclNS XmlParseXmlDecl
+# define XmlInitEncodingNS XmlInitEncoding
+# define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
+# undef XmlGetInternalEncodingNS
+# define XmlGetInternalEncodingNS XmlGetInternalEncoding
+# define XmlParseXmlDeclNS XmlParseXmlDecl
#endif
#ifdef XML_UNICODE
-#ifdef XML_UNICODE_WCHAR_T
-#define XML_T(x) (const wchar_t)x
-#define XML_L(x) L ## x
-#else
-#define XML_T(x) (const unsigned short)x
-#define XML_L(x) x
-#endif
+# ifdef XML_UNICODE_WCHAR_T
+# define XML_T(x) (const wchar_t) x
+# define XML_L(x) L##x
+# else
+# define XML_T(x) (const unsigned short)x
+# define XML_L(x) x
+# endif
#else
-#define XML_T(x) x
-#define XML_L(x) x
+# define XML_T(x) x
+# define XML_L(x) x
#endif
/* Round up n to be a multiple of sz, where sz is a power of 2. */
-#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
+#define ROUND_UP(n, sz) (((n) + ((sz)-1)) & ~((sz)-1))
/* Do safe (NULL-aware) pointer arithmetic */
#define EXPAT_SAFE_PTR_DIFF(p, q) (((p) && (q)) ? ((p) - (q)) : 0)
const XML_Memory_Handling_Suite *mem;
} HASH_TABLE;
-static size_t
-keylen(KEY s);
+static size_t keylen(KEY s);
-static void
-copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key);
+static void copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key);
/* For probing (after a collision) we need a step size relative prime
to the hash table size, which is a power of 2. We use double-hashing,
We limit the maximum step size to table->size / 4 (mask >> 2) and make
it odd, since odd numbers are always relative prime to a power of 2.
*/
-#define SECOND_HASH(hash, mask, power) \
- ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2))
-#define PROBE_STEP(hash, mask, power) \
+#define SECOND_HASH(hash, mask, power) \
+ ((((hash) & ~(mask)) >> ((power)-1)) & ((mask) >> 2))
+#define PROBE_STEP(hash, mask, power) \
((unsigned char)((SECOND_HASH(hash, mask, power)) | 1))
typedef struct {
NAMED **end;
} HASH_TABLE_ITER;
-#define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
+#define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
#define INIT_DATA_BUF_SIZE 1024
#define INIT_ATTS_SIZE 16
#define INIT_ATTS_VERSION 0xFFFFFFFF
TAG objects in a free list.
*/
typedef struct tag {
- struct tag *parent; /* parent of this element */
- const char *rawName; /* tagName in the original encoding */
+ struct tag *parent; /* parent of this element */
+ const char *rawName; /* tagName in the original encoding */
int rawNameLength;
- TAG_NAME name; /* tagName in the API encoding */
- char *buf; /* buffer for name components */
- char *bufEnd; /* end of the buffer */
+ TAG_NAME name; /* tagName in the API encoding */
+ char *buf; /* buffer for name components */
+ char *bufEnd; /* end of the buffer */
BINDING *bindings;
} TAG;
typedef struct {
const XML_Char *name;
const XML_Char *textPtr;
- int textLen; /* length in XML_Chars */
- int processed; /* # of processed bytes - when suspended */
+ int textLen; /* length in XML_Chars */
+ int processed; /* # of processed bytes - when suspended */
const XML_Char *systemId;
const XML_Char *base;
const XML_Char *publicId;
} ENTITY;
typedef struct {
- enum XML_Content_Type type;
- enum XML_Content_Quant quant;
- const XML_Char * name;
- int firstchild;
- int lastchild;
- int childcnt;
- int nextsib;
+ enum XML_Content_Type type;
+ enum XML_Content_Quant quant;
+ const XML_Char *name;
+ int firstchild;
+ int lastchild;
+ int childcnt;
+ int nextsib;
} CONTENT_SCAFFOLD;
#define INIT_SCAFFOLD_ELEMENTS 32
XML_Bool betweenDecl; /* WFC: PE Between Declarations */
} OPEN_INTERNAL_ENTITY;
-typedef enum XML_Error PTRCALL Processor(XML_Parser parser,
- const char *start,
- const char *end,
- const char **endPtr);
+typedef enum XML_Error PTRCALL Processor(XML_Parser parser, const char *start,
+ const char *end, const char **endPtr);
static Processor prologProcessor;
static Processor prologInitProcessor;
static Processor externalEntityContentProcessor;
static Processor internalEntityProcessor;
-static enum XML_Error
-handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
-static enum XML_Error
-processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
- const char *s, const char *next);
-static enum XML_Error
-initializeEncoding(XML_Parser parser);
-static enum XML_Error
-doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
- const char *end, int tok, const char *next, const char **nextPtr,
- XML_Bool haveMore);
-static enum XML_Error
-processInternalEntity(XML_Parser parser, ENTITY *entity,
- XML_Bool betweenDecl);
-static enum XML_Error
-doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
- const char *start, const char *end, const char **endPtr,
- XML_Bool haveMore);
-static enum XML_Error
-doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr,
- const char *end, const char **nextPtr, XML_Bool haveMore);
+static enum XML_Error handleUnknownEncoding(XML_Parser parser,
+ const XML_Char *encodingName);
+static enum XML_Error processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
+ const char *s, const char *next);
+static enum XML_Error initializeEncoding(XML_Parser parser);
+static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc,
+ const char *s, const char *end, int tok,
+ const char *next, const char **nextPtr,
+ XML_Bool haveMore, XML_Bool allowClosingDoctype);
+static enum XML_Error processInternalEntity(XML_Parser parser, ENTITY *entity,
+ XML_Bool betweenDecl);
+static enum XML_Error doContent(XML_Parser parser, int startTagLevel,
+ const ENCODING *enc, const char *start,
+ const char *end, const char **endPtr,
+ XML_Bool haveMore);
+static enum XML_Error doCdataSection(XML_Parser parser, const ENCODING *,
+ const char **startPtr, const char *end,
+ const char **nextPtr, XML_Bool haveMore);
#ifdef XML_DTD
-static enum XML_Error
-doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr,
- const char *end, const char **nextPtr, XML_Bool haveMore);
+static enum XML_Error doIgnoreSection(XML_Parser parser, const ENCODING *,
+ const char **startPtr, const char *end,
+ const char **nextPtr, XML_Bool haveMore);
#endif /* XML_DTD */
-static void
-freeBindings(XML_Parser parser, BINDING *bindings);
-static enum XML_Error
-storeAtts(XML_Parser parser, const ENCODING *, const char *s,
- TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
-static enum XML_Error
-addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
- const XML_Char *uri, BINDING **bindingsPtr);
-static int
-defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
- XML_Bool isId, const XML_Char *dfltValue, XML_Parser parser);
-static enum XML_Error
-storeAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
- const char *, const char *, STRING_POOL *);
-static enum XML_Error
-appendAttributeValue(XML_Parser parser, const ENCODING *, XML_Bool isCdata,
- const char *, const char *, STRING_POOL *);
-static ATTRIBUTE_ID *
-getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
- const char *end);
-static int
-setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
-static enum XML_Error
-storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start,
- const char *end);
-static int
-reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
- const char *start, const char *end);
-static int
-reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
- const char *end);
-static void
-reportDefault(XML_Parser parser, const ENCODING *enc, const char *start,
- const char *end);
-
-static const XML_Char * getContext(XML_Parser parser);
-static XML_Bool
-setContext(XML_Parser parser, const XML_Char *context);
+static void freeBindings(XML_Parser parser, BINDING *bindings);
+static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *,
+ const char *s, TAG_NAME *tagNamePtr,
+ BINDING **bindingsPtr);
+static enum XML_Error addBinding(XML_Parser parser, PREFIX *prefix,
+ const ATTRIBUTE_ID *attId, const XML_Char *uri,
+ BINDING **bindingsPtr);
+static int defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
+ XML_Bool isId, const XML_Char *dfltValue,
+ XML_Parser parser);
+static enum XML_Error storeAttributeValue(XML_Parser parser, const ENCODING *,
+ XML_Bool isCdata, const char *,
+ const char *, STRING_POOL *);
+static enum XML_Error appendAttributeValue(XML_Parser parser, const ENCODING *,
+ XML_Bool isCdata, const char *,
+ const char *, STRING_POOL *);
+static ATTRIBUTE_ID *getAttributeId(XML_Parser parser, const ENCODING *enc,
+ const char *start, const char *end);
+static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
+static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc,
+ const char *start, const char *end);
+static int reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
+ const char *start, const char *end);
+static int reportComment(XML_Parser parser, const ENCODING *enc,
+ const char *start, const char *end);
+static void reportDefault(XML_Parser parser, const ENCODING *enc,
+ const char *start, const char *end);
+
+static const XML_Char *getContext(XML_Parser parser);
+static XML_Bool setContext(XML_Parser parser, const XML_Char *context);
static void FASTCALL normalizePublicId(XML_Char *s);
-static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms);
+static DTD *dtdCreate(const XML_Memory_Handling_Suite *ms);
/* do not call if m_parentParser != NULL */
static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms);
-static void
-dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms);
-static int
-dtdCopy(XML_Parser oldParser,
- DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms);
-static int
-copyEntityTable(XML_Parser oldParser,
- HASH_TABLE *, STRING_POOL *, const HASH_TABLE *);
-static NAMED *
-lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize);
-static void FASTCALL
-hashTableInit(HASH_TABLE *, const XML_Memory_Handling_Suite *ms);
+static void dtdDestroy(DTD *p, XML_Bool isDocEntity,
+ const XML_Memory_Handling_Suite *ms);
+static int dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
+ const XML_Memory_Handling_Suite *ms);
+static int copyEntityTable(XML_Parser oldParser, HASH_TABLE *, STRING_POOL *,
+ const HASH_TABLE *);
+static NAMED *lookup(XML_Parser parser, HASH_TABLE *table, KEY name,
+ size_t createSize);
+static void FASTCALL hashTableInit(HASH_TABLE *,
+ const XML_Memory_Handling_Suite *ms);
static void FASTCALL hashTableClear(HASH_TABLE *);
static void FASTCALL hashTableDestroy(HASH_TABLE *);
-static void FASTCALL
-hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
-static NAMED * FASTCALL hashTableIterNext(HASH_TABLE_ITER *);
+static void FASTCALL hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
+static NAMED *FASTCALL hashTableIterNext(HASH_TABLE_ITER *);
-static void FASTCALL
-poolInit(STRING_POOL *, const XML_Memory_Handling_Suite *ms);
+static void FASTCALL poolInit(STRING_POOL *,
+ const XML_Memory_Handling_Suite *ms);
static void FASTCALL poolClear(STRING_POOL *);
static void FASTCALL poolDestroy(STRING_POOL *);
-static XML_Char *
-poolAppend(STRING_POOL *pool, const ENCODING *enc,
- const char *ptr, const char *end);
-static XML_Char *
-poolStoreString(STRING_POOL *pool, const ENCODING *enc,
- const char *ptr, const char *end);
+static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end);
+static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end);
static XML_Bool FASTCALL poolGrow(STRING_POOL *pool);
-static const XML_Char * FASTCALL
-poolCopyString(STRING_POOL *pool, const XML_Char *s);
-static const XML_Char *
-poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
-static const XML_Char * FASTCALL
-poolAppendString(STRING_POOL *pool, const XML_Char *s);
+static const XML_Char *FASTCALL poolCopyString(STRING_POOL *pool,
+ const XML_Char *s);
+static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s,
+ int n);
+static const XML_Char *FASTCALL poolAppendString(STRING_POOL *pool,
+ const XML_Char *s);
static int FASTCALL nextScaffoldPart(XML_Parser parser);
-static XML_Content * build_model(XML_Parser parser);
-static ELEMENT_TYPE *
-getElementType(XML_Parser parser, const ENCODING *enc,
- const char *ptr, const char *end);
+static XML_Content *build_model(XML_Parser parser);
+static ELEMENT_TYPE *getElementType(XML_Parser parser, const ENCODING *enc,
+ const char *ptr, const char *end);
static XML_Char *copyString(const XML_Char *s,
const XML_Memory_Handling_Suite *memsuite);
static unsigned long generate_hash_secret_salt(XML_Parser parser);
static XML_Bool startParsing(XML_Parser parser);
-static XML_Parser
-parserCreate(const XML_Char *encodingName,
- const XML_Memory_Handling_Suite *memsuite,
- const XML_Char *nameSep,
- DTD *dtd);
+static XML_Parser parserCreate(const XML_Char *encodingName,
+ const XML_Memory_Handling_Suite *memsuite,
+ const XML_Char *nameSep, DTD *dtd);
-static void
-parserInit(XML_Parser parser, const XML_Char *encodingName);
+static void parserInit(XML_Parser parser, const XML_Char *encodingName);
#define poolStart(pool) ((pool)->start)
#define poolEnd(pool) ((pool)->ptr)
#define poolLastChar(pool) (((pool)->ptr)[-1])
#define poolDiscard(pool) ((pool)->ptr = (pool)->start)
#define poolFinish(pool) ((pool)->start = (pool)->ptr)
-#define poolAppendChar(pool, c) \
- (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
- ? 0 \
- : ((*((pool)->ptr)++ = c), 1))
+#define poolAppendChar(pool, c) \
+ (((pool)->ptr == (pool)->end && ! poolGrow(pool)) \
+ ? 0 \
+ : ((*((pool)->ptr)++ = c), 1))
struct XML_ParserStruct {
/* The first member must be m_userData so that the XML_GetUserData
void *m_unknownEncodingMem;
void *m_unknownEncodingData;
void *m_unknownEncodingHandlerData;
- void (XMLCALL *m_unknownEncodingRelease)(void *);
+ void(XMLCALL *m_unknownEncodingRelease)(void *);
PROLOG_STATE m_prologState;
Processor *m_processor;
enum XML_Error m_errorCode;
unsigned long m_hash_secret_salt;
};
-#define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s)))
-#define REALLOC(parser, p, s) (parser->m_mem.realloc_fcn((p),(s)))
-#define FREE(parser, p) (parser->m_mem.free_fcn((p)))
-
+#define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s)))
+#define REALLOC(parser, p, s) (parser->m_mem.realloc_fcn((p), (s)))
+#define FREE(parser, p) (parser->m_mem.free_fcn((p)))
XML_Parser XMLCALL
-XML_ParserCreate(const XML_Char *encodingName)
-{
+XML_ParserCreate(const XML_Char *encodingName) {
return XML_ParserCreate_MM(encodingName, NULL, NULL);
}
XML_Parser XMLCALL
-XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
-{
+XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) {
XML_Char tmp[2];
*tmp = nsSep;
return XML_ParserCreate_MM(encodingName, NULL, tmp);
}
-static const XML_Char implicitContext[] = {
- ASCII_x, ASCII_m, ASCII_l, ASCII_EQUALS, ASCII_h, ASCII_t, ASCII_t, ASCII_p,
- ASCII_COLON, ASCII_SLASH, ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w,
- ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g,
- ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L, ASCII_SLASH, ASCII_1, ASCII_9,
- ASCII_9, ASCII_8, ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m, ASCII_e,
- ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0'
-};
-
+static const XML_Char implicitContext[]
+ = {ASCII_x, ASCII_m, ASCII_l, ASCII_EQUALS, ASCII_h,
+ ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH,
+ ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD,
+ ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r,
+ ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L,
+ ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9, ASCII_8,
+ ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m, ASCII_e,
+ ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e,
+ '\0'};
/* To avoid warnings about unused functions: */
#if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM)
-#if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
+# if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
/* Obtain entropy on Linux 3.17+ */
static int
-writeRandomBytes_getrandom_nonblock(void * target, size_t count) {
- int success = 0; /* full count bytes written? */
+writeRandomBytes_getrandom_nonblock(void *target, size_t count) {
+ int success = 0; /* full count bytes written? */
size_t bytesWrittenTotal = 0;
const unsigned int getrandomFlags = GRND_NONBLOCK;
do {
- void * const currentTarget = (void*)((char*)target + bytesWrittenTotal);
+ void *const currentTarget = (void *)((char *)target + bytesWrittenTotal);
const size_t bytesToWrite = count - bytesWrittenTotal;
const int bytesWrittenMore =
-#if defined(HAVE_GETRANDOM)
+# if defined(HAVE_GETRANDOM)
getrandom(currentTarget, bytesToWrite, getrandomFlags);
-#else
+# else
syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags);
-#endif
+# endif
if (bytesWrittenMore > 0) {
bytesWrittenTotal += bytesWrittenMore;
return success;
}
-#endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
-
+# endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
-#if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
+# if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
/* Extract entropy from /dev/urandom */
static int
-writeRandomBytes_dev_urandom(void * target, size_t count) {
- int success = 0; /* full count bytes written? */
+writeRandomBytes_dev_urandom(void *target, size_t count) {
+ int success = 0; /* full count bytes written? */
size_t bytesWrittenTotal = 0;
const int fd = open("/dev/urandom", O_RDONLY);
}
do {
- void * const currentTarget = (void*)((char*)target + bytesWrittenTotal);
+ void *const currentTarget = (void *)((char *)target + bytesWrittenTotal);
const size_t bytesToWrite = count - bytesWrittenTotal;
const ssize_t bytesWrittenMore = read(fd, currentTarget, bytesToWrite);
return success;
}
-#endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
-
-#endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
+# endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
+#endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
#if defined(HAVE_ARC4RANDOM) && ! defined(HAVE_ARC4RANDOM_BUF)
static void
-writeRandomBytes_arc4random(void * target, size_t count) {
+writeRandomBytes_arc4random(void *target, size_t count) {
size_t bytesWrittenTotal = 0;
while (bytesWrittenTotal < count) {
size_t i = 0;
for (; (i < sizeof(random32)) && (bytesWrittenTotal < count);
- i++, bytesWrittenTotal++) {
+ i++, bytesWrittenTotal++) {
const uint8_t random8 = (uint8_t)(random32 >> (i * 8));
((uint8_t *)target)[bytesWrittenTotal] = random8;
}
}
}
-#endif /* defined(HAVE_ARC4RANDOM) && ! defined(HAVE_ARC4RANDOM_BUF) */
-
+#endif /* defined(HAVE_ARC4RANDOM) && ! defined(HAVE_ARC4RANDOM_BUF) */
#ifdef _WIN32
-typedef BOOLEAN (APIENTRY *RTLGENRANDOM_FUNC)(PVOID, ULONG);
-HMODULE _Expat_LoadLibrary(LPCTSTR filename); /* see loadlibrary.c */
-
-/* Obtain entropy on Windows XP / Windows Server 2003 and later.
- * Hint on RtlGenRandom and the following article from libsodium.
- *
- * Michael Howard: Cryptographically Secure Random number on Windows without using CryptoAPI
- * https://blogs.msdn.microsoft.com/michael_howard/2005/01/14/cryptographically-secure-random-number-on-windows-without-using-cryptoapi/
+/* Obtain entropy on Windows using the rand_s() function which
+ * generates cryptographically secure random numbers. Internally it
+ * uses RtlGenRandom API which is present in Windows XP and later.
*/
static int
-writeRandomBytes_RtlGenRandom(void * target, size_t count) {
- int success = 0; /* full count bytes written? */
- const HMODULE advapi32 = _Expat_LoadLibrary(TEXT("ADVAPI32.DLL"));
-
- if (advapi32) {
- const RTLGENRANDOM_FUNC RtlGenRandom
- = (RTLGENRANDOM_FUNC)GetProcAddress(advapi32, "SystemFunction036");
- if (RtlGenRandom) {
- if (RtlGenRandom((PVOID)target, (ULONG)count) == TRUE) {
- success = 1;
- }
+writeRandomBytes_rand_s(void *target, size_t count) {
+ size_t bytesWrittenTotal = 0;
+
+ while (bytesWrittenTotal < count) {
+ unsigned int random32 = 0;
+ size_t i = 0;
+
+ if (rand_s(&random32))
+ return 0; /* failure */
+
+ for (; (i < sizeof(random32)) && (bytesWrittenTotal < count);
+ i++, bytesWrittenTotal++) {
+ const uint8_t random8 = (uint8_t)(random32 >> (i * 8));
+ ((uint8_t *)target)[bytesWrittenTotal] = random8;
}
- FreeLibrary(advapi32);
}
-
- return success;
+ return 1; /* success */
}
#endif /* _WIN32 */
-
#if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM)
static unsigned long
-gather_time_entropy(void)
-{
-#ifdef _WIN32
+gather_time_entropy(void) {
+# ifdef _WIN32
FILETIME ft;
GetSystemTimeAsFileTime(&ft); /* never fails */
return ft.dwHighDateTime ^ ft.dwLowDateTime;
-#else
+# else
struct timeval tv;
int gettimeofday_res;
gettimeofday_res = gettimeofday(&tv, NULL);
-#if defined(NDEBUG)
+# if defined(NDEBUG)
(void)gettimeofday_res;
-#else
- assert (gettimeofday_res == 0);
-#endif /* defined(NDEBUG) */
+# else
+ assert(gettimeofday_res == 0);
+# endif /* defined(NDEBUG) */
/* Microseconds time is <20 bits entropy */
return tv.tv_usec;
-#endif
+# endif
}
-#endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
-
+#endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
static unsigned long
-ENTROPY_DEBUG(const char * label, unsigned long entropy) {
- const char * const EXPAT_ENTROPY_DEBUG = getenv("EXPAT_ENTROPY_DEBUG");
+ENTROPY_DEBUG(const char *label, unsigned long entropy) {
+ const char *const EXPAT_ENTROPY_DEBUG = getenv("EXPAT_ENTROPY_DEBUG");
if (EXPAT_ENTROPY_DEBUG && ! strcmp(EXPAT_ENTROPY_DEBUG, "1")) {
- fprintf(stderr, "Entropy: %s --> 0x%0*lx (%lu bytes)\n",
- label,
- (int)sizeof(entropy) * 2, entropy,
- (unsigned long)sizeof(entropy));
+ fprintf(stderr, "Entropy: %s --> 0x%0*lx (%lu bytes)\n", label,
+ (int)sizeof(entropy) * 2, entropy, (unsigned long)sizeof(entropy));
}
return entropy;
}
static unsigned long
-generate_hash_secret_salt(XML_Parser parser)
-{
+generate_hash_secret_salt(XML_Parser parser) {
unsigned long entropy;
(void)parser;
return ENTROPY_DEBUG("arc4random", entropy);
#else
/* Try high quality providers first .. */
-#ifdef _WIN32
- if (writeRandomBytes_RtlGenRandom((void *)&entropy, sizeof(entropy))) {
- return ENTROPY_DEBUG("RtlGenRandom", entropy);
+# ifdef _WIN32
+ if (writeRandomBytes_rand_s((void *)&entropy, sizeof(entropy))) {
+ return ENTROPY_DEBUG("rand_s", entropy);
}
-#elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
+# elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
if (writeRandomBytes_getrandom_nonblock((void *)&entropy, sizeof(entropy))) {
return ENTROPY_DEBUG("getrandom", entropy);
}
-#endif
-#if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
+# endif
+# if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
if (writeRandomBytes_dev_urandom((void *)&entropy, sizeof(entropy))) {
return ENTROPY_DEBUG("/dev/urandom", entropy);
}
-#endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
+# endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
/* .. and self-made low quality for backup: */
/* Process ID is 0 bits entropy if attacker has local access */
return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647);
} else {
return ENTROPY_DEBUG("fallback(8)",
- entropy * (unsigned long)2305843009213693951ULL);
+ entropy * (unsigned long)2305843009213693951ULL);
}
#endif
}
return parser->m_hash_secret_salt;
}
-static XML_Bool /* only valid for root parser */
-startParsing(XML_Parser parser)
-{
- /* hash functions must be initialized before setContext() is called */
- if (parser->m_hash_secret_salt == 0)
- parser->m_hash_secret_salt = generate_hash_secret_salt(parser);
- if (parser->m_ns) {
- /* implicit context only set for root parser, since child
- parsers (i.e. external entity parsers) will inherit it
- */
- return setContext(parser, implicitContext);
- }
- return XML_TRUE;
+static XML_Bool /* only valid for root parser */
+startParsing(XML_Parser parser) {
+ /* hash functions must be initialized before setContext() is called */
+ if (parser->m_hash_secret_salt == 0)
+ parser->m_hash_secret_salt = generate_hash_secret_salt(parser);
+ if (parser->m_ns) {
+ /* implicit context only set for root parser, since child
+ parsers (i.e. external entity parsers) will inherit it
+ */
+ return setContext(parser, implicitContext);
+ }
+ return XML_TRUE;
}
XML_Parser XMLCALL
XML_ParserCreate_MM(const XML_Char *encodingName,
const XML_Memory_Handling_Suite *memsuite,
- const XML_Char *nameSep)
-{
+ const XML_Char *nameSep) {
return parserCreate(encodingName, memsuite, nameSep, NULL);
}
static XML_Parser
parserCreate(const XML_Char *encodingName,
- const XML_Memory_Handling_Suite *memsuite,
- const XML_Char *nameSep,
- DTD *dtd)
-{
+ const XML_Memory_Handling_Suite *memsuite, const XML_Char *nameSep,
+ DTD *dtd) {
XML_Parser parser;
if (memsuite) {
XML_Memory_Handling_Suite *mtemp;
- parser = (XML_Parser)
- memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
+ parser = (XML_Parser)memsuite->malloc_fcn(sizeof(struct XML_ParserStruct));
if (parser != NULL) {
mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem);
mtemp->malloc_fcn = memsuite->malloc_fcn;
mtemp->realloc_fcn = memsuite->realloc_fcn;
mtemp->free_fcn = memsuite->free_fcn;
}
- }
- else {
+ } else {
XML_Memory_Handling_Suite *mtemp;
parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct));
if (parser != NULL) {
}
}
- if (!parser)
+ if (! parser)
return parser;
parser->m_buffer = NULL;
parser->m_bufferLim = NULL;
parser->m_attsSize = INIT_ATTS_SIZE;
- parser->m_atts = (ATTRIBUTE *)MALLOC(parser, parser->m_attsSize * sizeof(ATTRIBUTE));
+ parser->m_atts
+ = (ATTRIBUTE *)MALLOC(parser, parser->m_attsSize * sizeof(ATTRIBUTE));
if (parser->m_atts == NULL) {
FREE(parser, parser);
return NULL;
}
#ifdef XML_ATTR_INFO
- parser->m_attInfo = (XML_AttrInfo*)MALLOC(parser, parser->m_attsSize * sizeof(XML_AttrInfo));
+ parser->m_attInfo = (XML_AttrInfo *)MALLOC(
+ parser, parser->m_attsSize * sizeof(XML_AttrInfo));
if (parser->m_attInfo == NULL) {
FREE(parser, parser->m_atts);
FREE(parser, parser);
return NULL;
}
#endif
- parser->m_dataBuf = (XML_Char *)MALLOC(parser, INIT_DATA_BUF_SIZE * sizeof(XML_Char));
+ parser->m_dataBuf
+ = (XML_Char *)MALLOC(parser, INIT_DATA_BUF_SIZE * sizeof(XML_Char));
if (parser->m_dataBuf == NULL) {
FREE(parser, parser->m_atts);
#ifdef XML_ATTR_INFO
poolInit(&parser->m_temp2Pool, &(parser->m_mem));
parserInit(parser, encodingName);
- if (encodingName && !parser->m_protocolEncodingName) {
+ if (encodingName && ! parser->m_protocolEncodingName) {
XML_ParserFree(parser);
return NULL;
}
parser->m_ns = XML_TRUE;
parser->m_internalEncoding = XmlGetInternalEncodingNS();
parser->m_namespaceSeparator = *nameSep;
- }
- else {
+ } else {
parser->m_internalEncoding = XmlGetInternalEncoding();
}
}
static void
-parserInit(XML_Parser parser, const XML_Char *encodingName)
-{
+parserInit(XML_Parser parser, const XML_Char *encodingName) {
parser->m_processor = prologInitProcessor;
XmlPrologStateInit(&parser->m_prologState);
if (encodingName != NULL) {
/* moves list of bindings to m_freeBindingList */
static void FASTCALL
-moveToFreeBindingList(XML_Parser parser, BINDING *bindings)
-{
+moveToFreeBindingList(XML_Parser parser, BINDING *bindings) {
while (bindings) {
BINDING *b = bindings;
bindings = bindings->nextTagBinding;
}
XML_Bool XMLCALL
-XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
-{
+XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) {
TAG *tStk;
OPEN_INTERNAL_ENTITY *openEntityList;
if (parser == NULL)
- return XML_FALSE;
+ return XML_FALSE;
if (parser->m_parentParser)
return XML_FALSE;
}
enum XML_Status XMLCALL
-XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
-{
+XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) {
if (parser == NULL)
- return XML_STATUS_ERROR;
+ return XML_STATUS_ERROR;
/* Block after XML_Parse()/XML_ParseBuffer() has been called.
XXX There's no way for the caller to determine which of the
XXX possible error cases caused the XML_STATUS_ERROR return.
*/
- if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED)
+ if (parser->m_parsingStatus.parsing == XML_PARSING
+ || parser->m_parsingStatus.parsing == XML_SUSPENDED)
return XML_STATUS_ERROR;
/* Get rid of any previous encoding name */
else {
/* Copy the new encoding name into allocated memory */
parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem));
- if (!parser->m_protocolEncodingName)
+ if (! parser->m_protocolEncodingName)
return XML_STATUS_ERROR;
}
return XML_STATUS_OK;
}
XML_Parser XMLCALL
-XML_ExternalEntityParserCreate(XML_Parser oldParser,
- const XML_Char *context,
- const XML_Char *encodingName)
-{
+XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
+ const XML_Char *encodingName) {
XML_Parser parser = oldParser;
DTD *newDtd = NULL;
DTD *oldDtd;
XML_AttlistDeclHandler oldAttlistDeclHandler;
XML_EntityDeclHandler oldEntityDeclHandler;
XML_XmlDeclHandler oldXmlDeclHandler;
- ELEMENT_TYPE * oldDeclElementType;
+ ELEMENT_TYPE *oldDeclElementType;
void *oldUserData;
void *oldHandlerArg;
oldhash_secret_salt = parser->m_hash_secret_salt;
#ifdef XML_DTD
- if (!context)
+ if (! context)
newDtd = oldDtd;
#endif /* XML_DTD */
XML_Char tmp[2];
*tmp = parser->m_namespaceSeparator;
parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
- }
- else {
+ } else {
parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
}
- if (!parser)
+ if (! parser)
return NULL;
parser->m_startElementHandler = oldStartElementHandler;
parser->m_prologState.inEntityValue = oldInEntityValue;
if (context) {
#endif /* XML_DTD */
- if (!dtdCopy(oldParser, parser->m_dtd, oldDtd, &parser->m_mem)
- || !setContext(parser, context)) {
+ if (! dtdCopy(oldParser, parser->m_dtd, oldDtd, &parser->m_mem)
+ || ! setContext(parser, context)) {
XML_ParserFree(parser);
return NULL;
}
parser->m_processor = externalEntityInitProcessor;
#ifdef XML_DTD
- }
- else {
- /* The DTD instance referenced by parser->m_dtd is shared between the document's
- root parser and external PE parsers, therefore one does not need to
- call setContext. In addition, one also *must* not call setContext,
- because this would overwrite existing prefix->binding pointers in
- parser->m_dtd with ones that get destroyed with the external PE parser.
- This would leave those prefixes with dangling pointers.
+ } else {
+ /* The DTD instance referenced by parser->m_dtd is shared between the
+ document's root parser and external PE parsers, therefore one does not
+ need to call setContext. In addition, one also *must* not call
+ setContext, because this would overwrite existing prefix->binding
+ pointers in parser->m_dtd with ones that get destroyed with the external
+ PE parser. This would leave those prefixes with dangling pointers.
*/
parser->m_isParamEntity = XML_TRUE;
XmlPrologStateInitExternalEntity(&parser->m_prologState);
}
static void FASTCALL
-destroyBindings(BINDING *bindings, XML_Parser parser)
-{
+destroyBindings(BINDING *bindings, XML_Parser parser) {
for (;;) {
BINDING *b = bindings;
- if (!b)
+ if (! b)
break;
bindings = b->nextTagBinding;
FREE(parser, b->uri);
}
void XMLCALL
-XML_ParserFree(XML_Parser parser)
-{
+XML_ParserFree(XML_Parser parser) {
TAG *tagList;
OPEN_INTERNAL_ENTITY *entityList;
if (parser == NULL)
/* external parameter entity parsers share the DTD structure
parser->m_dtd with the root parser, so we must not destroy it
*/
- if (!parser->m_isParamEntity && parser->m_dtd)
+ if (! parser->m_isParamEntity && parser->m_dtd)
#else
if (parser->m_dtd)
#endif /* XML_DTD */
- dtdDestroy(parser->m_dtd, (XML_Bool)!parser->m_parentParser, &parser->m_mem);
+ dtdDestroy(parser->m_dtd, (XML_Bool)! parser->m_parentParser,
+ &parser->m_mem);
FREE(parser, (void *)parser->m_atts);
#ifdef XML_ATTR_INFO
FREE(parser, (void *)parser->m_attInfo);
}
void XMLCALL
-XML_UseParserAsHandlerArg(XML_Parser parser)
-{
+XML_UseParserAsHandlerArg(XML_Parser parser) {
if (parser != NULL)
parser->m_handlerArg = parser;
}
enum XML_Error XMLCALL
-XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
-{
+XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD) {
if (parser == NULL)
return XML_ERROR_INVALID_ARGUMENT;
#ifdef XML_DTD
/* block after XML_Parse()/XML_ParseBuffer() has been called */
- if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED)
+ if (parser->m_parsingStatus.parsing == XML_PARSING
+ || parser->m_parsingStatus.parsing == XML_SUSPENDED)
return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING;
parser->m_useForeignDTD = useDTD;
return XML_ERROR_NONE;
}
void XMLCALL
-XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
-{
+XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) {
if (parser == NULL)
return;
/* block after XML_Parse()/XML_ParseBuffer() has been called */
- if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED)
+ if (parser->m_parsingStatus.parsing == XML_PARSING
+ || parser->m_parsingStatus.parsing == XML_SUSPENDED)
return;
parser->m_ns_triplets = do_nst ? XML_TRUE : XML_FALSE;
}
void XMLCALL
-XML_SetUserData(XML_Parser parser, void *p)
-{
+XML_SetUserData(XML_Parser parser, void *p) {
if (parser == NULL)
return;
if (parser->m_handlerArg == parser->m_userData)
}
enum XML_Status XMLCALL
-XML_SetBase(XML_Parser parser, const XML_Char *p)
-{
+XML_SetBase(XML_Parser parser, const XML_Char *p) {
if (parser == NULL)
return XML_STATUS_ERROR;
if (p) {
p = poolCopyString(&parser->m_dtd->pool, p);
- if (!p)
+ if (! p)
return XML_STATUS_ERROR;
parser->m_curBase = p;
- }
- else
+ } else
parser->m_curBase = NULL;
return XML_STATUS_OK;
}
-const XML_Char * XMLCALL
-XML_GetBase(XML_Parser parser)
-{
+const XML_Char *XMLCALL
+XML_GetBase(XML_Parser parser) {
if (parser == NULL)
return NULL;
return parser->m_curBase;
}
int XMLCALL
-XML_GetSpecifiedAttributeCount(XML_Parser parser)
-{
+XML_GetSpecifiedAttributeCount(XML_Parser parser) {
if (parser == NULL)
return -1;
return parser->m_nSpecifiedAtts;
}
int XMLCALL
-XML_GetIdAttributeIndex(XML_Parser parser)
-{
+XML_GetIdAttributeIndex(XML_Parser parser) {
if (parser == NULL)
return -1;
return parser->m_idAttIndex;
}
#ifdef XML_ATTR_INFO
-const XML_AttrInfo * XMLCALL
-XML_GetAttributeInfo(XML_Parser parser)
-{
+const XML_AttrInfo *XMLCALL
+XML_GetAttributeInfo(XML_Parser parser) {
if (parser == NULL)
return NULL;
return parser->m_attInfo;
#endif
void XMLCALL
-XML_SetElementHandler(XML_Parser parser,
- XML_StartElementHandler start,
- XML_EndElementHandler end)
-{
+XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start,
+ XML_EndElementHandler end) {
if (parser == NULL)
return;
parser->m_startElementHandler = start;
}
void XMLCALL
-XML_SetStartElementHandler(XML_Parser parser,
- XML_StartElementHandler start) {
+XML_SetStartElementHandler(XML_Parser parser, XML_StartElementHandler start) {
if (parser != NULL)
parser->m_startElementHandler = start;
}
void XMLCALL
-XML_SetEndElementHandler(XML_Parser parser,
- XML_EndElementHandler end) {
+XML_SetEndElementHandler(XML_Parser parser, XML_EndElementHandler end) {
if (parser != NULL)
parser->m_endElementHandler = end;
}
void XMLCALL
XML_SetCharacterDataHandler(XML_Parser parser,
- XML_CharacterDataHandler handler)
-{
+ XML_CharacterDataHandler handler) {
if (parser != NULL)
parser->m_characterDataHandler = handler;
}
void XMLCALL
XML_SetProcessingInstructionHandler(XML_Parser parser,
- XML_ProcessingInstructionHandler handler)
-{
+ XML_ProcessingInstructionHandler handler) {
if (parser != NULL)
parser->m_processingInstructionHandler = handler;
}
void XMLCALL
-XML_SetCommentHandler(XML_Parser parser,
- XML_CommentHandler handler)
-{
+XML_SetCommentHandler(XML_Parser parser, XML_CommentHandler handler) {
if (parser != NULL)
parser->m_commentHandler = handler;
}
void XMLCALL
XML_SetCdataSectionHandler(XML_Parser parser,
XML_StartCdataSectionHandler start,
- XML_EndCdataSectionHandler end)
-{
+ XML_EndCdataSectionHandler end) {
if (parser == NULL)
return;
parser->m_startCdataSectionHandler = start;
}
void XMLCALL
-XML_SetDefaultHandler(XML_Parser parser,
- XML_DefaultHandler handler)
-{
+XML_SetDefaultHandler(XML_Parser parser, XML_DefaultHandler handler) {
if (parser == NULL)
return;
parser->m_defaultHandler = handler;
}
void XMLCALL
-XML_SetDefaultHandlerExpand(XML_Parser parser,
- XML_DefaultHandler handler)
-{
+XML_SetDefaultHandlerExpand(XML_Parser parser, XML_DefaultHandler handler) {
if (parser == NULL)
return;
parser->m_defaultHandler = handler;
}
void XMLCALL
-XML_SetDoctypeDeclHandler(XML_Parser parser,
- XML_StartDoctypeDeclHandler start,
- XML_EndDoctypeDeclHandler end)
-{
+XML_SetDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start,
+ XML_EndDoctypeDeclHandler end) {
if (parser == NULL)
return;
parser->m_startDoctypeDeclHandler = start;
}
void XMLCALL
-XML_SetEndDoctypeDeclHandler(XML_Parser parser,
- XML_EndDoctypeDeclHandler end) {
+XML_SetEndDoctypeDeclHandler(XML_Parser parser, XML_EndDoctypeDeclHandler end) {
if (parser != NULL)
parser->m_endDoctypeDeclHandler = end;
}
void XMLCALL
XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
- XML_UnparsedEntityDeclHandler handler)
-{
+ XML_UnparsedEntityDeclHandler handler) {
if (parser != NULL)
parser->m_unparsedEntityDeclHandler = handler;
}
void XMLCALL
-XML_SetNotationDeclHandler(XML_Parser parser,
- XML_NotationDeclHandler handler)
-{
+XML_SetNotationDeclHandler(XML_Parser parser, XML_NotationDeclHandler handler) {
if (parser != NULL)
parser->m_notationDeclHandler = handler;
}
void XMLCALL
XML_SetNamespaceDeclHandler(XML_Parser parser,
XML_StartNamespaceDeclHandler start,
- XML_EndNamespaceDeclHandler end)
-{
+ XML_EndNamespaceDeclHandler end) {
if (parser == NULL)
return;
parser->m_startNamespaceDeclHandler = start;
void XMLCALL
XML_SetNotStandaloneHandler(XML_Parser parser,
- XML_NotStandaloneHandler handler)
-{
+ XML_NotStandaloneHandler handler) {
if (parser != NULL)
parser->m_notStandaloneHandler = handler;
}
void XMLCALL
XML_SetExternalEntityRefHandler(XML_Parser parser,
- XML_ExternalEntityRefHandler handler)
-{
+ XML_ExternalEntityRefHandler handler) {
if (parser != NULL)
parser->m_externalEntityRefHandler = handler;
}
void XMLCALL
-XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
-{
+XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg) {
if (parser == NULL)
return;
if (arg)
void XMLCALL
XML_SetSkippedEntityHandler(XML_Parser parser,
- XML_SkippedEntityHandler handler)
-{
+ XML_SkippedEntityHandler handler) {
if (parser != NULL)
parser->m_skippedEntityHandler = handler;
}
void XMLCALL
XML_SetUnknownEncodingHandler(XML_Parser parser,
- XML_UnknownEncodingHandler handler,
- void *data)
-{
+ XML_UnknownEncodingHandler handler, void *data) {
if (parser == NULL)
return;
parser->m_unknownEncodingHandler = handler;
}
void XMLCALL
-XML_SetElementDeclHandler(XML_Parser parser,
- XML_ElementDeclHandler eldecl)
-{
+XML_SetElementDeclHandler(XML_Parser parser, XML_ElementDeclHandler eldecl) {
if (parser != NULL)
parser->m_elementDeclHandler = eldecl;
}
void XMLCALL
-XML_SetAttlistDeclHandler(XML_Parser parser,
- XML_AttlistDeclHandler attdecl)
-{
+XML_SetAttlistDeclHandler(XML_Parser parser, XML_AttlistDeclHandler attdecl) {
if (parser != NULL)
parser->m_attlistDeclHandler = attdecl;
}
void XMLCALL
-XML_SetEntityDeclHandler(XML_Parser parser,
- XML_EntityDeclHandler handler)
-{
+XML_SetEntityDeclHandler(XML_Parser parser, XML_EntityDeclHandler handler) {
if (parser != NULL)
parser->m_entityDeclHandler = handler;
}
void XMLCALL
-XML_SetXmlDeclHandler(XML_Parser parser,
- XML_XmlDeclHandler handler) {
+XML_SetXmlDeclHandler(XML_Parser parser, XML_XmlDeclHandler handler) {
if (parser != NULL)
parser->m_xmlDeclHandler = handler;
}
int XMLCALL
XML_SetParamEntityParsing(XML_Parser parser,
- enum XML_ParamEntityParsing peParsing)
-{
+ enum XML_ParamEntityParsing peParsing) {
if (parser == NULL)
return 0;
/* block after XML_Parse()/XML_ParseBuffer() has been called */
- if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED)
+ if (parser->m_parsingStatus.parsing == XML_PARSING
+ || parser->m_parsingStatus.parsing == XML_SUSPENDED)
return 0;
#ifdef XML_DTD
parser->m_paramEntityParsing = peParsing;
}
int XMLCALL
-XML_SetHashSalt(XML_Parser parser,
- unsigned long hash_salt)
-{
+XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) {
if (parser == NULL)
return 0;
if (parser->m_parentParser)
return XML_SetHashSalt(parser->m_parentParser, hash_salt);
/* block after XML_Parse()/XML_ParseBuffer() has been called */
- if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED)
+ if (parser->m_parsingStatus.parsing == XML_PARSING
+ || parser->m_parsingStatus.parsing == XML_SUSPENDED)
return 0;
parser->m_hash_secret_salt = hash_salt;
return 1;
}
enum XML_Status XMLCALL
-XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
-{
+XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) {
if ((parser == NULL) || (len < 0) || ((s == NULL) && (len != 0))) {
if (parser != NULL)
parser->m_errorCode = XML_ERROR_INVALID_ARGUMENT;
parser->m_errorCode = XML_ERROR_FINISHED;
return XML_STATUS_ERROR;
case XML_INITIALIZED:
- if (parser->m_parentParser == NULL && !startParsing(parser)) {
+ if (parser->m_parentParser == NULL && ! startParsing(parser)) {
parser->m_errorCode = XML_ERROR_NO_MEMORY;
return XML_STATUS_ERROR;
}
if (len == 0) {
parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
- if (!isFinal)
+ if (! isFinal)
return XML_STATUS_OK;
parser->m_positionPtr = parser->m_bufferPtr;
parser->m_parseEndPtr = parser->m_bufferEnd;
data are the final chunk of input, then we have to check them again
to detect errors based on that fact.
*/
- parser->m_errorCode = parser->m_processor(parser, parser->m_bufferPtr, parser->m_parseEndPtr, &parser->m_bufferPtr);
+ parser->m_errorCode
+ = parser->m_processor(parser, parser->m_bufferPtr,
+ parser->m_parseEndPtr, &parser->m_bufferPtr);
if (parser->m_errorCode == XML_ERROR_NONE) {
switch (parser->m_parsingStatus.parsing) {
*
* LCOV_EXCL_START
*/
- XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, parser->m_bufferPtr, &parser->m_position);
+ XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
+ parser->m_bufferPtr, &parser->m_position);
parser->m_positionPtr = parser->m_bufferPtr;
return XML_STATUS_SUSPENDED;
/* LCOV_EXCL_STOP */
enum XML_Status result;
/* Detect overflow (a+b > MAX <==> b > MAX-a) */
if (len > ((XML_Size)-1) / 2 - parser->m_parseEndByteIndex) {
- parser->m_errorCode = XML_ERROR_NO_MEMORY;
- parser->m_eventPtr = parser->m_eventEndPtr = NULL;
- parser->m_processor = errorProcessor;
- return XML_STATUS_ERROR;
+ parser->m_errorCode = XML_ERROR_NO_MEMORY;
+ parser->m_eventPtr = parser->m_eventEndPtr = NULL;
+ parser->m_processor = errorProcessor;
+ return XML_STATUS_ERROR;
}
parser->m_parseEndByteIndex += len;
parser->m_positionPtr = s;
parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
- parser->m_errorCode = parser->m_processor(parser, s, parser->m_parseEndPtr = s + len, &end);
+ parser->m_errorCode
+ = parser->m_processor(parser, s, parser->m_parseEndPtr = s + len, &end);
if (parser->m_errorCode != XML_ERROR_NONE) {
parser->m_eventEndPtr = parser->m_eventPtr;
parser->m_processor = errorProcessor;
return XML_STATUS_ERROR;
- }
- else {
+ } else {
switch (parser->m_parsingStatus.parsing) {
case XML_SUSPENDED:
result = XML_STATUS_SUSPENDED;
}
}
- XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, end, &parser->m_position);
+ XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, end,
+ &parser->m_position);
nLeftOver = s + len - end;
if (nLeftOver) {
- if (parser->m_buffer == NULL || nLeftOver > parser->m_bufferLim - parser->m_buffer) {
+ if (parser->m_buffer == NULL
+ || nLeftOver > parser->m_bufferLim - parser->m_buffer) {
/* avoid _signed_ integer overflow */
char *temp = NULL;
const int bytesToAllocate = (int)((unsigned)len * 2U);
parser->m_eventEndPtr = parser->m_bufferPtr;
return result;
}
-#endif /* not defined XML_CONTEXT_BYTES */
+#endif /* not defined XML_CONTEXT_BYTES */
else {
void *buff = XML_GetBuffer(parser, len);
if (buff == NULL)
}
enum XML_Status XMLCALL
-XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
-{
+XML_ParseBuffer(XML_Parser parser, int len, int isFinal) {
const char *start;
enum XML_Status result = XML_STATUS_OK;
parser->m_errorCode = XML_ERROR_FINISHED;
return XML_STATUS_ERROR;
case XML_INITIALIZED:
- if (parser->m_parentParser == NULL && !startParsing(parser)) {
+ if (parser->m_parentParser == NULL && ! startParsing(parser)) {
parser->m_errorCode = XML_ERROR_NO_MEMORY;
return XML_STATUS_ERROR;
}
parser->m_parseEndByteIndex += len;
parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal;
- parser->m_errorCode = parser->m_processor(parser, start, parser->m_parseEndPtr, &parser->m_bufferPtr);
+ parser->m_errorCode = parser->m_processor(
+ parser, start, parser->m_parseEndPtr, &parser->m_bufferPtr);
if (parser->m_errorCode != XML_ERROR_NONE) {
parser->m_eventEndPtr = parser->m_eventPtr;
parser->m_processor = errorProcessor;
return XML_STATUS_ERROR;
- }
- else {
+ } else {
switch (parser->m_parsingStatus.parsing) {
case XML_SUSPENDED:
result = XML_STATUS_SUSPENDED;
parser->m_parsingStatus.parsing = XML_FINISHED;
return result;
}
- default: ; /* should not happen */
+ default:; /* should not happen */
}
}
- XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, parser->m_bufferPtr, &parser->m_position);
+ XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
+ parser->m_bufferPtr, &parser->m_position);
parser->m_positionPtr = parser->m_bufferPtr;
return result;
}
-void * XMLCALL
-XML_GetBuffer(XML_Parser parser, int len)
-{
+void *XMLCALL
+XML_GetBuffer(XML_Parser parser, int len) {
if (parser == NULL)
return NULL;
if (len < 0) {
case XML_FINISHED:
parser->m_errorCode = XML_ERROR_FINISHED;
return NULL;
- default: ;
+ default:;
}
if (len > EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferEnd)) {
#ifdef XML_CONTEXT_BYTES
int keep;
-#endif /* defined XML_CONTEXT_BYTES */
+#endif /* defined XML_CONTEXT_BYTES */
/* Do not invoke signed arithmetic overflow: */
- int neededSize = (int) ((unsigned)len +
- (unsigned)EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd,
- parser->m_bufferPtr));
+ int neededSize = (int)((unsigned)len
+ + (unsigned)EXPAT_SAFE_PTR_DIFF(
+ parser->m_bufferEnd, parser->m_bufferPtr));
if (neededSize < 0) {
parser->m_errorCode = XML_ERROR_NO_MEMORY;
return NULL;
if (keep > XML_CONTEXT_BYTES)
keep = XML_CONTEXT_BYTES;
neededSize += keep;
-#endif /* defined XML_CONTEXT_BYTES */
- if (neededSize <= EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_buffer)) {
+#endif /* defined XML_CONTEXT_BYTES */
+ if (neededSize
+ <= EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_buffer)) {
#ifdef XML_CONTEXT_BYTES
if (keep < EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer)) {
- int offset = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer) - keep;
- /* The buffer pointers cannot be NULL here; we have at least some bytes in the buffer */
- memmove(parser->m_buffer, &parser->m_buffer[offset], parser->m_bufferEnd - parser->m_bufferPtr + keep);
+ int offset
+ = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer)
+ - keep;
+ /* The buffer pointers cannot be NULL here; we have at least some bytes
+ * in the buffer */
+ memmove(parser->m_buffer, &parser->m_buffer[offset],
+ parser->m_bufferEnd - parser->m_bufferPtr + keep);
parser->m_bufferEnd -= offset;
parser->m_bufferPtr -= offset;
}
if (parser->m_buffer && parser->m_bufferPtr) {
memmove(parser->m_buffer, parser->m_bufferPtr,
EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr));
- parser->m_bufferEnd = parser->m_buffer +
- EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr);
+ parser->m_bufferEnd
+ = parser->m_buffer
+ + EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr);
parser->m_bufferPtr = parser->m_buffer;
}
-#endif /* not defined XML_CONTEXT_BYTES */
- }
- else {
+#endif /* not defined XML_CONTEXT_BYTES */
+ } else {
char *newBuf;
- int bufferSize = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferPtr);
+ int bufferSize
+ = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferPtr);
if (bufferSize == 0)
bufferSize = INIT_BUFFER_SIZE;
do {
/* Do not invoke signed arithmetic overflow: */
- bufferSize = (int) (2U * (unsigned) bufferSize);
+ bufferSize = (int)(2U * (unsigned)bufferSize);
} while (bufferSize < neededSize && bufferSize > 0);
if (bufferSize <= 0) {
parser->m_errorCode = XML_ERROR_NO_MEMORY;
parser->m_bufferLim = newBuf + bufferSize;
#ifdef XML_CONTEXT_BYTES
if (parser->m_bufferPtr) {
- int keep = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer);
- if (keep > XML_CONTEXT_BYTES)
- keep = XML_CONTEXT_BYTES;
memcpy(newBuf, &parser->m_bufferPtr[-keep],
- EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr) + keep);
+ EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr)
+ + keep);
FREE(parser, parser->m_buffer);
parser->m_buffer = newBuf;
- parser->m_bufferEnd = parser->m_buffer +
- EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr) + keep;
+ parser->m_bufferEnd
+ = parser->m_buffer
+ + EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr)
+ + keep;
parser->m_bufferPtr = parser->m_buffer + keep;
- }
- else {
+ } else {
/* This must be a brand new buffer with no data in it yet */
parser->m_bufferEnd = newBuf;
parser->m_bufferPtr = parser->m_buffer = newBuf;
memcpy(newBuf, parser->m_bufferPtr,
EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr));
FREE(parser, parser->m_buffer);
- parser->m_bufferEnd = newBuf +
- EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr);
- }
- else {
+ parser->m_bufferEnd
+ = newBuf
+ + EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr);
+ } else {
/* This must be a brand new buffer with no data in it yet */
parser->m_bufferEnd = newBuf;
}
parser->m_bufferPtr = parser->m_buffer = newBuf;
-#endif /* not defined XML_CONTEXT_BYTES */
+#endif /* not defined XML_CONTEXT_BYTES */
}
parser->m_eventPtr = parser->m_eventEndPtr = NULL;
parser->m_positionPtr = NULL;
}
enum XML_Status XMLCALL
-XML_StopParser(XML_Parser parser, XML_Bool resumable)
-{
+XML_StopParser(XML_Parser parser, XML_Bool resumable) {
if (parser == NULL)
return XML_STATUS_ERROR;
switch (parser->m_parsingStatus.parsing) {
}
#endif
parser->m_parsingStatus.parsing = XML_SUSPENDED;
- }
- else
+ } else
parser->m_parsingStatus.parsing = XML_FINISHED;
}
return XML_STATUS_OK;
}
enum XML_Status XMLCALL
-XML_ResumeParser(XML_Parser parser)
-{
+XML_ResumeParser(XML_Parser parser) {
enum XML_Status result = XML_STATUS_OK;
if (parser == NULL)
}
parser->m_parsingStatus.parsing = XML_PARSING;
- parser->m_errorCode = parser->m_processor(parser, parser->m_bufferPtr, parser->m_parseEndPtr, &parser->m_bufferPtr);
+ parser->m_errorCode = parser->m_processor(
+ parser, parser->m_bufferPtr, parser->m_parseEndPtr, &parser->m_bufferPtr);
if (parser->m_errorCode != XML_ERROR_NONE) {
parser->m_eventEndPtr = parser->m_eventPtr;
parser->m_processor = errorProcessor;
return XML_STATUS_ERROR;
- }
- else {
+ } else {
switch (parser->m_parsingStatus.parsing) {
case XML_SUSPENDED:
result = XML_STATUS_SUSPENDED;
parser->m_parsingStatus.parsing = XML_FINISHED;
return result;
}
- default: ;
+ default:;
}
}
- XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, parser->m_bufferPtr, &parser->m_position);
+ XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
+ parser->m_bufferPtr, &parser->m_position);
parser->m_positionPtr = parser->m_bufferPtr;
return result;
}
void XMLCALL
-XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status)
-{
+XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status) {
if (parser == NULL)
return;
assert(status != NULL);
}
enum XML_Error XMLCALL
-XML_GetErrorCode(XML_Parser parser)
-{
+XML_GetErrorCode(XML_Parser parser) {
if (parser == NULL)
return XML_ERROR_INVALID_ARGUMENT;
return parser->m_errorCode;
}
XML_Index XMLCALL
-XML_GetCurrentByteIndex(XML_Parser parser)
-{
+XML_GetCurrentByteIndex(XML_Parser parser) {
if (parser == NULL)
return -1;
if (parser->m_eventPtr)
- return (XML_Index)(parser->m_parseEndByteIndex - (parser->m_parseEndPtr - parser->m_eventPtr));
+ return (XML_Index)(parser->m_parseEndByteIndex
+ - (parser->m_parseEndPtr - parser->m_eventPtr));
return -1;
}
int XMLCALL
-XML_GetCurrentByteCount(XML_Parser parser)
-{
+XML_GetCurrentByteCount(XML_Parser parser) {
if (parser == NULL)
return 0;
if (parser->m_eventEndPtr && parser->m_eventPtr)
return 0;
}
-const char * XMLCALL
-XML_GetInputContext(XML_Parser parser, int *offset, int *size)
-{
+const char *XMLCALL
+XML_GetInputContext(XML_Parser parser, int *offset, int *size) {
#ifdef XML_CONTEXT_BYTES
if (parser == NULL)
return NULL;
if (offset != NULL)
*offset = (int)(parser->m_eventPtr - parser->m_buffer);
if (size != NULL)
- *size = (int)(parser->m_bufferEnd - parser->m_buffer);
+ *size = (int)(parser->m_bufferEnd - parser->m_buffer);
return parser->m_buffer;
}
#else
(void)offset;
(void)size;
#endif /* defined XML_CONTEXT_BYTES */
- return (char *) 0;
+ return (char *)0;
}
XML_Size XMLCALL
-XML_GetCurrentLineNumber(XML_Parser parser)
-{
+XML_GetCurrentLineNumber(XML_Parser parser) {
if (parser == NULL)
return 0;
if (parser->m_eventPtr && parser->m_eventPtr >= parser->m_positionPtr) {
- XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, parser->m_eventPtr, &parser->m_position);
+ XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
+ parser->m_eventPtr, &parser->m_position);
parser->m_positionPtr = parser->m_eventPtr;
}
return parser->m_position.lineNumber + 1;
}
XML_Size XMLCALL
-XML_GetCurrentColumnNumber(XML_Parser parser)
-{
+XML_GetCurrentColumnNumber(XML_Parser parser) {
if (parser == NULL)
return 0;
if (parser->m_eventPtr && parser->m_eventPtr >= parser->m_positionPtr) {
- XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, parser->m_eventPtr, &parser->m_position);
+ XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr,
+ parser->m_eventPtr, &parser->m_position);
parser->m_positionPtr = parser->m_eventPtr;
}
return parser->m_position.columnNumber;
}
void XMLCALL
-XML_FreeContentModel(XML_Parser parser, XML_Content *model)
-{
+XML_FreeContentModel(XML_Parser parser, XML_Content *model) {
if (parser != NULL)
FREE(parser, model);
}
-void * XMLCALL
-XML_MemMalloc(XML_Parser parser, size_t size)
-{
+void *XMLCALL
+XML_MemMalloc(XML_Parser parser, size_t size) {
if (parser == NULL)
return NULL;
return MALLOC(parser, size);
}
-void * XMLCALL
-XML_MemRealloc(XML_Parser parser, void *ptr, size_t size)
-{
+void *XMLCALL
+XML_MemRealloc(XML_Parser parser, void *ptr, size_t size) {
if (parser == NULL)
return NULL;
return REALLOC(parser, ptr, size);
}
void XMLCALL
-XML_MemFree(XML_Parser parser, void *ptr)
-{
+XML_MemFree(XML_Parser parser, void *ptr) {
if (parser != NULL)
FREE(parser, ptr);
}
void XMLCALL
-XML_DefaultCurrent(XML_Parser parser)
-{
+XML_DefaultCurrent(XML_Parser parser) {
if (parser == NULL)
return;
if (parser->m_defaultHandler) {
if (parser->m_openInternalEntities)
- reportDefault(parser,
- parser->m_internalEncoding,
+ reportDefault(parser, parser->m_internalEncoding,
parser->m_openInternalEntities->internalEventPtr,
parser->m_openInternalEntities->internalEventEndPtr);
else
- reportDefault(parser, parser->m_encoding, parser->m_eventPtr, parser->m_eventEndPtr);
+ reportDefault(parser, parser->m_encoding, parser->m_eventPtr,
+ parser->m_eventEndPtr);
}
}
-const XML_LChar * XMLCALL
-XML_ErrorString(enum XML_Error code)
-{
+const XML_LChar *XMLCALL
+XML_ErrorString(enum XML_Error code) {
switch (code) {
case XML_ERROR_NONE:
return NULL;
return XML_L("cannot suspend in external parameter entity");
/* Added in 2.0.0. */
case XML_ERROR_RESERVED_PREFIX_XML:
- return XML_L("reserved prefix (xml) must not be undeclared or bound to another namespace name");
+ return XML_L(
+ "reserved prefix (xml) must not be undeclared or bound to another namespace name");
case XML_ERROR_RESERVED_PREFIX_XMLNS:
return XML_L("reserved prefix (xmlns) must not be declared or undeclared");
case XML_ERROR_RESERVED_NAMESPACE_URI:
- return XML_L("prefix must not be bound to one of the reserved namespace names");
+ return XML_L(
+ "prefix must not be bound to one of the reserved namespace names");
/* Added in 2.2.5. */
- case XML_ERROR_INVALID_ARGUMENT: /* Constant added in 2.2.1, already */
+ case XML_ERROR_INVALID_ARGUMENT: /* Constant added in 2.2.1, already */
return XML_L("invalid argument");
}
return NULL;
}
-const XML_LChar * XMLCALL
+const XML_LChar *XMLCALL
XML_ExpatVersion(void) {
-
/* V1 is used to string-ize the version number. However, it would
string-ize the actual version macro *names* unless we get them
substituted before being passed to V1. CPP is defined to expand
with the correct numerals. */
/* ### I'm assuming cpp is portable in this respect... */
-#define V1(a,b,c) XML_L(#a)XML_L(".")XML_L(#b)XML_L(".")XML_L(#c)
-#define V2(a,b,c) XML_L("expat_")V1(a,b,c)
+#define V1(a, b, c) XML_L(#a) XML_L(".") XML_L(#b) XML_L(".") XML_L(#c)
+#define V2(a, b, c) XML_L("expat_") V1(a, b, c)
return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION);
}
XML_Expat_Version XMLCALL
-XML_ExpatVersionInfo(void)
-{
+XML_ExpatVersionInfo(void) {
XML_Expat_Version version;
version.major = XML_MAJOR_VERSION;
return version;
}
-const XML_Feature * XMLCALL
-XML_GetFeatureList(void)
-{
- static const XML_Feature features[] = {
- {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
- sizeof(XML_Char)},
- {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
- sizeof(XML_LChar)},
+const XML_Feature *XMLCALL
+XML_GetFeatureList(void) {
+ static const XML_Feature features[]
+ = {{XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
+ sizeof(XML_Char)},
+ {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
+ sizeof(XML_LChar)},
#ifdef XML_UNICODE
- {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
+ {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
#endif
#ifdef XML_UNICODE_WCHAR_T
- {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
+ {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
#endif
#ifdef XML_DTD
- {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
+ {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
#endif
#ifdef XML_CONTEXT_BYTES
- {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
- XML_CONTEXT_BYTES},
+ {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
+ XML_CONTEXT_BYTES},
#endif
#ifdef XML_MIN_SIZE
- {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
+ {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
#endif
#ifdef XML_NS
- {XML_FEATURE_NS, XML_L("XML_NS"), 0},
+ {XML_FEATURE_NS, XML_L("XML_NS"), 0},
#endif
#ifdef XML_LARGE_SIZE
- {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
+ {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
#endif
#ifdef XML_ATTR_INFO
- {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
+ {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
#endif
- {XML_FEATURE_END, NULL, 0}
- };
+ {XML_FEATURE_END, NULL, 0}};
return features;
}
permanent location, since the parse buffer is about to be discarded.
*/
static XML_Bool
-storeRawNames(XML_Parser parser)
-{
+storeRawNames(XML_Parser parser) {
TAG *tag = parser->m_tagStack;
while (tag) {
int bufSize;
then update it as well, since it will always point into tag->buf
*/
if (tag->name.localPart)
- tag->name.localPart = (XML_Char *)temp + (tag->name.localPart -
- (XML_Char *)tag->buf);
+ tag->name.localPart
+ = (XML_Char *)temp + (tag->name.localPart - (XML_Char *)tag->buf);
tag->buf = temp;
tag->bufEnd = temp + bufSize;
rawNameBuf = temp + nameLen;
}
static enum XML_Error PTRCALL
-contentProcessor(XML_Parser parser,
- const char *start,
- const char *end,
- const char **endPtr)
-{
- enum XML_Error result = doContent(parser, 0, parser->m_encoding, start, end,
- endPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
+contentProcessor(XML_Parser parser, const char *start, const char *end,
+ const char **endPtr) {
+ enum XML_Error result
+ = doContent(parser, 0, parser->m_encoding, start, end, endPtr,
+ (XML_Bool)! parser->m_parsingStatus.finalBuffer);
if (result == XML_ERROR_NONE) {
- if (!storeRawNames(parser))
+ if (! storeRawNames(parser))
return XML_ERROR_NO_MEMORY;
}
return result;
}
static enum XML_Error PTRCALL
-externalEntityInitProcessor(XML_Parser parser,
- const char *start,
- const char *end,
- const char **endPtr)
-{
+externalEntityInitProcessor(XML_Parser parser, const char *start,
+ const char *end, const char **endPtr) {
enum XML_Error result = initializeEncoding(parser);
if (result != XML_ERROR_NONE)
return result;
}
static enum XML_Error PTRCALL
-externalEntityInitProcessor2(XML_Parser parser,
- const char *start,
- const char *end,
- const char **endPtr)
-{
+externalEntityInitProcessor2(XML_Parser parser, const char *start,
+ const char *end, const char **endPtr) {
const char *next = start; /* XmlContentTok doesn't always set the last arg */
int tok = XmlContentTok(parser->m_encoding, start, end, &next);
switch (tok) {
doContent (by detecting XML_TOK_NONE) without processing any xml text
declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent.
*/
- if (next == end && !parser->m_parsingStatus.finalBuffer) {
+ if (next == end && ! parser->m_parsingStatus.finalBuffer) {
*endPtr = next;
return XML_ERROR_NONE;
}
start = next;
break;
case XML_TOK_PARTIAL:
- if (!parser->m_parsingStatus.finalBuffer) {
+ if (! parser->m_parsingStatus.finalBuffer) {
*endPtr = start;
return XML_ERROR_NONE;
}
parser->m_eventPtr = start;
return XML_ERROR_UNCLOSED_TOKEN;
case XML_TOK_PARTIAL_CHAR:
- if (!parser->m_parsingStatus.finalBuffer) {
+ if (! parser->m_parsingStatus.finalBuffer) {
*endPtr = start;
return XML_ERROR_NONE;
}
}
static enum XML_Error PTRCALL
-externalEntityInitProcessor3(XML_Parser parser,
- const char *start,
- const char *end,
- const char **endPtr)
-{
+externalEntityInitProcessor3(XML_Parser parser, const char *start,
+ const char *end, const char **endPtr) {
int tok;
const char *next = start; /* XmlContentTok doesn't always set the last arg */
parser->m_eventPtr = start;
parser->m_eventEndPtr = next;
switch (tok) {
- case XML_TOK_XML_DECL:
- {
- enum XML_Error result;
- result = processXmlDecl(parser, 1, start, next);
- if (result != XML_ERROR_NONE)
- return result;
- switch (parser->m_parsingStatus.parsing) {
- case XML_SUSPENDED:
- *endPtr = next;
- return XML_ERROR_NONE;
- case XML_FINISHED:
- return XML_ERROR_ABORTED;
- default:
- start = next;
- }
+ case XML_TOK_XML_DECL: {
+ enum XML_Error result;
+ result = processXmlDecl(parser, 1, start, next);
+ if (result != XML_ERROR_NONE)
+ return result;
+ switch (parser->m_parsingStatus.parsing) {
+ case XML_SUSPENDED:
+ *endPtr = next;
+ return XML_ERROR_NONE;
+ case XML_FINISHED:
+ return XML_ERROR_ABORTED;
+ default:
+ start = next;
}
- break;
+ } break;
case XML_TOK_PARTIAL:
- if (!parser->m_parsingStatus.finalBuffer) {
+ if (! parser->m_parsingStatus.finalBuffer) {
*endPtr = start;
return XML_ERROR_NONE;
}
return XML_ERROR_UNCLOSED_TOKEN;
case XML_TOK_PARTIAL_CHAR:
- if (!parser->m_parsingStatus.finalBuffer) {
+ if (! parser->m_parsingStatus.finalBuffer) {
*endPtr = start;
return XML_ERROR_NONE;
}
}
static enum XML_Error PTRCALL
-externalEntityContentProcessor(XML_Parser parser,
- const char *start,
- const char *end,
- const char **endPtr)
-{
- enum XML_Error result = doContent(parser, 1, parser->m_encoding, start, end,
- endPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
+externalEntityContentProcessor(XML_Parser parser, const char *start,
+ const char *end, const char **endPtr) {
+ enum XML_Error result
+ = doContent(parser, 1, parser->m_encoding, start, end, endPtr,
+ (XML_Bool)! parser->m_parsingStatus.finalBuffer);
if (result == XML_ERROR_NONE) {
- if (!storeRawNames(parser))
+ if (! storeRawNames(parser))
return XML_ERROR_NO_MEMORY;
}
return result;
}
static enum XML_Error
-doContent(XML_Parser parser,
- int startTagLevel,
- const ENCODING *enc,
- const char *s,
- const char *end,
- const char **nextPtr,
- XML_Bool haveMore)
-{
+doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
+ const char *s, const char *end, const char **nextPtr,
+ XML_Bool haveMore) {
/* save one level of indirection */
- DTD * const dtd = parser->m_dtd;
+ DTD *const dtd = parser->m_dtd;
const char **eventPP;
const char **eventEndPP;
if (enc == parser->m_encoding) {
eventPP = &parser->m_eventPtr;
eventEndPP = &parser->m_eventEndPtr;
- }
- else {
+ } else {
eventPP = &(parser->m_openInternalEntities->internalEventPtr);
eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
}
if (parser->m_characterDataHandler) {
XML_Char c = 0xA;
parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
- }
- else if (parser->m_defaultHandler)
+ } else if (parser->m_defaultHandler)
reportDefault(parser, enc, s, end);
/* We are at the end of the final buffer, should we check for
XML_SUSPENDED, XML_FINISHED?
return XML_ERROR_NONE;
}
return XML_ERROR_PARTIAL_CHAR;
- case XML_TOK_ENTITY_REF:
- {
- const XML_Char *name;
- ENTITY *entity;
- XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
- s + enc->minBytesPerChar,
- next - enc->minBytesPerChar);
- if (ch) {
- if (parser->m_characterDataHandler)
- parser->m_characterDataHandler(parser->m_handlerArg, &ch, 1);
- else if (parser->m_defaultHandler)
- reportDefault(parser, enc, s, next);
- break;
- }
- name = poolStoreString(&dtd->pool, enc,
- s + enc->minBytesPerChar,
- next - enc->minBytesPerChar);
- if (!name)
- return XML_ERROR_NO_MEMORY;
- entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
- poolDiscard(&dtd->pool);
- /* First, determine if a check for an existing declaration is needed;
- if yes, check that the entity exists, and that it is internal,
- otherwise call the skipped entity or default handler.
- */
- if (!dtd->hasParamEntityRefs || dtd->standalone) {
- if (!entity)
- return XML_ERROR_UNDEFINED_ENTITY;
- else if (!entity->is_internal)
- return XML_ERROR_ENTITY_DECLARED_IN_PE;
- }
- else if (!entity) {
+ case XML_TOK_ENTITY_REF: {
+ const XML_Char *name;
+ ENTITY *entity;
+ XML_Char ch = (XML_Char)XmlPredefinedEntityName(
+ enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar);
+ if (ch) {
+ if (parser->m_characterDataHandler)
+ parser->m_characterDataHandler(parser->m_handlerArg, &ch, 1);
+ else if (parser->m_defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ }
+ name = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (! name)
+ return XML_ERROR_NO_MEMORY;
+ entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
+ poolDiscard(&dtd->pool);
+ /* First, determine if a check for an existing declaration is needed;
+ if yes, check that the entity exists, and that it is internal,
+ otherwise call the skipped entity or default handler.
+ */
+ if (! dtd->hasParamEntityRefs || dtd->standalone) {
+ if (! entity)
+ return XML_ERROR_UNDEFINED_ENTITY;
+ else if (! entity->is_internal)
+ return XML_ERROR_ENTITY_DECLARED_IN_PE;
+ } else if (! entity) {
+ if (parser->m_skippedEntityHandler)
+ parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
+ else if (parser->m_defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ }
+ if (entity->open)
+ return XML_ERROR_RECURSIVE_ENTITY_REF;
+ if (entity->notation)
+ return XML_ERROR_BINARY_ENTITY_REF;
+ if (entity->textPtr) {
+ enum XML_Error result;
+ if (! parser->m_defaultExpandInternalEntities) {
if (parser->m_skippedEntityHandler)
- parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
+ parser->m_skippedEntityHandler(parser->m_handlerArg, entity->name,
+ 0);
else if (parser->m_defaultHandler)
reportDefault(parser, enc, s, next);
break;
}
- if (entity->open)
- return XML_ERROR_RECURSIVE_ENTITY_REF;
- if (entity->notation)
- return XML_ERROR_BINARY_ENTITY_REF;
- if (entity->textPtr) {
- enum XML_Error result;
- if (!parser->m_defaultExpandInternalEntities) {
- if (parser->m_skippedEntityHandler)
- parser->m_skippedEntityHandler(parser->m_handlerArg, entity->name, 0);
- else if (parser->m_defaultHandler)
- reportDefault(parser, enc, s, next);
- break;
- }
- result = processInternalEntity(parser, entity, XML_FALSE);
- if (result != XML_ERROR_NONE)
- return result;
- }
- else if (parser->m_externalEntityRefHandler) {
- const XML_Char *context;
- entity->open = XML_TRUE;
- context = getContext(parser);
- entity->open = XML_FALSE;
- if (!context)
- return XML_ERROR_NO_MEMORY;
- if (!parser->m_externalEntityRefHandler(parser->m_externalEntityRefHandlerArg,
- context,
- entity->base,
- entity->systemId,
- entity->publicId))
- return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
- poolDiscard(&parser->m_tempPool);
- }
- else if (parser->m_defaultHandler)
- reportDefault(parser, enc, s, next);
- break;
- }
+ result = processInternalEntity(parser, entity, XML_FALSE);
+ if (result != XML_ERROR_NONE)
+ return result;
+ } else if (parser->m_externalEntityRefHandler) {
+ const XML_Char *context;
+ entity->open = XML_TRUE;
+ context = getContext(parser);
+ entity->open = XML_FALSE;
+ if (! context)
+ return XML_ERROR_NO_MEMORY;
+ if (! parser->m_externalEntityRefHandler(
+ parser->m_externalEntityRefHandlerArg, context, entity->base,
+ entity->systemId, entity->publicId))
+ return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+ poolDiscard(&parser->m_tempPool);
+ } else if (parser->m_defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ }
case XML_TOK_START_TAG_NO_ATTS:
/* fall through */
- case XML_TOK_START_TAG_WITH_ATTS:
- {
- TAG *tag;
- enum XML_Error result;
- XML_Char *toPtr;
- if (parser->m_freeTagList) {
- tag = parser->m_freeTagList;
- parser->m_freeTagList = parser->m_freeTagList->parent;
+ case XML_TOK_START_TAG_WITH_ATTS: {
+ TAG *tag;
+ enum XML_Error result;
+ XML_Char *toPtr;
+ if (parser->m_freeTagList) {
+ tag = parser->m_freeTagList;
+ parser->m_freeTagList = parser->m_freeTagList->parent;
+ } else {
+ tag = (TAG *)MALLOC(parser, sizeof(TAG));
+ if (! tag)
+ return XML_ERROR_NO_MEMORY;
+ tag->buf = (char *)MALLOC(parser, INIT_TAG_BUF_SIZE);
+ if (! tag->buf) {
+ FREE(parser, tag);
+ return XML_ERROR_NO_MEMORY;
}
- else {
- tag = (TAG *)MALLOC(parser, sizeof(TAG));
- if (!tag)
- return XML_ERROR_NO_MEMORY;
- tag->buf = (char *)MALLOC(parser, INIT_TAG_BUF_SIZE);
- if (!tag->buf) {
- FREE(parser, tag);
- return XML_ERROR_NO_MEMORY;
+ tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
+ }
+ tag->bindings = NULL;
+ tag->parent = parser->m_tagStack;
+ parser->m_tagStack = tag;
+ tag->name.localPart = NULL;
+ tag->name.prefix = NULL;
+ tag->rawName = s + enc->minBytesPerChar;
+ tag->rawNameLength = XmlNameLength(enc, tag->rawName);
+ ++parser->m_tagLevel;
+ {
+ const char *rawNameEnd = tag->rawName + tag->rawNameLength;
+ const char *fromPtr = tag->rawName;
+ toPtr = (XML_Char *)tag->buf;
+ for (;;) {
+ int bufSize;
+ int convLen;
+ const enum XML_Convert_Result convert_res
+ = XmlConvert(enc, &fromPtr, rawNameEnd, (ICHAR **)&toPtr,
+ (ICHAR *)tag->bufEnd - 1);
+ convLen = (int)(toPtr - (XML_Char *)tag->buf);
+ if ((fromPtr >= rawNameEnd)
+ || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) {
+ tag->name.strLen = convLen;
+ break;
}
- tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
- }
- tag->bindings = NULL;
- tag->parent = parser->m_tagStack;
- parser->m_tagStack = tag;
- tag->name.localPart = NULL;
- tag->name.prefix = NULL;
- tag->rawName = s + enc->minBytesPerChar;
- tag->rawNameLength = XmlNameLength(enc, tag->rawName);
- ++parser->m_tagLevel;
- {
- const char *rawNameEnd = tag->rawName + tag->rawNameLength;
- const char *fromPtr = tag->rawName;
- toPtr = (XML_Char *)tag->buf;
- for (;;) {
- int bufSize;
- int convLen;
- const enum XML_Convert_Result convert_res = XmlConvert(enc,
- &fromPtr, rawNameEnd,
- (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
- convLen = (int)(toPtr - (XML_Char *)tag->buf);
- if ((fromPtr >= rawNameEnd) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) {
- tag->name.strLen = convLen;
- break;
- }
- bufSize = (int)(tag->bufEnd - tag->buf) << 1;
- {
- char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
- if (temp == NULL)
- return XML_ERROR_NO_MEMORY;
- tag->buf = temp;
- tag->bufEnd = temp + bufSize;
- toPtr = (XML_Char *)temp + convLen;
- }
+ bufSize = (int)(tag->bufEnd - tag->buf) << 1;
+ {
+ char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
+ if (temp == NULL)
+ return XML_ERROR_NO_MEMORY;
+ tag->buf = temp;
+ tag->bufEnd = temp + bufSize;
+ toPtr = (XML_Char *)temp + convLen;
}
}
- tag->name.str = (XML_Char *)tag->buf;
- *toPtr = XML_T('\0');
- result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
- if (result)
- return result;
- if (parser->m_startElementHandler)
- parser->m_startElementHandler(parser->m_handlerArg, tag->name.str,
- (const XML_Char **)parser->m_atts);
- else if (parser->m_defaultHandler)
- reportDefault(parser, enc, s, next);
- poolClear(&parser->m_tempPool);
- break;
}
+ tag->name.str = (XML_Char *)tag->buf;
+ *toPtr = XML_T('\0');
+ result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
+ if (result)
+ return result;
+ if (parser->m_startElementHandler)
+ parser->m_startElementHandler(parser->m_handlerArg, tag->name.str,
+ (const XML_Char **)parser->m_atts);
+ else if (parser->m_defaultHandler)
+ reportDefault(parser, enc, s, next);
+ poolClear(&parser->m_tempPool);
+ break;
+ }
case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
/* fall through */
- case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
- {
- const char *rawName = s + enc->minBytesPerChar;
- enum XML_Error result;
- BINDING *bindings = NULL;
- XML_Bool noElmHandlers = XML_TRUE;
- TAG_NAME name;
- name.str = poolStoreString(&parser->m_tempPool, enc, rawName,
- rawName + XmlNameLength(enc, rawName));
- if (!name.str)
- return XML_ERROR_NO_MEMORY;
- poolFinish(&parser->m_tempPool);
- result = storeAtts(parser, enc, s, &name, &bindings);
- if (result != XML_ERROR_NONE) {
- freeBindings(parser, bindings);
- return result;
- }
- poolFinish(&parser->m_tempPool);
- if (parser->m_startElementHandler) {
- parser->m_startElementHandler(parser->m_handlerArg, name.str, (const XML_Char **)parser->m_atts);
- noElmHandlers = XML_FALSE;
- }
- if (parser->m_endElementHandler) {
- if (parser->m_startElementHandler)
- *eventPP = *eventEndPP;
- parser->m_endElementHandler(parser->m_handlerArg, name.str);
- noElmHandlers = XML_FALSE;
- }
- if (noElmHandlers && parser->m_defaultHandler)
- reportDefault(parser, enc, s, next);
- poolClear(&parser->m_tempPool);
+ case XML_TOK_EMPTY_ELEMENT_WITH_ATTS: {
+ const char *rawName = s + enc->minBytesPerChar;
+ enum XML_Error result;
+ BINDING *bindings = NULL;
+ XML_Bool noElmHandlers = XML_TRUE;
+ TAG_NAME name;
+ name.str = poolStoreString(&parser->m_tempPool, enc, rawName,
+ rawName + XmlNameLength(enc, rawName));
+ if (! name.str)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&parser->m_tempPool);
+ result = storeAtts(parser, enc, s, &name, &bindings);
+ if (result != XML_ERROR_NONE) {
freeBindings(parser, bindings);
+ return result;
+ }
+ poolFinish(&parser->m_tempPool);
+ if (parser->m_startElementHandler) {
+ parser->m_startElementHandler(parser->m_handlerArg, name.str,
+ (const XML_Char **)parser->m_atts);
+ noElmHandlers = XML_FALSE;
+ }
+ if (parser->m_endElementHandler) {
+ if (parser->m_startElementHandler)
+ *eventPP = *eventEndPP;
+ parser->m_endElementHandler(parser->m_handlerArg, name.str);
+ noElmHandlers = XML_FALSE;
}
- if ((parser->m_tagLevel == 0) && (parser->m_parsingStatus.parsing != XML_FINISHED)) {
+ if (noElmHandlers && parser->m_defaultHandler)
+ reportDefault(parser, enc, s, next);
+ poolClear(&parser->m_tempPool);
+ freeBindings(parser, bindings);
+ }
+ if ((parser->m_tagLevel == 0)
+ && (parser->m_parsingStatus.parsing != XML_FINISHED)) {
if (parser->m_parsingStatus.parsing == XML_SUSPENDED)
parser->m_processor = epilogProcessor;
else
parser->m_tagStack = tag->parent;
tag->parent = parser->m_freeTagList;
parser->m_freeTagList = tag;
- rawName = s + enc->minBytesPerChar*2;
+ rawName = s + enc->minBytesPerChar * 2;
len = XmlNameLength(enc, rawName);
if (len != tag->rawNameLength
|| memcmp(tag->rawName, rawName, len) != 0) {
*/
uri = (XML_Char *)tag->name.str + tag->name.uriLen;
/* don't need to check for space - already done in storeAtts() */
- while (*localPart) *uri++ = *localPart++;
+ while (*localPart)
+ *uri++ = *localPart++;
prefix = (XML_Char *)tag->name.prefix;
if (parser->m_ns_triplets && prefix) {
*uri++ = parser->m_namespaceSeparator;
- while (*prefix) *uri++ = *prefix++;
- }
+ while (*prefix)
+ *uri++ = *prefix++;
+ }
*uri = XML_T('\0');
}
parser->m_endElementHandler(parser->m_handlerArg, tag->name.str);
- }
- else if (parser->m_defaultHandler)
+ } else if (parser->m_defaultHandler)
reportDefault(parser, enc, s, next);
while (tag->bindings) {
BINDING *b = tag->bindings;
if (parser->m_endNamespaceDeclHandler)
- parser->m_endNamespaceDeclHandler(parser->m_handlerArg, b->prefix->name);
+ parser->m_endNamespaceDeclHandler(parser->m_handlerArg,
+ b->prefix->name);
tag->bindings = tag->bindings->nextTagBinding;
b->nextTagBinding = parser->m_freeBindingList;
parser->m_freeBindingList = b;
b->prefix->binding = b->prevPrefixBinding;
}
- if (parser->m_tagLevel == 0)
- return epilogProcessor(parser, next, end, nextPtr);
- }
- break;
- case XML_TOK_CHAR_REF:
- {
- int n = XmlCharRefNumber(enc, s);
- if (n < 0)
- return XML_ERROR_BAD_CHAR_REF;
- if (parser->m_characterDataHandler) {
- XML_Char buf[XML_ENCODE_MAX];
- parser->m_characterDataHandler(parser->m_handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
+ if ((parser->m_tagLevel == 0)
+ && (parser->m_parsingStatus.parsing != XML_FINISHED)) {
+ if (parser->m_parsingStatus.parsing == XML_SUSPENDED)
+ parser->m_processor = epilogProcessor;
+ else
+ return epilogProcessor(parser, next, end, nextPtr);
}
- else if (parser->m_defaultHandler)
- reportDefault(parser, enc, s, next);
}
break;
+ case XML_TOK_CHAR_REF: {
+ int n = XmlCharRefNumber(enc, s);
+ if (n < 0)
+ return XML_ERROR_BAD_CHAR_REF;
+ if (parser->m_characterDataHandler) {
+ XML_Char buf[XML_ENCODE_MAX];
+ parser->m_characterDataHandler(parser->m_handlerArg, buf,
+ XmlEncode(n, (ICHAR *)buf));
+ } else if (parser->m_defaultHandler)
+ reportDefault(parser, enc, s, next);
+ } break;
case XML_TOK_XML_DECL:
return XML_ERROR_MISPLACED_XML_PI;
case XML_TOK_DATA_NEWLINE:
if (parser->m_characterDataHandler) {
XML_Char c = 0xA;
parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
- }
- else if (parser->m_defaultHandler)
+ } else if (parser->m_defaultHandler)
reportDefault(parser, enc, s, next);
break;
- case XML_TOK_CDATA_SECT_OPEN:
- {
- enum XML_Error result;
- if (parser->m_startCdataSectionHandler)
- parser->m_startCdataSectionHandler(parser->m_handlerArg);
-/* BEGIN disabled code */
- /* Suppose you doing a transformation on a document that involves
- changing only the character data. You set up a defaultHandler
- and a characterDataHandler. The defaultHandler simply copies
- characters through. The characterDataHandler does the
- transformation and writes the characters out escaping them as
- necessary. This case will fail to work if we leave out the
- following two lines (because & and < inside CDATA sections will
- be incorrectly escaped).
-
- However, now we have a start/endCdataSectionHandler, so it seems
- easier to let the user deal with this.
- */
- else if (0 && parser->m_characterDataHandler)
- parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf, 0);
-/* END disabled code */
- else if (parser->m_defaultHandler)
- reportDefault(parser, enc, s, next);
- result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore);
- if (result != XML_ERROR_NONE)
- return result;
- else if (!next) {
- parser->m_processor = cdataSectionProcessor;
- return result;
- }
+ case XML_TOK_CDATA_SECT_OPEN: {
+ enum XML_Error result;
+ if (parser->m_startCdataSectionHandler)
+ parser->m_startCdataSectionHandler(parser->m_handlerArg);
+ /* BEGIN disabled code */
+ /* Suppose you doing a transformation on a document that involves
+ changing only the character data. You set up a defaultHandler
+ and a characterDataHandler. The defaultHandler simply copies
+ characters through. The characterDataHandler does the
+ transformation and writes the characters out escaping them as
+ necessary. This case will fail to work if we leave out the
+ following two lines (because & and < inside CDATA sections will
+ be incorrectly escaped).
+
+ However, now we have a start/endCdataSectionHandler, so it seems
+ easier to let the user deal with this.
+ */
+ else if (0 && parser->m_characterDataHandler)
+ parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf,
+ 0);
+ /* END disabled code */
+ else if (parser->m_defaultHandler)
+ reportDefault(parser, enc, s, next);
+ result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore);
+ if (result != XML_ERROR_NONE)
+ return result;
+ else if (! next) {
+ parser->m_processor = cdataSectionProcessor;
+ return result;
}
- break;
+ } break;
case XML_TOK_TRAILING_RSQB:
if (haveMore) {
*nextPtr = s;
if (MUST_CONVERT(enc, s)) {
ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
- parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf,
- (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
- }
- else
- parser->m_characterDataHandler(parser->m_handlerArg,
- (XML_Char *)s,
- (int)((XML_Char *)end - (XML_Char *)s));
- }
- else if (parser->m_defaultHandler)
+ parser->m_characterDataHandler(
+ parser->m_handlerArg, parser->m_dataBuf,
+ (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
+ } else
+ parser->m_characterDataHandler(
+ parser->m_handlerArg, (XML_Char *)s,
+ (int)((XML_Char *)end - (XML_Char *)s));
+ } else if (parser->m_defaultHandler)
reportDefault(parser, enc, s, end);
/* We are at the end of the final buffer, should we check for
XML_SUSPENDED, XML_FINISHED?
}
*nextPtr = end;
return XML_ERROR_NONE;
- case XML_TOK_DATA_CHARS:
- {
- XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler;
- if (charDataHandler) {
- if (MUST_CONVERT(enc, s)) {
- for (;;) {
- ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
- const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
- *eventEndPP = s;
- charDataHandler(parser->m_handlerArg, parser->m_dataBuf,
- (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
- if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
- break;
- *eventPP = s;
- }
+ case XML_TOK_DATA_CHARS: {
+ XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler;
+ if (charDataHandler) {
+ if (MUST_CONVERT(enc, s)) {
+ for (;;) {
+ ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
+ const enum XML_Convert_Result convert_res = XmlConvert(
+ enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
+ *eventEndPP = s;
+ charDataHandler(parser->m_handlerArg, parser->m_dataBuf,
+ (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
+ if ((convert_res == XML_CONVERT_COMPLETED)
+ || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
+ break;
+ *eventPP = s;
}
- else
- charDataHandler(parser->m_handlerArg,
- (XML_Char *)s,
- (int)((XML_Char *)next - (XML_Char *)s));
- }
- else if (parser->m_defaultHandler)
- reportDefault(parser, enc, s, next);
- }
- break;
+ } else
+ charDataHandler(parser->m_handlerArg, (XML_Char *)s,
+ (int)((XML_Char *)next - (XML_Char *)s));
+ } else if (parser->m_defaultHandler)
+ reportDefault(parser, enc, s, next);
+ } break;
case XML_TOK_PI:
- if (!reportProcessingInstruction(parser, enc, s, next))
+ if (! reportProcessingInstruction(parser, enc, s, next))
return XML_ERROR_NO_MEMORY;
break;
case XML_TOK_COMMENT:
- if (!reportComment(parser, enc, s, next))
+ if (! reportComment(parser, enc, s, next))
return XML_ERROR_NO_MEMORY;
break;
default:
return XML_ERROR_NONE;
case XML_FINISHED:
return XML_ERROR_ABORTED;
- default: ;
+ default:;
}
}
/* not reached */
* reused as appropriate.
*/
static void
-freeBindings(XML_Parser parser, BINDING *bindings)
-{
+freeBindings(XML_Parser parser, BINDING *bindings) {
while (bindings) {
BINDING *b = bindings;
* binding in addBindings(), so call the end handler now.
*/
if (parser->m_endNamespaceDeclHandler)
- parser->m_endNamespaceDeclHandler(parser->m_handlerArg, b->prefix->name);
+ parser->m_endNamespaceDeclHandler(parser->m_handlerArg, b->prefix->name);
bindings = bindings->nextTagBinding;
b->nextTagBinding = parser->m_freeBindingList;
- generate namespace aware element name (URI, prefix)
*/
static enum XML_Error
-storeAtts(XML_Parser parser, const ENCODING *enc,
- const char *attStr, TAG_NAME *tagNamePtr,
- BINDING **bindingsPtr)
-{
- DTD * const dtd = parser->m_dtd; /* save one level of indirection */
+storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
+ TAG_NAME *tagNamePtr, BINDING **bindingsPtr) {
+ DTD *const dtd = parser->m_dtd; /* save one level of indirection */
ELEMENT_TYPE *elementType;
int nDefaultAtts;
- const XML_Char **appAtts; /* the attribute list for the application */
+ const XML_Char **appAtts; /* the attribute list for the application */
int attIndex = 0;
int prefixLen;
int i;
const XML_Char *localPart;
/* lookup the element type name */
- elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str,0);
- if (!elementType) {
+ elementType
+ = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str, 0);
+ if (! elementType) {
const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str);
- if (!name)
+ if (! name)
return XML_ERROR_NO_MEMORY;
elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
sizeof(ELEMENT_TYPE));
- if (!elementType)
+ if (! elementType)
return XML_ERROR_NO_MEMORY;
- if (parser->m_ns && !setElementTypePrefix(parser, elementType))
+ if (parser->m_ns && ! setElementTypePrefix(parser, elementType))
return XML_ERROR_NO_MEMORY;
}
nDefaultAtts = elementType->nDefaultAtts;
XML_AttrInfo *temp2;
#endif
parser->m_attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
- temp = (ATTRIBUTE *)REALLOC(parser, (void *)parser->m_atts, parser->m_attsSize * sizeof(ATTRIBUTE));
+ temp = (ATTRIBUTE *)REALLOC(parser, (void *)parser->m_atts,
+ parser->m_attsSize * sizeof(ATTRIBUTE));
if (temp == NULL) {
parser->m_attsSize = oldAttsSize;
return XML_ERROR_NO_MEMORY;
}
parser->m_atts = temp;
#ifdef XML_ATTR_INFO
- temp2 = (XML_AttrInfo *)REALLOC(parser, (void *)parser->m_attInfo, parser->m_attsSize * sizeof(XML_AttrInfo));
+ temp2 = (XML_AttrInfo *)REALLOC(parser, (void *)parser->m_attInfo,
+ parser->m_attsSize * sizeof(XML_AttrInfo));
if (temp2 == NULL) {
parser->m_attsSize = oldAttsSize;
return XML_ERROR_NO_MEMORY;
XML_AttrInfo *currAttInfo = &parser->m_attInfo[i];
#endif
/* add the name and value to the attribute list */
- ATTRIBUTE_ID *attId = getAttributeId(parser, enc, currAtt->name,
- currAtt->name
- + XmlNameLength(enc, currAtt->name));
- if (!attId)
+ ATTRIBUTE_ID *attId
+ = getAttributeId(parser, enc, currAtt->name,
+ currAtt->name + XmlNameLength(enc, currAtt->name));
+ if (! attId)
return XML_ERROR_NO_MEMORY;
#ifdef XML_ATTR_INFO
- currAttInfo->nameStart = parser->m_parseEndByteIndex - (parser->m_parseEndPtr - currAtt->name);
- currAttInfo->nameEnd = currAttInfo->nameStart +
- XmlNameLength(enc, currAtt->name);
- currAttInfo->valueStart = parser->m_parseEndByteIndex -
- (parser->m_parseEndPtr - currAtt->valuePtr);
- currAttInfo->valueEnd = parser->m_parseEndByteIndex - (parser->m_parseEndPtr - currAtt->valueEnd);
+ currAttInfo->nameStart
+ = parser->m_parseEndByteIndex - (parser->m_parseEndPtr - currAtt->name);
+ currAttInfo->nameEnd
+ = currAttInfo->nameStart + XmlNameLength(enc, currAtt->name);
+ currAttInfo->valueStart = parser->m_parseEndByteIndex
+ - (parser->m_parseEndPtr - currAtt->valuePtr);
+ currAttInfo->valueEnd = parser->m_parseEndByteIndex
+ - (parser->m_parseEndPtr - currAtt->valueEnd);
#endif
/* Detect duplicate attributes by their QNames. This does not work when
namespace processing is turned on and different prefixes for the same
}
(attId->name)[-1] = 1;
appAtts[attIndex++] = attId->name;
- if (!parser->m_atts[i].normalized) {
+ if (! parser->m_atts[i].normalized) {
enum XML_Error result;
XML_Bool isCdata = XML_TRUE;
}
/* normalize the attribute value */
- result = storeAttributeValue(parser, enc, isCdata,
- parser->m_atts[i].valuePtr, parser->m_atts[i].valueEnd,
- &parser->m_tempPool);
+ result = storeAttributeValue(
+ parser, enc, isCdata, parser->m_atts[i].valuePtr,
+ parser->m_atts[i].valueEnd, &parser->m_tempPool);
if (result)
return result;
appAtts[attIndex] = poolStart(&parser->m_tempPool);
poolFinish(&parser->m_tempPool);
- }
- else {
+ } else {
/* the value did not need normalizing */
- appAtts[attIndex] = poolStoreString(&parser->m_tempPool, enc, parser->m_atts[i].valuePtr,
+ appAtts[attIndex] = poolStoreString(&parser->m_tempPool, enc,
+ parser->m_atts[i].valuePtr,
parser->m_atts[i].valueEnd);
if (appAtts[attIndex] == 0)
return XML_ERROR_NO_MEMORY;
if (result)
return result;
--attIndex;
- }
- else {
+ } else {
/* deal with other prefixed names later */
attIndex++;
nPrefixes++;
(attId->name)[-1] = 2;
}
- }
- else
+ } else
attIndex++;
}
parser->m_idAttIndex = i;
break;
}
- }
- else
+ } else
parser->m_idAttIndex = -1;
/* do attribute defaulting */
for (i = 0; i < nDefaultAtts; i++) {
const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i;
- if (!(da->id->name)[-1] && da->value) {
+ if (! (da->id->name)[-1] && da->value) {
if (da->id->prefix) {
if (da->id->xmlns) {
enum XML_Error result = addBinding(parser, da->id->prefix, da->id,
da->value, bindingsPtr);
if (result)
return result;
- }
- else {
+ } else {
(da->id->name)[-1] = 2;
nPrefixes++;
appAtts[attIndex++] = da->id->name;
appAtts[attIndex++] = da->value;
}
- }
- else {
+ } else {
(da->id->name)[-1] = 1;
appAtts[attIndex++] = da->id->name;
appAtts[attIndex++] = da->value;
and clear flags that say whether attributes were specified */
i = 0;
if (nPrefixes) {
- int j; /* hash table index */
+ int j; /* hash table index */
unsigned long version = parser->m_nsAttsVersion;
int nsAttsSize = (int)1 << parser->m_nsAttsPower;
unsigned char oldNsAttsPower = parser->m_nsAttsPower;
/* size of hash table must be at least 2 * (# of prefixed attributes) */
- if ((nPrefixes << 1) >> parser->m_nsAttsPower) { /* true for m_nsAttsPower = 0 */
+ if ((nPrefixes << 1)
+ >> parser->m_nsAttsPower) { /* true for m_nsAttsPower = 0 */
NS_ATT *temp;
/* hash table size must also be a power of 2 and >= 8 */
- while (nPrefixes >> parser->m_nsAttsPower++);
+ while (nPrefixes >> parser->m_nsAttsPower++)
+ ;
if (parser->m_nsAttsPower < 3)
parser->m_nsAttsPower = 3;
nsAttsSize = (int)1 << parser->m_nsAttsPower;
- temp = (NS_ATT *)REALLOC(parser, parser->m_nsAtts, nsAttsSize * sizeof(NS_ATT));
- if (!temp) {
+ temp = (NS_ATT *)REALLOC(parser, parser->m_nsAtts,
+ nsAttsSize * sizeof(NS_ATT));
+ if (! temp) {
/* Restore actual size of memory in m_nsAtts */
parser->m_nsAttsPower = oldNsAttsPower;
return XML_ERROR_NO_MEMORY;
}
parser->m_nsAtts = temp;
- version = 0; /* force re-initialization of m_nsAtts hash table */
+ version = 0; /* force re-initialization of m_nsAtts hash table */
}
/* using a version flag saves us from initializing m_nsAtts every time */
- if (!version) { /* initialize version flags when version wraps around */
+ if (! version) { /* initialize version flags when version wraps around */
version = INIT_ATTS_VERSION;
- for (j = nsAttsSize; j != 0; )
+ for (j = nsAttsSize; j != 0;)
parser->m_nsAtts[--j].version = version;
}
parser->m_nsAttsVersion = --version;
/* expand prefixed names and check for duplicates */
for (; i < attIndex; i += 2) {
const XML_Char *s = appAtts[i];
- if (s[-1] == 2) { /* prefixed */
+ if (s[-1] == 2) { /* prefixed */
ATTRIBUTE_ID *id;
const BINDING *b;
unsigned long uriHash;
copy_salt_to_sipkey(parser, &sip_key);
sip24_init(&sip_state, &sip_key);
- ((XML_Char *)s)[-1] = 0; /* clear flag */
+ ((XML_Char *)s)[-1] = 0; /* clear flag */
id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);
- if (!id || !id->prefix) {
+ if (! id || ! id->prefix) {
/* This code is walking through the appAtts array, dealing
* with (in this case) a prefixed attribute name. To be in
* the array, the attribute must have already been bound, so
return XML_ERROR_NO_MEMORY; /* LCOV_EXCL_LINE */
}
b = id->prefix->binding;
- if (!b)
+ if (! b)
return XML_ERROR_UNBOUND_PREFIX;
for (j = 0; j < b->uriLen; j++) {
const XML_Char c = b->uri[j];
- if (!poolAppendChar(&parser->m_tempPool, c))
+ if (! poolAppendChar(&parser->m_tempPool, c))
return XML_ERROR_NO_MEMORY;
}
sip24_update(&sip_state, s, keylen(s) * sizeof(XML_Char));
- do { /* copies null terminator */
- if (!poolAppendChar(&parser->m_tempPool, *s))
+ do { /* copies null terminator */
+ if (! poolAppendChar(&parser->m_tempPool, *s))
return XML_ERROR_NO_MEMORY;
} while (*s++);
*/
unsigned char step = 0;
unsigned long mask = nsAttsSize - 1;
- j = uriHash & mask; /* index into hash table */
+ j = uriHash & mask; /* index into hash table */
while (parser->m_nsAtts[j].version == version) {
/* for speed we compare stored hash values first */
if (uriHash == parser->m_nsAtts[j].hash) {
const XML_Char *s1 = poolStart(&parser->m_tempPool);
const XML_Char *s2 = parser->m_nsAtts[j].uriName;
/* s1 is null terminated, but not s2 */
- for (; *s1 == *s2 && *s1 != 0; s1++, s2++);
+ for (; *s1 == *s2 && *s1 != 0; s1++, s2++)
+ ;
if (*s1 == 0)
return XML_ERROR_DUPLICATE_ATTRIBUTE;
}
- if (!step)
+ if (! step)
step = PROBE_STEP(uriHash, mask, parser->m_nsAttsPower);
j < step ? (j += nsAttsSize - step) : (j -= step);
}
}
- if (parser->m_ns_triplets) { /* append namespace separator and prefix */
+ if (parser->m_ns_triplets) { /* append namespace separator and prefix */
parser->m_tempPool.ptr[-1] = parser->m_namespaceSeparator;
s = b->prefix->name;
do {
- if (!poolAppendChar(&parser->m_tempPool, *s))
+ if (! poolAppendChar(&parser->m_tempPool, *s))
return XML_ERROR_NO_MEMORY;
} while (*s++);
}
parser->m_nsAtts[j].hash = uriHash;
parser->m_nsAtts[j].uriName = s;
- if (!--nPrefixes) {
+ if (! --nPrefixes) {
i += 2;
break;
}
- }
- else /* not prefixed */
- ((XML_Char *)s)[-1] = 0; /* clear flag */
+ } else /* not prefixed */
+ ((XML_Char *)s)[-1] = 0; /* clear flag */
}
}
/* clear flags for the remaining attributes */
for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
binding->attId->name[-1] = 0;
- if (!parser->m_ns)
+ if (! parser->m_ns)
return XML_ERROR_NONE;
/* expand the element type name */
if (elementType->prefix) {
binding = elementType->prefix->binding;
- if (!binding)
+ if (! binding)
return XML_ERROR_UNBOUND_PREFIX;
localPart = tagNamePtr->str;
while (*localPart++ != XML_T(ASCII_COLON))
;
- }
- else if (dtd->defaultPrefix.binding) {
+ } else if (dtd->defaultPrefix.binding) {
binding = dtd->defaultPrefix.binding;
localPart = tagNamePtr->str;
- }
- else
+ } else
return XML_ERROR_NONE;
prefixLen = 0;
if (parser->m_ns_triplets && binding->prefix->name) {
for (; binding->prefix->name[prefixLen++];)
- ; /* prefixLen includes null terminator */
+ ; /* prefixLen includes null terminator */
}
tagNamePtr->localPart = localPart;
tagNamePtr->uriLen = binding->uriLen;
tagNamePtr->prefix = binding->prefix->name;
tagNamePtr->prefixLen = prefixLen;
for (i = 0; localPart[i++];)
- ; /* i includes null terminator */
+ ; /* i includes null terminator */
n = i + binding->uriLen + prefixLen;
if (n > binding->uriAlloc) {
TAG *p;
uri = (XML_Char *)MALLOC(parser, (n + EXPAND_SPARE) * sizeof(XML_Char));
- if (!uri)
+ if (! uri)
return XML_ERROR_NO_MEMORY;
binding->uriAlloc = n + EXPAND_SPARE;
memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
/* we always have a namespace separator between localPart and prefix */
if (prefixLen) {
uri += i - 1;
- *uri = parser->m_namespaceSeparator; /* replace null terminator */
+ *uri = parser->m_namespaceSeparator; /* replace null terminator */
memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char));
}
tagNamePtr->str = binding->uri;
*/
static enum XML_Error
addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
- const XML_Char *uri, BINDING **bindingsPtr)
-{
- static const XML_Char xmlNamespace[] = {
- ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
- ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
- ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L,
- ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9, ASCII_8, ASCII_SLASH,
- ASCII_n, ASCII_a, ASCII_m, ASCII_e, ASCII_s, ASCII_p, ASCII_a, ASCII_c,
- ASCII_e, '\0'
- };
- static const int xmlLen =
- (int)sizeof(xmlNamespace)/sizeof(XML_Char) - 1;
- static const XML_Char xmlnsNamespace[] = {
- ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH,
- ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD,
- ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_2, ASCII_0, ASCII_0,
- ASCII_0, ASCII_SLASH, ASCII_x, ASCII_m, ASCII_l, ASCII_n, ASCII_s,
- ASCII_SLASH, '\0'
- };
- static const int xmlnsLen =
- (int)sizeof(xmlnsNamespace)/sizeof(XML_Char) - 1;
+ const XML_Char *uri, BINDING **bindingsPtr) {
+ static const XML_Char xmlNamespace[]
+ = {ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON,
+ ASCII_SLASH, ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w,
+ ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o,
+ ASCII_r, ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M,
+ ASCII_L, ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9,
+ ASCII_8, ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m,
+ ASCII_e, ASCII_s, ASCII_p, ASCII_a, ASCII_c,
+ ASCII_e, '\0'};
+ static const int xmlLen = (int)sizeof(xmlNamespace) / sizeof(XML_Char) - 1;
+ static const XML_Char xmlnsNamespace[]
+ = {ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH,
+ ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w,
+ ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH,
+ ASCII_2, ASCII_0, ASCII_0, ASCII_0, ASCII_SLASH, ASCII_x,
+ ASCII_m, ASCII_l, ASCII_n, ASCII_s, ASCII_SLASH, '\0'};
+ static const int xmlnsLen
+ = (int)sizeof(xmlnsNamespace) / sizeof(XML_Char) - 1;
XML_Bool mustBeXML = XML_FALSE;
XML_Bool isXML = XML_TRUE;
if (*uri == XML_T('\0') && prefix->name)
return XML_ERROR_UNDECLARING_PREFIX;
- if (prefix->name
- && prefix->name[0] == XML_T(ASCII_x)
+ if (prefix->name && prefix->name[0] == XML_T(ASCII_x)
&& prefix->name[1] == XML_T(ASCII_m)
&& prefix->name[2] == XML_T(ASCII_l)) {
-
/* Not allowed to bind xmlns */
- if (prefix->name[3] == XML_T(ASCII_n)
- && prefix->name[4] == XML_T(ASCII_s)
+ if (prefix->name[3] == XML_T(ASCII_n) && prefix->name[4] == XML_T(ASCII_s)
&& prefix->name[5] == XML_T('\0'))
return XML_ERROR_RESERVED_PREFIX_XMLNS;
if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len]))
isXML = XML_FALSE;
- if (!mustBeXML && isXMLNS
+ if (! mustBeXML && isXMLNS
&& (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
isXMLNS = XML_FALSE;
}
if (parser->m_freeBindingList) {
b = parser->m_freeBindingList;
if (len > b->uriAlloc) {
- XML_Char *temp = (XML_Char *)REALLOC(parser, b->uri,
- sizeof(XML_Char) * (len + EXPAND_SPARE));
+ XML_Char *temp = (XML_Char *)REALLOC(
+ parser, b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE));
if (temp == NULL)
return XML_ERROR_NO_MEMORY;
b->uri = temp;
b->uriAlloc = len + EXPAND_SPARE;
}
parser->m_freeBindingList = b->nextTagBinding;
- }
- else {
+ } else {
b = (BINDING *)MALLOC(parser, sizeof(BINDING));
- if (!b)
+ if (! b)
return XML_ERROR_NO_MEMORY;
- b->uri = (XML_Char *)MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE));
- if (!b->uri) {
+ b->uri
+ = (XML_Char *)MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE));
+ if (! b->uri) {
FREE(parser, b);
return XML_ERROR_NO_MEMORY;
}
/* if attId == NULL then we are not starting a namespace scope */
if (attId && parser->m_startNamespaceDeclHandler)
parser->m_startNamespaceDeclHandler(parser->m_handlerArg, prefix->name,
- prefix->binding ? uri : 0);
+ prefix->binding ? uri : 0);
return XML_ERROR_NONE;
}
the whole file is parsed with one call.
*/
static enum XML_Error PTRCALL
-cdataSectionProcessor(XML_Parser parser,
- const char *start,
- const char *end,
- const char **endPtr)
-{
- enum XML_Error result = doCdataSection(parser, parser->m_encoding, &start, end,
- endPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
+cdataSectionProcessor(XML_Parser parser, const char *start, const char *end,
+ const char **endPtr) {
+ enum XML_Error result
+ = doCdataSection(parser, parser->m_encoding, &start, end, endPtr,
+ (XML_Bool)! parser->m_parsingStatus.finalBuffer);
if (result != XML_ERROR_NONE)
return result;
if (start) {
- if (parser->m_parentParser) { /* we are parsing an external entity */
+ if (parser->m_parentParser) { /* we are parsing an external entity */
parser->m_processor = externalEntityContentProcessor;
return externalEntityContentProcessor(parser, start, end, endPtr);
- }
- else {
+ } else {
parser->m_processor = contentProcessor;
return contentProcessor(parser, start, end, endPtr);
}
the section is not yet closed.
*/
static enum XML_Error
-doCdataSection(XML_Parser parser,
- const ENCODING *enc,
- const char **startPtr,
- const char *end,
- const char **nextPtr,
- XML_Bool haveMore)
-{
+doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
+ const char *end, const char **nextPtr, XML_Bool haveMore) {
const char *s = *startPtr;
const char **eventPP;
const char **eventEndPP;
eventPP = &parser->m_eventPtr;
*eventPP = s;
eventEndPP = &parser->m_eventEndPtr;
- }
- else {
+ } else {
eventPP = &(parser->m_openInternalEntities->internalEventPtr);
eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
}
case XML_TOK_CDATA_SECT_CLOSE:
if (parser->m_endCdataSectionHandler)
parser->m_endCdataSectionHandler(parser->m_handlerArg);
-/* BEGIN disabled code */
+ /* BEGIN disabled code */
/* see comment under XML_TOK_CDATA_SECT_OPEN */
else if (0 && parser->m_characterDataHandler)
- parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf, 0);
-/* END disabled code */
+ parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf,
+ 0);
+ /* END disabled code */
else if (parser->m_defaultHandler)
reportDefault(parser, enc, s, next);
*startPtr = next;
if (parser->m_characterDataHandler) {
XML_Char c = 0xA;
parser->m_characterDataHandler(parser->m_handlerArg, &c, 1);
- }
- else if (parser->m_defaultHandler)
+ } else if (parser->m_defaultHandler)
reportDefault(parser, enc, s, next);
break;
- case XML_TOK_DATA_CHARS:
- {
- XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler;
- if (charDataHandler) {
- if (MUST_CONVERT(enc, s)) {
- for (;;) {
- ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
- const enum XML_Convert_Result convert_res = XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
- *eventEndPP = next;
- charDataHandler(parser->m_handlerArg, parser->m_dataBuf,
- (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
- if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
- break;
- *eventPP = s;
- }
+ case XML_TOK_DATA_CHARS: {
+ XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler;
+ if (charDataHandler) {
+ if (MUST_CONVERT(enc, s)) {
+ for (;;) {
+ ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
+ const enum XML_Convert_Result convert_res = XmlConvert(
+ enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
+ *eventEndPP = next;
+ charDataHandler(parser->m_handlerArg, parser->m_dataBuf,
+ (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
+ if ((convert_res == XML_CONVERT_COMPLETED)
+ || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
+ break;
+ *eventPP = s;
}
- else
- charDataHandler(parser->m_handlerArg,
- (XML_Char *)s,
- (int)((XML_Char *)next - (XML_Char *)s));
- }
- else if (parser->m_defaultHandler)
- reportDefault(parser, enc, s, next);
- }
- break;
+ } else
+ charDataHandler(parser->m_handlerArg, (XML_Char *)s,
+ (int)((XML_Char *)next - (XML_Char *)s));
+ } else if (parser->m_defaultHandler)
+ reportDefault(parser, enc, s, next);
+ } break;
case XML_TOK_INVALID:
*eventPP = next;
return XML_ERROR_INVALID_TOKEN;
* statistics.
*
* LCOV_EXCL_START
- */
+ */
*eventPP = next;
return XML_ERROR_UNEXPECTED_STATE;
/* LCOV_EXCL_STOP */
return XML_ERROR_NONE;
case XML_FINISHED:
return XML_ERROR_ABORTED;
- default: ;
+ default:;
}
}
/* not reached */
the whole file is parsed with one call.
*/
static enum XML_Error PTRCALL
-ignoreSectionProcessor(XML_Parser parser,
- const char *start,
- const char *end,
- const char **endPtr)
-{
- enum XML_Error result = doIgnoreSection(parser, parser->m_encoding, &start, end,
- endPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
+ignoreSectionProcessor(XML_Parser parser, const char *start, const char *end,
+ const char **endPtr) {
+ enum XML_Error result
+ = doIgnoreSection(parser, parser->m_encoding, &start, end, endPtr,
+ (XML_Bool)! parser->m_parsingStatus.finalBuffer);
if (result != XML_ERROR_NONE)
return result;
if (start) {
if the section is not yet closed.
*/
static enum XML_Error
-doIgnoreSection(XML_Parser parser,
- const ENCODING *enc,
- const char **startPtr,
- const char *end,
- const char **nextPtr,
- XML_Bool haveMore)
-{
+doIgnoreSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
+ const char *end, const char **nextPtr, XML_Bool haveMore) {
const char *next;
int tok;
const char *s = *startPtr;
eventPP = &parser->m_eventPtr;
*eventPP = s;
eventEndPP = &parser->m_eventEndPtr;
- }
- else {
+ } else {
/* It's not entirely clear, but it seems the following two lines
* of code cannot be executed. The only occasions on which 'enc'
* is not 'encoding' are when this function is called
#endif /* XML_DTD */
static enum XML_Error
-initializeEncoding(XML_Parser parser)
-{
+initializeEncoding(XML_Parser parser) {
const char *s;
#ifdef XML_UNICODE
char encodingBuf[128];
/* See comments abount `protoclEncodingName` in parserInit() */
- if (!parser->m_protocolEncodingName)
+ if (! parser->m_protocolEncodingName)
s = NULL;
else {
int i;
#else
s = parser->m_protocolEncodingName;
#endif
- if ((parser->m_ns ? XmlInitEncodingNS : XmlInitEncoding)(&parser->m_initEncoding, &parser->m_encoding, s))
+ if ((parser->m_ns ? XmlInitEncodingNS : XmlInitEncoding)(
+ &parser->m_initEncoding, &parser->m_encoding, s))
return XML_ERROR_NONE;
return handleUnknownEncoding(parser, parser->m_protocolEncodingName);
}
static enum XML_Error
-processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
- const char *s, const char *next)
-{
+processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *s,
+ const char *next) {
const char *encodingName = NULL;
const XML_Char *storedEncName = NULL;
const ENCODING *newEncoding = NULL;
const char *versionend;
const XML_Char *storedversion = NULL;
int standalone = -1;
- if (!(parser->m_ns
- ? XmlParseXmlDeclNS
- : XmlParseXmlDecl)(isGeneralTextEntity,
- parser->m_encoding,
- s,
- next,
- &parser->m_eventPtr,
- &version,
- &versionend,
- &encodingName,
- &newEncoding,
- &standalone)) {
+ if (! (parser->m_ns ? XmlParseXmlDeclNS : XmlParseXmlDecl)(
+ isGeneralTextEntity, parser->m_encoding, s, next, &parser->m_eventPtr,
+ &version, &versionend, &encodingName, &newEncoding, &standalone)) {
if (isGeneralTextEntity)
return XML_ERROR_TEXT_DECL;
else
return XML_ERROR_XML_DECL;
}
- if (!isGeneralTextEntity && standalone == 1) {
+ if (! isGeneralTextEntity && standalone == 1) {
parser->m_dtd->standalone = XML_TRUE;
#ifdef XML_DTD
- if (parser->m_paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
+ if (parser->m_paramEntityParsing
+ == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
#endif /* XML_DTD */
}
if (parser->m_xmlDeclHandler) {
if (encodingName != NULL) {
- storedEncName = poolStoreString(&parser->m_temp2Pool,
- parser->m_encoding,
- encodingName,
- encodingName
- + XmlNameLength(parser->m_encoding, encodingName));
- if (!storedEncName)
- return XML_ERROR_NO_MEMORY;
+ storedEncName = poolStoreString(
+ &parser->m_temp2Pool, parser->m_encoding, encodingName,
+ encodingName + XmlNameLength(parser->m_encoding, encodingName));
+ if (! storedEncName)
+ return XML_ERROR_NO_MEMORY;
poolFinish(&parser->m_temp2Pool);
}
if (version) {
- storedversion = poolStoreString(&parser->m_temp2Pool,
- parser->m_encoding,
- version,
- versionend - parser->m_encoding->minBytesPerChar);
- if (!storedversion)
+ storedversion
+ = poolStoreString(&parser->m_temp2Pool, parser->m_encoding, version,
+ versionend - parser->m_encoding->minBytesPerChar);
+ if (! storedversion)
return XML_ERROR_NO_MEMORY;
}
- parser->m_xmlDeclHandler(parser->m_handlerArg, storedversion, storedEncName, standalone);
- }
- else if (parser->m_defaultHandler)
+ parser->m_xmlDeclHandler(parser->m_handlerArg, storedversion, storedEncName,
+ standalone);
+ } else if (parser->m_defaultHandler)
reportDefault(parser, parser->m_encoding, s, next);
if (parser->m_protocolEncodingName == NULL) {
if (newEncoding) {
* this is UTF-16, is it the same endianness?
*/
if (newEncoding->minBytesPerChar != parser->m_encoding->minBytesPerChar
- || (newEncoding->minBytesPerChar == 2 &&
- newEncoding != parser->m_encoding)) {
+ || (newEncoding->minBytesPerChar == 2
+ && newEncoding != parser->m_encoding)) {
parser->m_eventPtr = encodingName;
return XML_ERROR_INCORRECT_ENCODING;
}
parser->m_encoding = newEncoding;
- }
- else if (encodingName) {
+ } else if (encodingName) {
enum XML_Error result;
- if (!storedEncName) {
+ if (! storedEncName) {
storedEncName = poolStoreString(
- &parser->m_temp2Pool, parser->m_encoding, encodingName,
- encodingName + XmlNameLength(parser->m_encoding, encodingName));
- if (!storedEncName)
+ &parser->m_temp2Pool, parser->m_encoding, encodingName,
+ encodingName + XmlNameLength(parser->m_encoding, encodingName));
+ if (! storedEncName)
return XML_ERROR_NO_MEMORY;
}
result = handleUnknownEncoding(parser, storedEncName);
}
static enum XML_Error
-handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
-{
+handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName) {
if (parser->m_unknownEncodingHandler) {
XML_Encoding info;
int i;
info.convert = NULL;
info.data = NULL;
info.release = NULL;
- if (parser->m_unknownEncodingHandler(parser->m_unknownEncodingHandlerData, encodingName,
- &info)) {
+ if (parser->m_unknownEncodingHandler(parser->m_unknownEncodingHandlerData,
+ encodingName, &info)) {
ENCODING *enc;
parser->m_unknownEncodingMem = MALLOC(parser, XmlSizeOfUnknownEncoding());
- if (!parser->m_unknownEncodingMem) {
+ if (! parser->m_unknownEncodingMem) {
if (info.release)
info.release(info.data);
return XML_ERROR_NO_MEMORY;
}
- enc = (parser->m_ns
- ? XmlInitUnknownEncodingNS
- : XmlInitUnknownEncoding)(parser->m_unknownEncodingMem,
- info.map,
- info.convert,
- info.data);
+ enc = (parser->m_ns ? XmlInitUnknownEncodingNS : XmlInitUnknownEncoding)(
+ parser->m_unknownEncodingMem, info.map, info.convert, info.data);
if (enc) {
parser->m_unknownEncodingData = info.data;
parser->m_unknownEncodingRelease = info.release;
}
static enum XML_Error PTRCALL
-prologInitProcessor(XML_Parser parser,
- const char *s,
- const char *end,
- const char **nextPtr)
-{
+prologInitProcessor(XML_Parser parser, const char *s, const char *end,
+ const char **nextPtr) {
enum XML_Error result = initializeEncoding(parser);
if (result != XML_ERROR_NONE)
return result;
#ifdef XML_DTD
static enum XML_Error PTRCALL
-externalParEntInitProcessor(XML_Parser parser,
- const char *s,
- const char *end,
- const char **nextPtr)
-{
+externalParEntInitProcessor(XML_Parser parser, const char *s, const char *end,
+ const char **nextPtr) {
enum XML_Error result = initializeEncoding(parser);
if (result != XML_ERROR_NONE)
return result;
if (parser->m_prologState.inEntityValue) {
parser->m_processor = entityValueInitProcessor;
return entityValueInitProcessor(parser, s, end, nextPtr);
- }
- else {
+ } else {
parser->m_processor = externalParEntProcessor;
return externalParEntProcessor(parser, s, end, nextPtr);
}
}
static enum XML_Error PTRCALL
-entityValueInitProcessor(XML_Parser parser,
- const char *s,
- const char *end,
- const char **nextPtr)
-{
+entityValueInitProcessor(XML_Parser parser, const char *s, const char *end,
+ const char **nextPtr) {
int tok;
const char *start = s;
const char *next = start;
tok = XmlPrologTok(parser->m_encoding, start, end, &next);
parser->m_eventEndPtr = next;
if (tok <= 0) {
- if (!parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
+ if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
*nextPtr = s;
return XML_ERROR_NONE;
}
return XML_ERROR_UNCLOSED_TOKEN;
case XML_TOK_PARTIAL_CHAR:
return XML_ERROR_PARTIAL_CHAR;
- case XML_TOK_NONE: /* start == end */
+ case XML_TOK_NONE: /* start == end */
default:
break;
}
/* found end of entity value - can store it now */
return storeEntityValue(parser, parser->m_encoding, s, end);
- }
- else if (tok == XML_TOK_XML_DECL) {
+ } else if (tok == XML_TOK_XML_DECL) {
enum XML_Error result;
result = processXmlDecl(parser, 0, start, next);
if (result != XML_ERROR_NONE)
return result;
- /* At this point, m_parsingStatus.parsing cannot be XML_SUSPENDED. For that
- * to happen, a parameter entity parsing handler must have
- * attempted to suspend the parser, which fails and raises an
- * error. The parser can be aborted, but can't be suspended.
+ /* At this point, m_parsingStatus.parsing cannot be XML_SUSPENDED. For
+ * that to happen, a parameter entity parsing handler must have attempted
+ * to suspend the parser, which fails and raises an error. The parser can
+ * be aborted, but can't be suspended.
*/
if (parser->m_parsingStatus.parsing == XML_FINISHED)
return XML_ERROR_ABORTED;
then, when this routine is entered the next time, XmlPrologTok will
return XML_TOK_INVALID, since the BOM is still in the buffer
*/
- else if (tok == XML_TOK_BOM && next == end && !parser->m_parsingStatus.finalBuffer) {
+ else if (tok == XML_TOK_BOM && next == end
+ && ! parser->m_parsingStatus.finalBuffer) {
*nextPtr = next;
return XML_ERROR_NONE;
}
}
static enum XML_Error PTRCALL
-externalParEntProcessor(XML_Parser parser,
- const char *s,
- const char *end,
- const char **nextPtr)
-{
+externalParEntProcessor(XML_Parser parser, const char *s, const char *end,
+ const char **nextPtr) {
const char *next = s;
int tok;
tok = XmlPrologTok(parser->m_encoding, s, end, &next);
if (tok <= 0) {
- if (!parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
+ if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
*nextPtr = s;
return XML_ERROR_NONE;
}
return XML_ERROR_UNCLOSED_TOKEN;
case XML_TOK_PARTIAL_CHAR:
return XML_ERROR_PARTIAL_CHAR;
- case XML_TOK_NONE: /* start == end */
+ case XML_TOK_NONE: /* start == end */
default:
break;
}
}
parser->m_processor = prologProcessor;
- return doProlog(parser, parser->m_encoding, s, end, tok, next,
- nextPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
+ return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
+ (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE);
}
static enum XML_Error PTRCALL
-entityValueProcessor(XML_Parser parser,
- const char *s,
- const char *end,
- const char **nextPtr)
-{
+entityValueProcessor(XML_Parser parser, const char *s, const char *end,
+ const char **nextPtr) {
const char *start = s;
const char *next = s;
const ENCODING *enc = parser->m_encoding;
for (;;) {
tok = XmlPrologTok(enc, start, end, &next);
if (tok <= 0) {
- if (!parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
+ if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
*nextPtr = s;
return XML_ERROR_NONE;
}
return XML_ERROR_UNCLOSED_TOKEN;
case XML_TOK_PARTIAL_CHAR:
return XML_ERROR_PARTIAL_CHAR;
- case XML_TOK_NONE: /* start == end */
+ case XML_TOK_NONE: /* start == end */
default:
break;
}
#endif /* XML_DTD */
static enum XML_Error PTRCALL
-prologProcessor(XML_Parser parser,
- const char *s,
- const char *end,
- const char **nextPtr)
-{
+prologProcessor(XML_Parser parser, const char *s, const char *end,
+ const char **nextPtr) {
const char *next = s;
int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
- return doProlog(parser, parser->m_encoding, s, end, tok, next,
- nextPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
+ return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
+ (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE);
}
static enum XML_Error
-doProlog(XML_Parser parser,
- const ENCODING *enc,
- const char *s,
- const char *end,
- int tok,
- const char *next,
- const char **nextPtr,
- XML_Bool haveMore)
-{
+doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
+ int tok, const char *next, const char **nextPtr, XML_Bool haveMore,
+ XML_Bool allowClosingDoctype) {
#ifdef XML_DTD
- static const XML_Char externalSubsetName[] = { ASCII_HASH , '\0' };
+ static const XML_Char externalSubsetName[] = {ASCII_HASH, '\0'};
#endif /* XML_DTD */
- static const XML_Char atypeCDATA[] =
- { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
- static const XML_Char atypeID[] = { ASCII_I, ASCII_D, '\0' };
- static const XML_Char atypeIDREF[] =
- { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' };
- static const XML_Char atypeIDREFS[] =
- { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' };
- static const XML_Char atypeENTITY[] =
- { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' };
- static const XML_Char atypeENTITIES[] = { ASCII_E, ASCII_N,
- ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0' };
- static const XML_Char atypeNMTOKEN[] = {
- ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' };
- static const XML_Char atypeNMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T,
- ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0' };
- static const XML_Char notationPrefix[] = { ASCII_N, ASCII_O, ASCII_T,
- ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0' };
- static const XML_Char enumValueSep[] = { ASCII_PIPE, '\0' };
- static const XML_Char enumValueStart[] = { ASCII_LPAREN, '\0' };
+ static const XML_Char atypeCDATA[]
+ = {ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0'};
+ static const XML_Char atypeID[] = {ASCII_I, ASCII_D, '\0'};
+ static const XML_Char atypeIDREF[]
+ = {ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0'};
+ static const XML_Char atypeIDREFS[]
+ = {ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0'};
+ static const XML_Char atypeENTITY[]
+ = {ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0'};
+ static const XML_Char atypeENTITIES[]
+ = {ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T,
+ ASCII_I, ASCII_E, ASCII_S, '\0'};
+ static const XML_Char atypeNMTOKEN[]
+ = {ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0'};
+ static const XML_Char atypeNMTOKENS[]
+ = {ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K,
+ ASCII_E, ASCII_N, ASCII_S, '\0'};
+ static const XML_Char notationPrefix[]
+ = {ASCII_N, ASCII_O, ASCII_T, ASCII_A, ASCII_T,
+ ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0'};
+ static const XML_Char enumValueSep[] = {ASCII_PIPE, '\0'};
+ static const XML_Char enumValueStart[] = {ASCII_LPAREN, '\0'};
/* save one level of indirection */
- DTD * const dtd = parser->m_dtd;
+ DTD *const dtd = parser->m_dtd;
const char **eventPP;
const char **eventEndPP;
if (enc == parser->m_encoding) {
eventPP = &parser->m_eventPtr;
eventEndPP = &parser->m_eventEndPtr;
- }
- else {
+ } else {
eventPP = &(parser->m_openInternalEntities->internalEventPtr);
eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr);
}
case XML_TOK_NONE:
#ifdef XML_DTD
/* for internal PE NOT referenced between declarations */
- if (enc != parser->m_encoding && !parser->m_openInternalEntities->betweenDecl) {
+ if (enc != parser->m_encoding
+ && ! parser->m_openInternalEntities->betweenDecl) {
*nextPtr = s;
return XML_ERROR_NONE;
}
}
role = XmlTokenRole(&parser->m_prologState, tok, s, next, enc);
switch (role) {
- case XML_ROLE_XML_DECL:
- {
- enum XML_Error result = processXmlDecl(parser, 0, s, next);
- if (result != XML_ERROR_NONE)
- return result;
- enc = parser->m_encoding;
- handleDefault = XML_FALSE;
- }
- break;
+ case XML_ROLE_XML_DECL: {
+ enum XML_Error result = processXmlDecl(parser, 0, s, next);
+ if (result != XML_ERROR_NONE)
+ return result;
+ enc = parser->m_encoding;
+ handleDefault = XML_FALSE;
+ } break;
case XML_ROLE_DOCTYPE_NAME:
if (parser->m_startDoctypeDeclHandler) {
- parser->m_doctypeName = poolStoreString(&parser->m_tempPool, enc, s, next);
- if (!parser->m_doctypeName)
+ parser->m_doctypeName
+ = poolStoreString(&parser->m_tempPool, enc, s, next);
+ if (! parser->m_doctypeName)
return XML_ERROR_NO_MEMORY;
poolFinish(&parser->m_tempPool);
parser->m_doctypePubid = NULL;
break;
case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
if (parser->m_startDoctypeDeclHandler) {
- parser->m_startDoctypeDeclHandler(parser->m_handlerArg, parser->m_doctypeName, parser->m_doctypeSysid,
- parser->m_doctypePubid, 1);
+ parser->m_startDoctypeDeclHandler(
+ parser->m_handlerArg, parser->m_doctypeName, parser->m_doctypeSysid,
+ parser->m_doctypePubid, 1);
parser->m_doctypeName = NULL;
poolClear(&parser->m_tempPool);
handleDefault = XML_FALSE;
}
break;
#ifdef XML_DTD
- case XML_ROLE_TEXT_DECL:
- {
- enum XML_Error result = processXmlDecl(parser, 1, s, next);
- if (result != XML_ERROR_NONE)
- return result;
- enc = parser->m_encoding;
- handleDefault = XML_FALSE;
- }
- break;
+ case XML_ROLE_TEXT_DECL: {
+ enum XML_Error result = processXmlDecl(parser, 1, s, next);
+ if (result != XML_ERROR_NONE)
+ return result;
+ enc = parser->m_encoding;
+ handleDefault = XML_FALSE;
+ } break;
#endif /* XML_DTD */
case XML_ROLE_DOCTYPE_PUBLIC_ID:
#ifdef XML_DTD
parser->m_useForeignDTD = XML_FALSE;
- parser->m_declEntity = (ENTITY *)lookup(parser,
- &dtd->paramEntities,
- externalSubsetName,
- sizeof(ENTITY));
- if (!parser->m_declEntity)
+ parser->m_declEntity = (ENTITY *)lookup(
+ parser, &dtd->paramEntities, externalSubsetName, sizeof(ENTITY));
+ if (! parser->m_declEntity)
return XML_ERROR_NO_MEMORY;
#endif /* XML_DTD */
dtd->hasParamEntityRefs = XML_TRUE;
if (parser->m_startDoctypeDeclHandler) {
XML_Char *pubId;
- if (!XmlIsPublicId(enc, s, next, eventPP))
+ if (! XmlIsPublicId(enc, s, next, eventPP))
return XML_ERROR_PUBLICID;
pubId = poolStoreString(&parser->m_tempPool, enc,
s + enc->minBytesPerChar,
next - enc->minBytesPerChar);
- if (!pubId)
+ if (! pubId)
return XML_ERROR_NO_MEMORY;
normalizePublicId(pubId);
poolFinish(&parser->m_tempPool);
}
/* fall through */
case XML_ROLE_ENTITY_PUBLIC_ID:
- if (!XmlIsPublicId(enc, s, next, eventPP))
+ if (! XmlIsPublicId(enc, s, next, eventPP))
return XML_ERROR_PUBLICID;
alreadyChecked:
if (dtd->keepProcessing && parser->m_declEntity) {
- XML_Char *tem = poolStoreString(&dtd->pool,
- enc,
- s + enc->minBytesPerChar,
- next - enc->minBytesPerChar);
- if (!tem)
+ XML_Char *tem
+ = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (! tem)
return XML_ERROR_NO_MEMORY;
normalizePublicId(tem);
parser->m_declEntity->publicId = tem;
}
break;
case XML_ROLE_DOCTYPE_CLOSE:
+ if (allowClosingDoctype != XML_TRUE) {
+ /* Must not close doctype from within expanded parameter entities */
+ return XML_ERROR_INVALID_TOKEN;
+ }
+
if (parser->m_doctypeName) {
- parser->m_startDoctypeDeclHandler(parser->m_handlerArg, parser->m_doctypeName,
- parser->m_doctypeSysid, parser->m_doctypePubid, 0);
+ parser->m_startDoctypeDeclHandler(
+ parser->m_handlerArg, parser->m_doctypeName, parser->m_doctypeSysid,
+ parser->m_doctypePubid, 0);
poolClear(&parser->m_tempPool);
handleDefault = XML_FALSE;
}
if (parser->m_doctypeSysid || parser->m_useForeignDTD) {
XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
dtd->hasParamEntityRefs = XML_TRUE;
- if (parser->m_paramEntityParsing && parser->m_externalEntityRefHandler) {
- ENTITY *entity = (ENTITY *)lookup(parser,
- &dtd->paramEntities,
- externalSubsetName,
- sizeof(ENTITY));
- if (!entity) {
+ if (parser->m_paramEntityParsing
+ && parser->m_externalEntityRefHandler) {
+ ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
+ externalSubsetName, sizeof(ENTITY));
+ if (! entity) {
/* The external subset name "#" will have already been
* inserted into the hash table at the start of the
* external entity parsing, so no allocation will happen
if (parser->m_useForeignDTD)
entity->base = parser->m_curBase;
dtd->paramEntityRead = XML_FALSE;
- if (!parser->m_externalEntityRefHandler(parser->m_externalEntityRefHandlerArg,
- 0,
- entity->base,
- entity->systemId,
- entity->publicId))
+ if (! parser->m_externalEntityRefHandler(
+ parser->m_externalEntityRefHandlerArg, 0, entity->base,
+ entity->systemId, entity->publicId))
return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
if (dtd->paramEntityRead) {
- if (!dtd->standalone &&
- parser->m_notStandaloneHandler &&
- !parser->m_notStandaloneHandler(parser->m_handlerArg))
+ if (! dtd->standalone && parser->m_notStandaloneHandler
+ && ! parser->m_notStandaloneHandler(parser->m_handlerArg))
return XML_ERROR_NOT_STANDALONE;
}
/* if we didn't read the foreign DTD then this means that there
is no external subset and we must reset dtd->hasParamEntityRefs
*/
- else if (!parser->m_doctypeSysid)
+ else if (! parser->m_doctypeSysid)
dtd->hasParamEntityRefs = hadParamEntityRefs;
/* end of DTD - no need to update dtd->keepProcessing */
}
if (parser->m_useForeignDTD) {
XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs;
dtd->hasParamEntityRefs = XML_TRUE;
- if (parser->m_paramEntityParsing && parser->m_externalEntityRefHandler) {
+ if (parser->m_paramEntityParsing
+ && parser->m_externalEntityRefHandler) {
ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities,
- externalSubsetName,
- sizeof(ENTITY));
- if (!entity)
+ externalSubsetName, sizeof(ENTITY));
+ if (! entity)
return XML_ERROR_NO_MEMORY;
entity->base = parser->m_curBase;
dtd->paramEntityRead = XML_FALSE;
- if (!parser->m_externalEntityRefHandler(parser->m_externalEntityRefHandlerArg,
- 0,
- entity->base,
- entity->systemId,
- entity->publicId))
+ if (! parser->m_externalEntityRefHandler(
+ parser->m_externalEntityRefHandlerArg, 0, entity->base,
+ entity->systemId, entity->publicId))
return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
if (dtd->paramEntityRead) {
- if (!dtd->standalone &&
- parser->m_notStandaloneHandler &&
- !parser->m_notStandaloneHandler(parser->m_handlerArg))
+ if (! dtd->standalone && parser->m_notStandaloneHandler
+ && ! parser->m_notStandaloneHandler(parser->m_handlerArg))
return XML_ERROR_NOT_STANDALONE;
}
/* if we didn't read the foreign DTD then this means that there
return contentProcessor(parser, s, end, nextPtr);
case XML_ROLE_ATTLIST_ELEMENT_NAME:
parser->m_declElementType = getElementType(parser, enc, s, next);
- if (!parser->m_declElementType)
+ if (! parser->m_declElementType)
return XML_ERROR_NO_MEMORY;
goto checkAttListDeclHandler;
case XML_ROLE_ATTRIBUTE_NAME:
parser->m_declAttributeId = getAttributeId(parser, enc, s, next);
- if (!parser->m_declAttributeId)
+ if (! parser->m_declAttributeId)
return XML_ERROR_NO_MEMORY;
parser->m_declAttributeIsCdata = XML_FALSE;
parser->m_declAttributeType = NULL;
const XML_Char *prefix;
if (parser->m_declAttributeType) {
prefix = enumValueSep;
+ } else {
+ prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE ? notationPrefix
+ : enumValueStart);
}
- else {
- prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE
- ? notationPrefix
- : enumValueStart);
- }
- if (!poolAppendString(&parser->m_tempPool, prefix))
+ if (! poolAppendString(&parser->m_tempPool, prefix))
return XML_ERROR_NO_MEMORY;
- if (!poolAppend(&parser->m_tempPool, enc, s, next))
+ if (! poolAppend(&parser->m_tempPool, enc, s, next))
return XML_ERROR_NO_MEMORY;
parser->m_declAttributeType = parser->m_tempPool.start;
handleDefault = XML_FALSE;
case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
if (dtd->keepProcessing) {
- if (!defineAttribute(parser->m_declElementType, parser->m_declAttributeId,
- parser->m_declAttributeIsCdata, parser->m_declAttributeIsId,
- 0, parser))
+ if (! defineAttribute(parser->m_declElementType,
+ parser->m_declAttributeId,
+ parser->m_declAttributeIsCdata,
+ parser->m_declAttributeIsId, 0, parser))
return XML_ERROR_NO_MEMORY;
if (parser->m_attlistDeclHandler && parser->m_declAttributeType) {
if (*parser->m_declAttributeType == XML_T(ASCII_LPAREN)
|| (*parser->m_declAttributeType == XML_T(ASCII_N)
&& parser->m_declAttributeType[1] == XML_T(ASCII_O))) {
/* Enumerated or Notation type */
- if (!poolAppendChar(&parser->m_tempPool, XML_T(ASCII_RPAREN))
- || !poolAppendChar(&parser->m_tempPool, XML_T('\0')))
+ if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_RPAREN))
+ || ! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
return XML_ERROR_NO_MEMORY;
parser->m_declAttributeType = parser->m_tempPool.start;
poolFinish(&parser->m_tempPool);
}
*eventEndPP = s;
- parser->m_attlistDeclHandler(parser->m_handlerArg, parser->m_declElementType->name,
- parser->m_declAttributeId->name, parser->m_declAttributeType,
- 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
+ parser->m_attlistDeclHandler(
+ parser->m_handlerArg, parser->m_declElementType->name,
+ parser->m_declAttributeId->name, parser->m_declAttributeType, 0,
+ role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
poolClear(&parser->m_tempPool);
handleDefault = XML_FALSE;
}
case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
if (dtd->keepProcessing) {
const XML_Char *attVal;
- enum XML_Error result =
- storeAttributeValue(parser, enc, parser->m_declAttributeIsCdata,
- s + enc->minBytesPerChar,
- next - enc->minBytesPerChar,
- &dtd->pool);
+ enum XML_Error result = storeAttributeValue(
+ parser, enc, parser->m_declAttributeIsCdata,
+ s + enc->minBytesPerChar, next - enc->minBytesPerChar, &dtd->pool);
if (result)
return result;
attVal = poolStart(&dtd->pool);
poolFinish(&dtd->pool);
/* ID attributes aren't allowed to have a default */
- if (!defineAttribute(parser->m_declElementType, parser->m_declAttributeId,
- parser->m_declAttributeIsCdata, XML_FALSE, attVal, parser))
+ if (! defineAttribute(
+ parser->m_declElementType, parser->m_declAttributeId,
+ parser->m_declAttributeIsCdata, XML_FALSE, attVal, parser))
return XML_ERROR_NO_MEMORY;
if (parser->m_attlistDeclHandler && parser->m_declAttributeType) {
if (*parser->m_declAttributeType == XML_T(ASCII_LPAREN)
|| (*parser->m_declAttributeType == XML_T(ASCII_N)
&& parser->m_declAttributeType[1] == XML_T(ASCII_O))) {
/* Enumerated or Notation type */
- if (!poolAppendChar(&parser->m_tempPool, XML_T(ASCII_RPAREN))
- || !poolAppendChar(&parser->m_tempPool, XML_T('\0')))
+ if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_RPAREN))
+ || ! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
return XML_ERROR_NO_MEMORY;
parser->m_declAttributeType = parser->m_tempPool.start;
poolFinish(&parser->m_tempPool);
}
*eventEndPP = s;
- parser->m_attlistDeclHandler(parser->m_handlerArg, parser->m_declElementType->name,
- parser->m_declAttributeId->name, parser->m_declAttributeType,
- attVal,
- role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
+ parser->m_attlistDeclHandler(
+ parser->m_handlerArg, parser->m_declElementType->name,
+ parser->m_declAttributeId->name, parser->m_declAttributeType,
+ attVal, role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
poolClear(&parser->m_tempPool);
handleDefault = XML_FALSE;
}
break;
case XML_ROLE_ENTITY_VALUE:
if (dtd->keepProcessing) {
- enum XML_Error result = storeEntityValue(parser, enc,
- s + enc->minBytesPerChar,
- next - enc->minBytesPerChar);
+ enum XML_Error result = storeEntityValue(
+ parser, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar);
if (parser->m_declEntity) {
parser->m_declEntity->textPtr = poolStart(&dtd->entityValuePool);
- parser->m_declEntity->textLen = (int)(poolLength(&dtd->entityValuePool));
+ parser->m_declEntity->textLen
+ = (int)(poolLength(&dtd->entityValuePool));
poolFinish(&dtd->entityValuePool);
if (parser->m_entityDeclHandler) {
*eventEndPP = s;
- parser->m_entityDeclHandler(parser->m_handlerArg,
- parser->m_declEntity->name,
- parser->m_declEntity->is_param,
- parser->m_declEntity->textPtr,
- parser->m_declEntity->textLen,
- parser->m_curBase, 0, 0, 0);
+ parser->m_entityDeclHandler(
+ parser->m_handlerArg, parser->m_declEntity->name,
+ parser->m_declEntity->is_param, parser->m_declEntity->textPtr,
+ parser->m_declEntity->textLen, parser->m_curBase, 0, 0, 0);
handleDefault = XML_FALSE;
}
- }
- else
+ } else
poolDiscard(&dtd->entityValuePool);
if (result != XML_ERROR_NONE)
return result;
dtd->hasParamEntityRefs = XML_TRUE;
if (parser->m_startDoctypeDeclHandler) {
parser->m_doctypeSysid = poolStoreString(&parser->m_tempPool, enc,
- s + enc->minBytesPerChar,
- next - enc->minBytesPerChar);
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
if (parser->m_doctypeSysid == NULL)
return XML_ERROR_NO_MEMORY;
poolFinish(&parser->m_tempPool);
for the case where no parser->m_startDoctypeDeclHandler is set */
parser->m_doctypeSysid = externalSubsetName;
#endif /* XML_DTD */
- if (!dtd->standalone
+ if (! dtd->standalone
#ifdef XML_DTD
- && !parser->m_paramEntityParsing
+ && ! parser->m_paramEntityParsing
#endif /* XML_DTD */
&& parser->m_notStandaloneHandler
- && !parser->m_notStandaloneHandler(parser->m_handlerArg))
+ && ! parser->m_notStandaloneHandler(parser->m_handlerArg))
return XML_ERROR_NOT_STANDALONE;
#ifndef XML_DTD
break;
-#else /* XML_DTD */
- if (!parser->m_declEntity) {
- parser->m_declEntity = (ENTITY *)lookup(parser,
- &dtd->paramEntities,
- externalSubsetName,
- sizeof(ENTITY));
- if (!parser->m_declEntity)
+#else /* XML_DTD */
+ if (! parser->m_declEntity) {
+ parser->m_declEntity = (ENTITY *)lookup(
+ parser, &dtd->paramEntities, externalSubsetName, sizeof(ENTITY));
+ if (! parser->m_declEntity)
return XML_ERROR_NO_MEMORY;
parser->m_declEntity->publicId = NULL;
}
/* fall through */
case XML_ROLE_ENTITY_SYSTEM_ID:
if (dtd->keepProcessing && parser->m_declEntity) {
- parser->m_declEntity->systemId = poolStoreString(&dtd->pool, enc,
- s + enc->minBytesPerChar,
- next - enc->minBytesPerChar);
- if (!parser->m_declEntity->systemId)
+ parser->m_declEntity->systemId
+ = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (! parser->m_declEntity->systemId)
return XML_ERROR_NO_MEMORY;
parser->m_declEntity->base = parser->m_curBase;
poolFinish(&dtd->pool);
}
break;
case XML_ROLE_ENTITY_COMPLETE:
- if (dtd->keepProcessing && parser->m_declEntity && parser->m_entityDeclHandler) {
+ if (dtd->keepProcessing && parser->m_declEntity
+ && parser->m_entityDeclHandler) {
*eventEndPP = s;
- parser->m_entityDeclHandler(parser->m_handlerArg,
- parser->m_declEntity->name,
- parser->m_declEntity->is_param,
- 0,0,
- parser->m_declEntity->base,
- parser->m_declEntity->systemId,
- parser->m_declEntity->publicId,
- 0);
+ parser->m_entityDeclHandler(
+ parser->m_handlerArg, parser->m_declEntity->name,
+ parser->m_declEntity->is_param, 0, 0, parser->m_declEntity->base,
+ parser->m_declEntity->systemId, parser->m_declEntity->publicId, 0);
handleDefault = XML_FALSE;
}
break;
case XML_ROLE_ENTITY_NOTATION_NAME:
if (dtd->keepProcessing && parser->m_declEntity) {
- parser->m_declEntity->notation = poolStoreString(&dtd->pool, enc, s, next);
- if (!parser->m_declEntity->notation)
+ parser->m_declEntity->notation
+ = poolStoreString(&dtd->pool, enc, s, next);
+ if (! parser->m_declEntity->notation)
return XML_ERROR_NO_MEMORY;
poolFinish(&dtd->pool);
if (parser->m_unparsedEntityDeclHandler) {
*eventEndPP = s;
- parser->m_unparsedEntityDeclHandler(parser->m_handlerArg,
- parser->m_declEntity->name,
- parser->m_declEntity->base,
- parser->m_declEntity->systemId,
- parser->m_declEntity->publicId,
- parser->m_declEntity->notation);
+ parser->m_unparsedEntityDeclHandler(
+ parser->m_handlerArg, parser->m_declEntity->name,
+ parser->m_declEntity->base, parser->m_declEntity->systemId,
+ parser->m_declEntity->publicId, parser->m_declEntity->notation);
handleDefault = XML_FALSE;
- }
- else if (parser->m_entityDeclHandler) {
+ } else if (parser->m_entityDeclHandler) {
*eventEndPP = s;
- parser->m_entityDeclHandler(parser->m_handlerArg,
- parser->m_declEntity->name,
- 0,0,0,
- parser->m_declEntity->base,
- parser->m_declEntity->systemId,
- parser->m_declEntity->publicId,
- parser->m_declEntity->notation);
+ parser->m_entityDeclHandler(
+ parser->m_handlerArg, parser->m_declEntity->name, 0, 0, 0,
+ parser->m_declEntity->base, parser->m_declEntity->systemId,
+ parser->m_declEntity->publicId, parser->m_declEntity->notation);
handleDefault = XML_FALSE;
}
}
break;
- case XML_ROLE_GENERAL_ENTITY_NAME:
- {
- if (XmlPredefinedEntityName(enc, s, next)) {
- parser->m_declEntity = NULL;
- break;
- }
- if (dtd->keepProcessing) {
- const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
- if (!name)
- return XML_ERROR_NO_MEMORY;
- parser->m_declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities, name,
- sizeof(ENTITY));
- if (!parser->m_declEntity)
- return XML_ERROR_NO_MEMORY;
- if (parser->m_declEntity->name != name) {
- poolDiscard(&dtd->pool);
- parser->m_declEntity = NULL;
- }
- else {
- poolFinish(&dtd->pool);
- parser->m_declEntity->publicId = NULL;
- parser->m_declEntity->is_param = XML_FALSE;
- /* if we have a parent parser or are reading an internal parameter
- entity, then the entity declaration is not considered "internal"
- */
- parser->m_declEntity->is_internal = !(parser->m_parentParser || parser->m_openInternalEntities);
- if (parser->m_entityDeclHandler)
- handleDefault = XML_FALSE;
- }
- }
- else {
+ case XML_ROLE_GENERAL_ENTITY_NAME: {
+ if (XmlPredefinedEntityName(enc, s, next)) {
+ parser->m_declEntity = NULL;
+ break;
+ }
+ if (dtd->keepProcessing) {
+ const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
+ if (! name)
+ return XML_ERROR_NO_MEMORY;
+ parser->m_declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities,
+ name, sizeof(ENTITY));
+ if (! parser->m_declEntity)
+ return XML_ERROR_NO_MEMORY;
+ if (parser->m_declEntity->name != name) {
poolDiscard(&dtd->pool);
parser->m_declEntity = NULL;
+ } else {
+ poolFinish(&dtd->pool);
+ parser->m_declEntity->publicId = NULL;
+ parser->m_declEntity->is_param = XML_FALSE;
+ /* if we have a parent parser or are reading an internal parameter
+ entity, then the entity declaration is not considered "internal"
+ */
+ parser->m_declEntity->is_internal
+ = ! (parser->m_parentParser || parser->m_openInternalEntities);
+ if (parser->m_entityDeclHandler)
+ handleDefault = XML_FALSE;
}
+ } else {
+ poolDiscard(&dtd->pool);
+ parser->m_declEntity = NULL;
}
- break;
+ } break;
case XML_ROLE_PARAM_ENTITY_NAME:
#ifdef XML_DTD
if (dtd->keepProcessing) {
const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next);
- if (!name)
+ if (! name)
return XML_ERROR_NO_MEMORY;
parser->m_declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities,
- name, sizeof(ENTITY));
- if (!parser->m_declEntity)
+ name, sizeof(ENTITY));
+ if (! parser->m_declEntity)
return XML_ERROR_NO_MEMORY;
if (parser->m_declEntity->name != name) {
poolDiscard(&dtd->pool);
parser->m_declEntity = NULL;
- }
- else {
+ } else {
poolFinish(&dtd->pool);
parser->m_declEntity->publicId = NULL;
parser->m_declEntity->is_param = XML_TRUE;
/* if we have a parent parser or are reading an internal parameter
entity, then the entity declaration is not considered "internal"
*/
- parser->m_declEntity->is_internal = !(parser->m_parentParser || parser->m_openInternalEntities);
+ parser->m_declEntity->is_internal
+ = ! (parser->m_parentParser || parser->m_openInternalEntities);
if (parser->m_entityDeclHandler)
handleDefault = XML_FALSE;
}
- }
- else {
+ } else {
poolDiscard(&dtd->pool);
parser->m_declEntity = NULL;
}
-#else /* not XML_DTD */
+#else /* not XML_DTD */
parser->m_declEntity = NULL;
#endif /* XML_DTD */
break;
parser->m_declNotationPublicId = NULL;
parser->m_declNotationName = NULL;
if (parser->m_notationDeclHandler) {
- parser->m_declNotationName = poolStoreString(&parser->m_tempPool, enc, s, next);
- if (!parser->m_declNotationName)
+ parser->m_declNotationName
+ = poolStoreString(&parser->m_tempPool, enc, s, next);
+ if (! parser->m_declNotationName)
return XML_ERROR_NO_MEMORY;
poolFinish(&parser->m_tempPool);
handleDefault = XML_FALSE;
}
break;
case XML_ROLE_NOTATION_PUBLIC_ID:
- if (!XmlIsPublicId(enc, s, next, eventPP))
+ if (! XmlIsPublicId(enc, s, next, eventPP))
return XML_ERROR_PUBLICID;
- if (parser->m_declNotationName) { /* means m_notationDeclHandler != NULL */
- XML_Char *tem = poolStoreString(&parser->m_tempPool,
- enc,
+ if (parser
+ ->m_declNotationName) { /* means m_notationDeclHandler != NULL */
+ XML_Char *tem = poolStoreString(&parser->m_tempPool, enc,
s + enc->minBytesPerChar,
next - enc->minBytesPerChar);
- if (!tem)
+ if (! tem)
return XML_ERROR_NO_MEMORY;
normalizePublicId(tem);
parser->m_declNotationPublicId = tem;
break;
case XML_ROLE_NOTATION_SYSTEM_ID:
if (parser->m_declNotationName && parser->m_notationDeclHandler) {
- const XML_Char *systemId
- = poolStoreString(&parser->m_tempPool, enc,
- s + enc->minBytesPerChar,
- next - enc->minBytesPerChar);
- if (!systemId)
+ const XML_Char *systemId = poolStoreString(&parser->m_tempPool, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (! systemId)
return XML_ERROR_NO_MEMORY;
*eventEndPP = s;
- parser->m_notationDeclHandler(parser->m_handlerArg,
- parser->m_declNotationName,
- parser->m_curBase,
- systemId,
- parser->m_declNotationPublicId);
+ parser->m_notationDeclHandler(
+ parser->m_handlerArg, parser->m_declNotationName, parser->m_curBase,
+ systemId, parser->m_declNotationPublicId);
handleDefault = XML_FALSE;
}
poolClear(&parser->m_tempPool);
case XML_ROLE_NOTATION_NO_SYSTEM_ID:
if (parser->m_declNotationPublicId && parser->m_notationDeclHandler) {
*eventEndPP = s;
- parser->m_notationDeclHandler(parser->m_handlerArg,
- parser->m_declNotationName,
- parser->m_curBase,
- 0,
- parser->m_declNotationPublicId);
+ parser->m_notationDeclHandler(
+ parser->m_handlerArg, parser->m_declNotationName, parser->m_curBase,
+ 0, parser->m_declNotationPublicId);
handleDefault = XML_FALSE;
}
poolClear(&parser->m_tempPool);
return XML_ERROR_SYNTAX;
}
#ifdef XML_DTD
- case XML_ROLE_IGNORE_SECT:
- {
- enum XML_Error result;
- if (parser->m_defaultHandler)
- reportDefault(parser, enc, s, next);
- handleDefault = XML_FALSE;
- result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
- if (result != XML_ERROR_NONE)
- return result;
- else if (!next) {
- parser->m_processor = ignoreSectionProcessor;
- return result;
- }
+ case XML_ROLE_IGNORE_SECT: {
+ enum XML_Error result;
+ if (parser->m_defaultHandler)
+ reportDefault(parser, enc, s, next);
+ handleDefault = XML_FALSE;
+ result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore);
+ if (result != XML_ERROR_NONE)
+ return result;
+ else if (! next) {
+ parser->m_processor = ignoreSectionProcessor;
+ return result;
}
- break;
+ } break;
#endif /* XML_DTD */
case XML_ROLE_GROUP_OPEN:
if (parser->m_prologState.level >= parser->m_groupSize) {
if (parser->m_groupSize) {
- char *temp = (char *)REALLOC(parser, parser->m_groupConnector, parser->m_groupSize *= 2);
- if (temp == NULL) {
- parser->m_groupSize /= 2;
- return XML_ERROR_NO_MEMORY;
+ {
+ char *const new_connector = (char *)REALLOC(
+ parser, parser->m_groupConnector, parser->m_groupSize *= 2);
+ if (new_connector == NULL) {
+ parser->m_groupSize /= 2;
+ return XML_ERROR_NO_MEMORY;
+ }
+ parser->m_groupConnector = new_connector;
}
- parser->m_groupConnector = temp;
+
if (dtd->scaffIndex) {
- int *temp = (int *)REALLOC(parser, dtd->scaffIndex,
- parser->m_groupSize * sizeof(int));
- if (temp == NULL)
+ int *const new_scaff_index = (int *)REALLOC(
+ parser, dtd->scaffIndex, parser->m_groupSize * sizeof(int));
+ if (new_scaff_index == NULL)
return XML_ERROR_NO_MEMORY;
- dtd->scaffIndex = temp;
+ dtd->scaffIndex = new_scaff_index;
}
- }
- else {
- parser->m_groupConnector = (char *)MALLOC(parser, parser->m_groupSize = 32);
- if (!parser->m_groupConnector) {
+ } else {
+ parser->m_groupConnector
+ = (char *)MALLOC(parser, parser->m_groupSize = 32);
+ if (! parser->m_groupConnector) {
parser->m_groupSize = 0;
return XML_ERROR_NO_MEMORY;
}
int myindex = nextScaffoldPart(parser);
if (myindex < 0)
return XML_ERROR_NO_MEMORY;
+ assert(dtd->scaffIndex != NULL);
dtd->scaffIndex[dtd->scaffLevel] = myindex;
dtd->scaffLevel++;
dtd->scaffold[myindex].type = XML_CTYPE_SEQ;
if (parser->m_groupConnector[parser->m_prologState.level] == ASCII_COMMA)
return XML_ERROR_SYNTAX;
if (dtd->in_eldecl
- && !parser->m_groupConnector[parser->m_prologState.level]
+ && ! parser->m_groupConnector[parser->m_prologState.level]
&& (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
- != XML_CTYPE_MIXED)
- ) {
+ != XML_CTYPE_MIXED)) {
dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type
= XML_CTYPE_CHOICE;
if (parser->m_elementDeclHandler)
#ifdef XML_DTD
case XML_ROLE_INNER_PARAM_ENTITY_REF:
dtd->hasParamEntityRefs = XML_TRUE;
- if (!parser->m_paramEntityParsing)
+ if (! parser->m_paramEntityParsing)
dtd->keepProcessing = dtd->standalone;
else {
const XML_Char *name;
ENTITY *entity;
- name = poolStoreString(&dtd->pool, enc,
- s + enc->minBytesPerChar,
- next - enc->minBytesPerChar);
- if (!name)
+ name = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (! name)
return XML_ERROR_NO_MEMORY;
entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
poolDiscard(&dtd->pool);
if yes, check that the entity exists, and that it is internal,
otherwise call the skipped entity handler
*/
- if (parser->m_prologState.documentEntity &&
- (dtd->standalone
- ? !parser->m_openInternalEntities
- : !dtd->hasParamEntityRefs)) {
- if (!entity)
+ if (parser->m_prologState.documentEntity
+ && (dtd->standalone ? ! parser->m_openInternalEntities
+ : ! dtd->hasParamEntityRefs)) {
+ if (! entity)
return XML_ERROR_UNDEFINED_ENTITY;
- else if (!entity->is_internal) {
+ else if (! entity->is_internal) {
/* It's hard to exhaustively search the code to be sure,
* but there doesn't seem to be a way of executing the
* following line. There are two cases:
*/
return XML_ERROR_ENTITY_DECLARED_IN_PE; /* LCOV_EXCL_LINE */
}
- }
- else if (!entity) {
+ } else if (! entity) {
dtd->keepProcessing = dtd->standalone;
/* cannot report skipped entities in declarations */
- if ((role == XML_ROLE_PARAM_ENTITY_REF) && parser->m_skippedEntityHandler) {
+ if ((role == XML_ROLE_PARAM_ENTITY_REF)
+ && parser->m_skippedEntityHandler) {
parser->m_skippedEntityHandler(parser->m_handlerArg, name, 1);
handleDefault = XML_FALSE;
}
return XML_ERROR_RECURSIVE_ENTITY_REF;
if (entity->textPtr) {
enum XML_Error result;
- XML_Bool betweenDecl =
- (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
+ XML_Bool betweenDecl
+ = (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE);
result = processInternalEntity(parser, entity, betweenDecl);
if (result != XML_ERROR_NONE)
return result;
if (parser->m_externalEntityRefHandler) {
dtd->paramEntityRead = XML_FALSE;
entity->open = XML_TRUE;
- if (!parser->m_externalEntityRefHandler(parser->m_externalEntityRefHandlerArg,
- 0,
- entity->base,
- entity->systemId,
- entity->publicId)) {
+ if (! parser->m_externalEntityRefHandler(
+ parser->m_externalEntityRefHandlerArg, 0, entity->base,
+ entity->systemId, entity->publicId)) {
entity->open = XML_FALSE;
return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
}
entity->open = XML_FALSE;
handleDefault = XML_FALSE;
- if (!dtd->paramEntityRead) {
+ if (! dtd->paramEntityRead) {
dtd->keepProcessing = dtd->standalone;
break;
}
- }
- else {
+ } else {
dtd->keepProcessing = dtd->standalone;
break;
}
}
#endif /* XML_DTD */
- if (!dtd->standalone &&
- parser->m_notStandaloneHandler &&
- !parser->m_notStandaloneHandler(parser->m_handlerArg))
+ if (! dtd->standalone && parser->m_notStandaloneHandler
+ && ! parser->m_notStandaloneHandler(parser->m_handlerArg))
return XML_ERROR_NOT_STANDALONE;
break;
- /* Element declaration stuff */
+ /* Element declaration stuff */
case XML_ROLE_ELEMENT_NAME:
if (parser->m_elementDeclHandler) {
parser->m_declElementType = getElementType(parser, enc, s, next);
- if (!parser->m_declElementType)
+ if (! parser->m_declElementType)
return XML_ERROR_NO_MEMORY;
dtd->scaffLevel = 0;
dtd->scaffCount = 0;
case XML_ROLE_CONTENT_EMPTY:
if (dtd->in_eldecl) {
if (parser->m_elementDeclHandler) {
- XML_Content * content = (XML_Content *) MALLOC(parser, sizeof(XML_Content));
- if (!content)
+ XML_Content *content
+ = (XML_Content *)MALLOC(parser, sizeof(XML_Content));
+ if (! content)
return XML_ERROR_NO_MEMORY;
content->quant = XML_CQUANT_NONE;
content->name = NULL;
content->numchildren = 0;
content->children = NULL;
- content->type = ((role == XML_ROLE_CONTENT_ANY) ?
- XML_CTYPE_ANY :
- XML_CTYPE_EMPTY);
+ content->type = ((role == XML_ROLE_CONTENT_ANY) ? XML_CTYPE_ANY
+ : XML_CTYPE_EMPTY);
*eventEndPP = s;
- parser->m_elementDeclHandler(parser->m_handlerArg, parser->m_declElementType->name, content);
+ parser->m_elementDeclHandler(
+ parser->m_handlerArg, parser->m_declElementType->name, content);
handleDefault = XML_FALSE;
}
dtd->in_eldecl = XML_FALSE;
ELEMENT_TYPE *el;
const XML_Char *name;
int nameLen;
- const char *nxt = (quant == XML_CQUANT_NONE
- ? next
- : next - enc->minBytesPerChar);
+ const char *nxt
+ = (quant == XML_CQUANT_NONE ? next : next - enc->minBytesPerChar);
int myindex = nextScaffoldPart(parser);
if (myindex < 0)
return XML_ERROR_NO_MEMORY;
dtd->scaffold[myindex].type = XML_CTYPE_NAME;
dtd->scaffold[myindex].quant = quant;
el = getElementType(parser, enc, s, nxt);
- if (!el)
+ if (! el)
return XML_ERROR_NO_MEMORY;
name = el->name;
dtd->scaffold[myindex].name = name;
nameLen = 0;
- for (; name[nameLen++]; );
- dtd->contentStringLen += nameLen;
+ for (; name[nameLen++];)
+ ;
+ dtd->contentStringLen += nameLen;
if (parser->m_elementDeclHandler)
handleDefault = XML_FALSE;
}
dtd->scaffLevel--;
dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant;
if (dtd->scaffLevel == 0) {
- if (!handleDefault) {
+ if (! handleDefault) {
XML_Content *model = build_model(parser);
- if (!model)
+ if (! model)
return XML_ERROR_NO_MEMORY;
*eventEndPP = s;
- parser->m_elementDeclHandler(parser->m_handlerArg, parser->m_declElementType->name, model);
+ parser->m_elementDeclHandler(
+ parser->m_handlerArg, parser->m_declElementType->name, model);
}
dtd->in_eldecl = XML_FALSE;
dtd->contentStringLen = 0;
/* End element declaration stuff */
case XML_ROLE_PI:
- if (!reportProcessingInstruction(parser, enc, s, next))
+ if (! reportProcessingInstruction(parser, enc, s, next))
return XML_ERROR_NO_MEMORY;
handleDefault = XML_FALSE;
break;
case XML_ROLE_COMMENT:
- if (!reportComment(parser, enc, s, next))
+ if (! reportComment(parser, enc, s, next))
return XML_ERROR_NO_MEMORY;
handleDefault = XML_FALSE;
break;
}
static enum XML_Error PTRCALL
-epilogProcessor(XML_Parser parser,
- const char *s,
- const char *end,
- const char **nextPtr)
-{
+epilogProcessor(XML_Parser parser, const char *s, const char *end,
+ const char **nextPtr) {
parser->m_processor = epilogProcessor;
parser->m_eventPtr = s;
for (;;) {
reportDefault(parser, parser->m_encoding, s, next);
break;
case XML_TOK_PI:
- if (!reportProcessingInstruction(parser, parser->m_encoding, s, next))
+ if (! reportProcessingInstruction(parser, parser->m_encoding, s, next))
return XML_ERROR_NO_MEMORY;
break;
case XML_TOK_COMMENT:
- if (!reportComment(parser, parser->m_encoding, s, next))
+ if (! reportComment(parser, parser->m_encoding, s, next))
return XML_ERROR_NO_MEMORY;
break;
case XML_TOK_INVALID:
parser->m_eventPtr = next;
return XML_ERROR_INVALID_TOKEN;
case XML_TOK_PARTIAL:
- if (!parser->m_parsingStatus.finalBuffer) {
+ if (! parser->m_parsingStatus.finalBuffer) {
*nextPtr = s;
return XML_ERROR_NONE;
}
return XML_ERROR_UNCLOSED_TOKEN;
case XML_TOK_PARTIAL_CHAR:
- if (!parser->m_parsingStatus.finalBuffer) {
+ if (! parser->m_parsingStatus.finalBuffer) {
*nextPtr = s;
return XML_ERROR_NONE;
}
return XML_ERROR_NONE;
case XML_FINISHED:
return XML_ERROR_ABORTED;
- default: ;
+ default:;
}
}
}
static enum XML_Error
-processInternalEntity(XML_Parser parser, ENTITY *entity,
- XML_Bool betweenDecl)
-{
+processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {
const char *textStart, *textEnd;
const char *next;
enum XML_Error result;
if (parser->m_freeInternalEntities) {
openEntity = parser->m_freeInternalEntities;
parser->m_freeInternalEntities = openEntity->next;
- }
- else {
- openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY));
- if (!openEntity)
+ } else {
+ openEntity
+ = (OPEN_INTERNAL_ENTITY *)MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY));
+ if (! openEntity)
return XML_ERROR_NO_MEMORY;
}
entity->open = XML_TRUE;
#ifdef XML_DTD
if (entity->is_param) {
- int tok = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
- result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd, tok,
- next, &next, XML_FALSE);
- }
- else
+ int tok
+ = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
+ result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
+ tok, next, &next, XML_FALSE, XML_FALSE);
+ } else
#endif /* XML_DTD */
- result = doContent(parser, parser->m_tagLevel, parser->m_internalEncoding, textStart,
- textEnd, &next, XML_FALSE);
+ result = doContent(parser, parser->m_tagLevel, parser->m_internalEncoding,
+ textStart, textEnd, &next, XML_FALSE);
if (result == XML_ERROR_NONE) {
if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
entity->processed = (int)(next - textStart);
parser->m_processor = internalEntityProcessor;
- }
- else {
+ } else {
entity->open = XML_FALSE;
parser->m_openInternalEntities = openEntity->next;
/* put openEntity back in list of free instances */
}
static enum XML_Error PTRCALL
-internalEntityProcessor(XML_Parser parser,
- const char *s,
- const char *end,
- const char **nextPtr)
-{
+internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
+ const char **nextPtr) {
ENTITY *entity;
const char *textStart, *textEnd;
const char *next;
enum XML_Error result;
OPEN_INTERNAL_ENTITY *openEntity = parser->m_openInternalEntities;
- if (!openEntity)
+ if (! openEntity)
return XML_ERROR_UNEXPECTED_STATE;
entity = openEntity->entity;
#ifdef XML_DTD
if (entity->is_param) {
- int tok = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
- result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd, tok,
- next, &next, XML_FALSE);
- }
- else
+ int tok
+ = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
+ result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
+ tok, next, &next, XML_FALSE, XML_TRUE);
+ } else
#endif /* XML_DTD */
- result = doContent(parser, openEntity->startTagLevel, parser->m_internalEncoding,
- textStart, textEnd, &next, XML_FALSE);
+ result = doContent(parser, openEntity->startTagLevel,
+ parser->m_internalEncoding, textStart, textEnd, &next,
+ XML_FALSE);
if (result != XML_ERROR_NONE)
return result;
- else if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
+ else if (textEnd != next
+ && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
entity->processed = (int)(next - (char *)entity->textPtr);
return result;
- }
- else {
+ } else {
entity->open = XML_FALSE;
parser->m_openInternalEntities = openEntity->next;
/* put openEntity back in list of free instances */
parser->m_processor = prologProcessor;
tok = XmlPrologTok(parser->m_encoding, s, end, &next);
return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
- (XML_Bool)!parser->m_parsingStatus.finalBuffer);
- }
- else
+ (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE);
+ } else
#endif /* XML_DTD */
{
parser->m_processor = contentProcessor;
/* see externalEntityContentProcessor vs contentProcessor */
- return doContent(parser, parser->m_parentParser ? 1 : 0, parser->m_encoding, s, end,
- nextPtr, (XML_Bool)!parser->m_parsingStatus.finalBuffer);
+ return doContent(parser, parser->m_parentParser ? 1 : 0, parser->m_encoding,
+ s, end, nextPtr,
+ (XML_Bool)! parser->m_parsingStatus.finalBuffer);
}
}
static enum XML_Error PTRCALL
-errorProcessor(XML_Parser parser,
- const char *UNUSED_P(s),
- const char *UNUSED_P(end),
- const char **UNUSED_P(nextPtr))
-{
+errorProcessor(XML_Parser parser, const char *s, const char *end,
+ const char **nextPtr) {
+ UNUSED_P(s);
+ UNUSED_P(end);
+ UNUSED_P(nextPtr);
return parser->m_errorCode;
}
static enum XML_Error
storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
- const char *ptr, const char *end,
- STRING_POOL *pool)
-{
- enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr,
- end, pool);
+ const char *ptr, const char *end, STRING_POOL *pool) {
+ enum XML_Error result
+ = appendAttributeValue(parser, enc, isCdata, ptr, end, pool);
if (result)
return result;
- if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
+ if (! isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
poolChop(pool);
- if (!poolAppendChar(pool, XML_T('\0')))
+ if (! poolAppendChar(pool, XML_T('\0')))
return XML_ERROR_NO_MEMORY;
return XML_ERROR_NONE;
}
static enum XML_Error
appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
- const char *ptr, const char *end,
- STRING_POOL *pool)
-{
- DTD * const dtd = parser->m_dtd; /* save one level of indirection */
+ const char *ptr, const char *end, STRING_POOL *pool) {
+ DTD *const dtd = parser->m_dtd; /* save one level of indirection */
for (;;) {
const char *next;
int tok = XmlAttributeValueTok(enc, ptr, end, &next);
if (enc == parser->m_encoding)
parser->m_eventPtr = ptr;
return XML_ERROR_INVALID_TOKEN;
- case XML_TOK_CHAR_REF:
- {
- XML_Char buf[XML_ENCODE_MAX];
- int i;
- int n = XmlCharRefNumber(enc, ptr);
- if (n < 0) {
- if (enc == parser->m_encoding)
- parser->m_eventPtr = ptr;
- return XML_ERROR_BAD_CHAR_REF;
- }
- if (!isCdata
- && n == 0x20 /* space */
- && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
- break;
- n = XmlEncode(n, (ICHAR *)buf);
- /* The XmlEncode() functions can never return 0 here. That
- * error return happens if the code point passed in is either
- * negative or greater than or equal to 0x110000. The
- * XmlCharRefNumber() functions will all return a number
- * strictly less than 0x110000 or a negative value if an error
- * occurred. The negative value is intercepted above, so
- * XmlEncode() is never passed a value it might return an
- * error for.
- */
- for (i = 0; i < n; i++) {
- if (!poolAppendChar(pool, buf[i]))
- return XML_ERROR_NO_MEMORY;
- }
+ case XML_TOK_CHAR_REF: {
+ XML_Char buf[XML_ENCODE_MAX];
+ int i;
+ int n = XmlCharRefNumber(enc, ptr);
+ if (n < 0) {
+ if (enc == parser->m_encoding)
+ parser->m_eventPtr = ptr;
+ return XML_ERROR_BAD_CHAR_REF;
}
- break;
+ if (! isCdata && n == 0x20 /* space */
+ && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
+ break;
+ n = XmlEncode(n, (ICHAR *)buf);
+ /* The XmlEncode() functions can never return 0 here. That
+ * error return happens if the code point passed in is either
+ * negative or greater than or equal to 0x110000. The
+ * XmlCharRefNumber() functions will all return a number
+ * strictly less than 0x110000 or a negative value if an error
+ * occurred. The negative value is intercepted above, so
+ * XmlEncode() is never passed a value it might return an
+ * error for.
+ */
+ for (i = 0; i < n; i++) {
+ if (! poolAppendChar(pool, buf[i]))
+ return XML_ERROR_NO_MEMORY;
+ }
+ } break;
case XML_TOK_DATA_CHARS:
- if (!poolAppend(pool, enc, ptr, next))
+ if (! poolAppend(pool, enc, ptr, next))
return XML_ERROR_NO_MEMORY;
break;
case XML_TOK_TRAILING_CR:
/* fall through */
case XML_TOK_ATTRIBUTE_VALUE_S:
case XML_TOK_DATA_NEWLINE:
- if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
+ if (! isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
break;
- if (!poolAppendChar(pool, 0x20))
+ if (! poolAppendChar(pool, 0x20))
return XML_ERROR_NO_MEMORY;
break;
- case XML_TOK_ENTITY_REF:
- {
- const XML_Char *name;
- ENTITY *entity;
- char checkEntityDecl;
- XML_Char ch = (XML_Char) XmlPredefinedEntityName(enc,
- ptr + enc->minBytesPerChar,
- next - enc->minBytesPerChar);
- if (ch) {
- if (!poolAppendChar(pool, ch))
- return XML_ERROR_NO_MEMORY;
- break;
- }
- name = poolStoreString(&parser->m_temp2Pool, enc,
- ptr + enc->minBytesPerChar,
- next - enc->minBytesPerChar);
- if (!name)
+ case XML_TOK_ENTITY_REF: {
+ const XML_Char *name;
+ ENTITY *entity;
+ char checkEntityDecl;
+ XML_Char ch = (XML_Char)XmlPredefinedEntityName(
+ enc, ptr + enc->minBytesPerChar, next - enc->minBytesPerChar);
+ if (ch) {
+ if (! poolAppendChar(pool, ch))
return XML_ERROR_NO_MEMORY;
- entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
- poolDiscard(&parser->m_temp2Pool);
- /* First, determine if a check for an existing declaration is needed;
- if yes, check that the entity exists, and that it is internal.
- */
- if (pool == &dtd->pool) /* are we called from prolog? */
- checkEntityDecl =
+ break;
+ }
+ name = poolStoreString(&parser->m_temp2Pool, enc,
+ ptr + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (! name)
+ return XML_ERROR_NO_MEMORY;
+ entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0);
+ poolDiscard(&parser->m_temp2Pool);
+ /* First, determine if a check for an existing declaration is needed;
+ if yes, check that the entity exists, and that it is internal.
+ */
+ if (pool == &dtd->pool) /* are we called from prolog? */
+ checkEntityDecl =
#ifdef XML_DTD
- parser->m_prologState.documentEntity &&
+ parser->m_prologState.documentEntity &&
#endif /* XML_DTD */
- (dtd->standalone
- ? !parser->m_openInternalEntities
- : !dtd->hasParamEntityRefs);
- else /* if (pool == &parser->m_tempPool): we are called from content */
- checkEntityDecl = !dtd->hasParamEntityRefs || dtd->standalone;
- if (checkEntityDecl) {
- if (!entity)
- return XML_ERROR_UNDEFINED_ENTITY;
- else if (!entity->is_internal)
- return XML_ERROR_ENTITY_DECLARED_IN_PE;
- }
- else if (!entity) {
- /* Cannot report skipped entity here - see comments on
- parser->m_skippedEntityHandler.
- if (parser->m_skippedEntityHandler)
- parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
- */
- /* Cannot call the default handler because this would be
- out of sync with the call to the startElementHandler.
- if ((pool == &parser->m_tempPool) && parser->m_defaultHandler)
- reportDefault(parser, enc, ptr, next);
- */
- break;
- }
- if (entity->open) {
- if (enc == parser->m_encoding) {
- /* It does not appear that this line can be executed.
- *
- * The "if (entity->open)" check catches recursive entity
- * definitions. In order to be called with an open
- * entity, it must have gone through this code before and
- * been through the recursive call to
- * appendAttributeValue() some lines below. That call
- * sets the local encoding ("enc") to the parser's
- * internal encoding (internal_utf8 or internal_utf16),
- * which can never be the same as the principle encoding.
- * It doesn't appear there is another code path that gets
- * here with entity->open being TRUE.
- *
- * Since it is not certain that this logic is watertight,
- * we keep the line and merely exclude it from coverage
- * tests.
- */
- parser->m_eventPtr = ptr; /* LCOV_EXCL_LINE */
- }
- return XML_ERROR_RECURSIVE_ENTITY_REF;
- }
- if (entity->notation) {
- if (enc == parser->m_encoding)
- parser->m_eventPtr = ptr;
- return XML_ERROR_BINARY_ENTITY_REF;
- }
- if (!entity->textPtr) {
- if (enc == parser->m_encoding)
- parser->m_eventPtr = ptr;
- return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
- }
- else {
- enum XML_Error result;
- const XML_Char *textEnd = entity->textPtr + entity->textLen;
- entity->open = XML_TRUE;
- result = appendAttributeValue(parser, parser->m_internalEncoding, isCdata,
- (char *)entity->textPtr,
- (char *)textEnd, pool);
- entity->open = XML_FALSE;
- if (result)
- return result;
+ (dtd->standalone ? ! parser->m_openInternalEntities
+ : ! dtd->hasParamEntityRefs);
+ else /* if (pool == &parser->m_tempPool): we are called from content */
+ checkEntityDecl = ! dtd->hasParamEntityRefs || dtd->standalone;
+ if (checkEntityDecl) {
+ if (! entity)
+ return XML_ERROR_UNDEFINED_ENTITY;
+ else if (! entity->is_internal)
+ return XML_ERROR_ENTITY_DECLARED_IN_PE;
+ } else if (! entity) {
+ /* Cannot report skipped entity here - see comments on
+ parser->m_skippedEntityHandler.
+ if (parser->m_skippedEntityHandler)
+ parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0);
+ */
+ /* Cannot call the default handler because this would be
+ out of sync with the call to the startElementHandler.
+ if ((pool == &parser->m_tempPool) && parser->m_defaultHandler)
+ reportDefault(parser, enc, ptr, next);
+ */
+ break;
+ }
+ if (entity->open) {
+ if (enc == parser->m_encoding) {
+ /* It does not appear that this line can be executed.
+ *
+ * The "if (entity->open)" check catches recursive entity
+ * definitions. In order to be called with an open
+ * entity, it must have gone through this code before and
+ * been through the recursive call to
+ * appendAttributeValue() some lines below. That call
+ * sets the local encoding ("enc") to the parser's
+ * internal encoding (internal_utf8 or internal_utf16),
+ * which can never be the same as the principle encoding.
+ * It doesn't appear there is another code path that gets
+ * here with entity->open being TRUE.
+ *
+ * Since it is not certain that this logic is watertight,
+ * we keep the line and merely exclude it from coverage
+ * tests.
+ */
+ parser->m_eventPtr = ptr; /* LCOV_EXCL_LINE */
}
+ return XML_ERROR_RECURSIVE_ENTITY_REF;
}
- break;
+ if (entity->notation) {
+ if (enc == parser->m_encoding)
+ parser->m_eventPtr = ptr;
+ return XML_ERROR_BINARY_ENTITY_REF;
+ }
+ if (! entity->textPtr) {
+ if (enc == parser->m_encoding)
+ parser->m_eventPtr = ptr;
+ return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
+ } else {
+ enum XML_Error result;
+ const XML_Char *textEnd = entity->textPtr + entity->textLen;
+ entity->open = XML_TRUE;
+ result = appendAttributeValue(parser, parser->m_internalEncoding,
+ isCdata, (char *)entity->textPtr,
+ (char *)textEnd, pool);
+ entity->open = XML_FALSE;
+ if (result)
+ return result;
+ }
+ } break;
default:
/* The only token returned by XmlAttributeValueTok() that does
* not have an explicit case here is XML_TOK_PARTIAL_CHAR.
}
static enum XML_Error
-storeEntityValue(XML_Parser parser,
- const ENCODING *enc,
- const char *entityTextPtr,
- const char *entityTextEnd)
-{
- DTD * const dtd = parser->m_dtd; /* save one level of indirection */
+storeEntityValue(XML_Parser parser, const ENCODING *enc,
+ const char *entityTextPtr, const char *entityTextEnd) {
+ DTD *const dtd = parser->m_dtd; /* save one level of indirection */
STRING_POOL *pool = &(dtd->entityValuePool);
enum XML_Error result = XML_ERROR_NONE;
#ifdef XML_DTD
/* never return Null for the value argument in EntityDeclHandler,
since this would indicate an external entity; therefore we
have to make sure that entityValuePool.start is not null */
- if (!pool->blocks) {
- if (!poolGrow(pool))
+ if (! pool->blocks) {
+ if (! poolGrow(pool))
return XML_ERROR_NO_MEMORY;
}
name = poolStoreString(&parser->m_tempPool, enc,
entityTextPtr + enc->minBytesPerChar,
next - enc->minBytesPerChar);
- if (!name) {
+ if (! name) {
result = XML_ERROR_NO_MEMORY;
goto endEntityValue;
}
entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0);
poolDiscard(&parser->m_tempPool);
- if (!entity) {
+ if (! entity) {
/* not a well-formedness error - see XML 1.0: WFC Entity Declared */
/* cannot report skipped entity here - see comments on
parser->m_skippedEntityHandler
if (parser->m_externalEntityRefHandler) {
dtd->paramEntityRead = XML_FALSE;
entity->open = XML_TRUE;
- if (!parser->m_externalEntityRefHandler(parser->m_externalEntityRefHandlerArg,
- 0,
- entity->base,
- entity->systemId,
- entity->publicId)) {
+ if (! parser->m_externalEntityRefHandler(
+ parser->m_externalEntityRefHandlerArg, 0, entity->base,
+ entity->systemId, entity->publicId)) {
entity->open = XML_FALSE;
result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
goto endEntityValue;
}
entity->open = XML_FALSE;
- if (!dtd->paramEntityRead)
+ if (! dtd->paramEntityRead)
dtd->keepProcessing = dtd->standalone;
- }
- else
+ } else
dtd->keepProcessing = dtd->standalone;
- }
- else {
+ } else {
entity->open = XML_TRUE;
- result = storeEntityValue(parser,
- parser->m_internalEncoding,
- (char *)entity->textPtr,
- (char *)(entity->textPtr
- + entity->textLen));
+ result = storeEntityValue(
+ parser, parser->m_internalEncoding, (char *)entity->textPtr,
+ (char *)(entity->textPtr + entity->textLen));
entity->open = XML_FALSE;
if (result)
goto endEntityValue;
goto endEntityValue;
case XML_TOK_ENTITY_REF:
case XML_TOK_DATA_CHARS:
- if (!poolAppend(pool, enc, entityTextPtr, next)) {
+ if (! poolAppend(pool, enc, entityTextPtr, next)) {
result = XML_ERROR_NO_MEMORY;
goto endEntityValue;
}
next = entityTextPtr + enc->minBytesPerChar;
/* fall through */
case XML_TOK_DATA_NEWLINE:
- if (pool->end == pool->ptr && !poolGrow(pool)) {
- result = XML_ERROR_NO_MEMORY;
+ if (pool->end == pool->ptr && ! poolGrow(pool)) {
+ result = XML_ERROR_NO_MEMORY;
goto endEntityValue;
}
*(pool->ptr)++ = 0xA;
break;
- case XML_TOK_CHAR_REF:
- {
- XML_Char buf[XML_ENCODE_MAX];
- int i;
- int n = XmlCharRefNumber(enc, entityTextPtr);
- if (n < 0) {
- if (enc == parser->m_encoding)
- parser->m_eventPtr = entityTextPtr;
- result = XML_ERROR_BAD_CHAR_REF;
+ case XML_TOK_CHAR_REF: {
+ XML_Char buf[XML_ENCODE_MAX];
+ int i;
+ int n = XmlCharRefNumber(enc, entityTextPtr);
+ if (n < 0) {
+ if (enc == parser->m_encoding)
+ parser->m_eventPtr = entityTextPtr;
+ result = XML_ERROR_BAD_CHAR_REF;
+ goto endEntityValue;
+ }
+ n = XmlEncode(n, (ICHAR *)buf);
+ /* The XmlEncode() functions can never return 0 here. That
+ * error return happens if the code point passed in is either
+ * negative or greater than or equal to 0x110000. The
+ * XmlCharRefNumber() functions will all return a number
+ * strictly less than 0x110000 or a negative value if an error
+ * occurred. The negative value is intercepted above, so
+ * XmlEncode() is never passed a value it might return an
+ * error for.
+ */
+ for (i = 0; i < n; i++) {
+ if (pool->end == pool->ptr && ! poolGrow(pool)) {
+ result = XML_ERROR_NO_MEMORY;
goto endEntityValue;
}
- n = XmlEncode(n, (ICHAR *)buf);
- /* The XmlEncode() functions can never return 0 here. That
- * error return happens if the code point passed in is either
- * negative or greater than or equal to 0x110000. The
- * XmlCharRefNumber() functions will all return a number
- * strictly less than 0x110000 or a negative value if an error
- * occurred. The negative value is intercepted above, so
- * XmlEncode() is never passed a value it might return an
- * error for.
- */
- for (i = 0; i < n; i++) {
- if (pool->end == pool->ptr && !poolGrow(pool)) {
- result = XML_ERROR_NO_MEMORY;
- goto endEntityValue;
- }
- *(pool->ptr)++ = buf[i];
- }
+ *(pool->ptr)++ = buf[i];
}
- break;
+ } break;
case XML_TOK_PARTIAL:
if (enc == parser->m_encoding)
parser->m_eventPtr = entityTextPtr;
}
static void FASTCALL
-normalizeLines(XML_Char *s)
-{
+normalizeLines(XML_Char *s) {
XML_Char *p;
for (;; s++) {
if (*s == XML_T('\0'))
*p++ = 0xA;
if (*++s == 0xA)
s++;
- }
- else
+ } else
*p++ = *s++;
} while (*s);
*p = XML_T('\0');
static int
reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
- const char *start, const char *end)
-{
+ const char *start, const char *end) {
const XML_Char *target;
XML_Char *data;
const char *tem;
- if (!parser->m_processingInstructionHandler) {
+ if (! parser->m_processingInstructionHandler) {
if (parser->m_defaultHandler)
reportDefault(parser, enc, start, end);
return 1;
start += enc->minBytesPerChar * 2;
tem = start + XmlNameLength(enc, start);
target = poolStoreString(&parser->m_tempPool, enc, start, tem);
- if (!target)
+ if (! target)
return 0;
poolFinish(&parser->m_tempPool);
- data = poolStoreString(&parser->m_tempPool, enc,
- XmlSkipS(enc, tem),
- end - enc->minBytesPerChar*2);
- if (!data)
+ data = poolStoreString(&parser->m_tempPool, enc, XmlSkipS(enc, tem),
+ end - enc->minBytesPerChar * 2);
+ if (! data)
return 0;
normalizeLines(data);
parser->m_processingInstructionHandler(parser->m_handlerArg, target, data);
}
static int
-reportComment(XML_Parser parser, const ENCODING *enc,
- const char *start, const char *end)
-{
+reportComment(XML_Parser parser, const ENCODING *enc, const char *start,
+ const char *end) {
XML_Char *data;
- if (!parser->m_commentHandler) {
+ if (! parser->m_commentHandler) {
if (parser->m_defaultHandler)
reportDefault(parser, enc, start, end);
return 1;
}
- data = poolStoreString(&parser->m_tempPool,
- enc,
+ data = poolStoreString(&parser->m_tempPool, enc,
start + enc->minBytesPerChar * 4,
end - enc->minBytesPerChar * 3);
- if (!data)
+ if (! data)
return 0;
normalizeLines(data);
parser->m_commentHandler(parser->m_handlerArg, data);
}
static void
-reportDefault(XML_Parser parser, const ENCODING *enc,
- const char *s, const char *end)
-{
+reportDefault(XML_Parser parser, const ENCODING *enc, const char *s,
+ const char *end) {
if (MUST_CONVERT(enc, s)) {
enum XML_Convert_Result convert_res;
const char **eventPP;
if (enc == parser->m_encoding) {
eventPP = &parser->m_eventPtr;
eventEndPP = &parser->m_eventEndPtr;
- }
- else {
+ } else {
/* To get here, two things must be true; the parser must be
* using a character encoding that is not the same as the
* encoding passed in, and the encoding passed in must need
}
do {
ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf;
- convert_res = XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
+ convert_res
+ = XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)parser->m_dataBufEnd);
*eventEndPP = s;
- parser->m_defaultHandler(parser->m_handlerArg, parser->m_dataBuf, (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
+ parser->m_defaultHandler(parser->m_handlerArg, parser->m_dataBuf,
+ (int)(dataPtr - (ICHAR *)parser->m_dataBuf));
*eventPP = s;
- } while ((convert_res != XML_CONVERT_COMPLETED) && (convert_res != XML_CONVERT_INPUT_INCOMPLETE));
- }
- else
- parser->m_defaultHandler(parser->m_handlerArg, (XML_Char *)s, (int)((XML_Char *)end - (XML_Char *)s));
+ } while ((convert_res != XML_CONVERT_COMPLETED)
+ && (convert_res != XML_CONVERT_INPUT_INCOMPLETE));
+ } else
+ parser->m_defaultHandler(parser->m_handlerArg, (XML_Char *)s,
+ (int)((XML_Char *)end - (XML_Char *)s));
}
-
static int
defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
- XML_Bool isId, const XML_Char *value, XML_Parser parser)
-{
+ XML_Bool isId, const XML_Char *value, XML_Parser parser) {
DEFAULT_ATTRIBUTE *att;
if (value || isId) {
/* The handling of default attributes gets messed up if we have
for (i = 0; i < type->nDefaultAtts; i++)
if (attId == type->defaultAtts[i].id)
return 1;
- if (isId && !type->idAtt && !attId->xmlns)
+ if (isId && ! type->idAtt && ! attId->xmlns)
type->idAtt = attId;
}
if (type->nDefaultAtts == type->allocDefaultAtts) {
if (type->allocDefaultAtts == 0) {
type->allocDefaultAtts = 8;
- type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(parser, type->allocDefaultAtts
- * sizeof(DEFAULT_ATTRIBUTE));
- if (!type->defaultAtts) {
+ type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(
+ parser, type->allocDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
+ if (! type->defaultAtts) {
type->allocDefaultAtts = 0;
return 0;
}
- }
- else {
+ } else {
DEFAULT_ATTRIBUTE *temp;
int count = type->allocDefaultAtts * 2;
- temp = (DEFAULT_ATTRIBUTE *)
- REALLOC(parser, type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE)));
+ temp = (DEFAULT_ATTRIBUTE *)REALLOC(parser, type->defaultAtts,
+ (count * sizeof(DEFAULT_ATTRIBUTE)));
if (temp == NULL)
return 0;
type->allocDefaultAtts = count;
att->id = attId;
att->value = value;
att->isCdata = isCdata;
- if (!isCdata)
+ if (! isCdata)
attId->maybeTokenized = XML_TRUE;
type->nDefaultAtts += 1;
return 1;
}
static int
-setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
-{
- DTD * const dtd = parser->m_dtd; /* save one level of indirection */
+setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType) {
+ DTD *const dtd = parser->m_dtd; /* save one level of indirection */
const XML_Char *name;
for (name = elementType->name; *name; name++) {
if (*name == XML_T(ASCII_COLON)) {
PREFIX *prefix;
const XML_Char *s;
for (s = elementType->name; s != name; s++) {
- if (!poolAppendChar(&dtd->pool, *s))
+ if (! poolAppendChar(&dtd->pool, *s))
return 0;
}
- if (!poolAppendChar(&dtd->pool, XML_T('\0')))
+ if (! poolAppendChar(&dtd->pool, XML_T('\0')))
return 0;
prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
sizeof(PREFIX));
- if (!prefix)
+ if (! prefix)
return 0;
if (prefix->name == poolStart(&dtd->pool))
poolFinish(&dtd->pool);
}
static ATTRIBUTE_ID *
-getAttributeId(XML_Parser parser, const ENCODING *enc,
- const char *start, const char *end)
-{
- DTD * const dtd = parser->m_dtd; /* save one level of indirection */
+getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start,
+ const char *end) {
+ DTD *const dtd = parser->m_dtd; /* save one level of indirection */
ATTRIBUTE_ID *id;
const XML_Char *name;
- if (!poolAppendChar(&dtd->pool, XML_T('\0')))
+ if (! poolAppendChar(&dtd->pool, XML_T('\0')))
return NULL;
name = poolStoreString(&dtd->pool, enc, start, end);
- if (!name)
+ if (! name)
return NULL;
/* skip quotation mark - its storage will be re-used (like in name[-1]) */
++name;
- id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name, sizeof(ATTRIBUTE_ID));
- if (!id)
+ id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name,
+ sizeof(ATTRIBUTE_ID));
+ if (! id)
return NULL;
if (id->name != name)
poolDiscard(&dtd->pool);
else {
poolFinish(&dtd->pool);
- if (!parser->m_ns)
+ if (! parser->m_ns)
;
- else if (name[0] == XML_T(ASCII_x)
- && name[1] == XML_T(ASCII_m)
- && name[2] == XML_T(ASCII_l)
- && name[3] == XML_T(ASCII_n)
- && name[4] == XML_T(ASCII_s)
- && (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) {
+ else if (name[0] == XML_T(ASCII_x) && name[1] == XML_T(ASCII_m)
+ && name[2] == XML_T(ASCII_l) && name[3] == XML_T(ASCII_n)
+ && name[4] == XML_T(ASCII_s)
+ && (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) {
if (name[5] == XML_T('\0'))
id->prefix = &dtd->defaultPrefix;
else
- id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6, sizeof(PREFIX));
+ id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6,
+ sizeof(PREFIX));
id->xmlns = XML_TRUE;
- }
- else {
+ } else {
int i;
for (i = 0; name[i]; i++) {
/* attributes without prefix are *not* in the default namespace */
if (name[i] == XML_T(ASCII_COLON)) {
int j;
for (j = 0; j < i; j++) {
- if (!poolAppendChar(&dtd->pool, name[j]))
+ if (! poolAppendChar(&dtd->pool, name[j]))
return NULL;
}
- if (!poolAppendChar(&dtd->pool, XML_T('\0')))
+ if (! poolAppendChar(&dtd->pool, XML_T('\0')))
return NULL;
- id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
- sizeof(PREFIX));
- if (!id->prefix)
+ id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes,
+ poolStart(&dtd->pool), sizeof(PREFIX));
+ if (! id->prefix)
return NULL;
if (id->prefix->name == poolStart(&dtd->pool))
poolFinish(&dtd->pool);
#define CONTEXT_SEP XML_T(ASCII_FF)
static const XML_Char *
-getContext(XML_Parser parser)
-{
- DTD * const dtd = parser->m_dtd; /* save one level of indirection */
+getContext(XML_Parser parser) {
+ DTD *const dtd = parser->m_dtd; /* save one level of indirection */
HASH_TABLE_ITER iter;
XML_Bool needSep = XML_FALSE;
if (dtd->defaultPrefix.binding) {
int i;
int len;
- if (!poolAppendChar(&parser->m_tempPool, XML_T(ASCII_EQUALS)))
+ if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_EQUALS)))
return NULL;
len = dtd->defaultPrefix.binding->uriLen;
if (parser->m_namespaceSeparator)
len--;
for (i = 0; i < len; i++) {
- if (!poolAppendChar(&parser->m_tempPool, dtd->defaultPrefix.binding->uri[i])) {
+ if (! poolAppendChar(&parser->m_tempPool,
+ dtd->defaultPrefix.binding->uri[i])) {
/* Because of memory caching, I don't believe this line can be
* executed.
*
int len;
const XML_Char *s;
PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
- if (!prefix)
+ if (! prefix)
break;
- if (!prefix->binding) {
+ if (! prefix->binding) {
/* This test appears to be (justifiable) paranoia. There does
* not seem to be a way of injecting a prefix without a binding
* that doesn't get errored long before this function is called.
*/
continue; /* LCOV_EXCL_LINE */
}
- if (needSep && !poolAppendChar(&parser->m_tempPool, CONTEXT_SEP))
+ if (needSep && ! poolAppendChar(&parser->m_tempPool, CONTEXT_SEP))
return NULL;
for (s = prefix->name; *s; s++)
- if (!poolAppendChar(&parser->m_tempPool, *s))
+ if (! poolAppendChar(&parser->m_tempPool, *s))
return NULL;
- if (!poolAppendChar(&parser->m_tempPool, XML_T(ASCII_EQUALS)))
+ if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_EQUALS)))
return NULL;
len = prefix->binding->uriLen;
if (parser->m_namespaceSeparator)
len--;
for (i = 0; i < len; i++)
- if (!poolAppendChar(&parser->m_tempPool, prefix->binding->uri[i]))
+ if (! poolAppendChar(&parser->m_tempPool, prefix->binding->uri[i]))
return NULL;
needSep = XML_TRUE;
}
-
hashTableIterInit(&iter, &(dtd->generalEntities));
for (;;) {
const XML_Char *s;
ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
- if (!e)
+ if (! e)
break;
- if (!e->open)
+ if (! e->open)
continue;
- if (needSep && !poolAppendChar(&parser->m_tempPool, CONTEXT_SEP))
+ if (needSep && ! poolAppendChar(&parser->m_tempPool, CONTEXT_SEP))
return NULL;
for (s = e->name; *s; s++)
- if (!poolAppendChar(&parser->m_tempPool, *s))
+ if (! poolAppendChar(&parser->m_tempPool, *s))
return 0;
needSep = XML_TRUE;
}
- if (!poolAppendChar(&parser->m_tempPool, XML_T('\0')))
+ if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
return NULL;
return parser->m_tempPool.start;
}
static XML_Bool
-setContext(XML_Parser parser, const XML_Char *context)
-{
- DTD * const dtd = parser->m_dtd; /* save one level of indirection */
+setContext(XML_Parser parser, const XML_Char *context) {
+ DTD *const dtd = parser->m_dtd; /* save one level of indirection */
const XML_Char *s = context;
while (*context != XML_T('\0')) {
if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
ENTITY *e;
- if (!poolAppendChar(&parser->m_tempPool, XML_T('\0')))
+ if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
return XML_FALSE;
- e = (ENTITY *)lookup(parser, &dtd->generalEntities, poolStart(&parser->m_tempPool), 0);
+ e = (ENTITY *)lookup(parser, &dtd->generalEntities,
+ poolStart(&parser->m_tempPool), 0);
if (e)
e->open = XML_TRUE;
if (*s != XML_T('\0'))
s++;
context = s;
poolDiscard(&parser->m_tempPool);
- }
- else if (*s == XML_T(ASCII_EQUALS)) {
+ } else if (*s == XML_T(ASCII_EQUALS)) {
PREFIX *prefix;
if (poolLength(&parser->m_tempPool) == 0)
prefix = &dtd->defaultPrefix;
else {
- if (!poolAppendChar(&parser->m_tempPool, XML_T('\0')))
+ if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
return XML_FALSE;
- prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&parser->m_tempPool),
- sizeof(PREFIX));
- if (!prefix)
+ prefix
+ = (PREFIX *)lookup(parser, &dtd->prefixes,
+ poolStart(&parser->m_tempPool), sizeof(PREFIX));
+ if (! prefix)
return XML_FALSE;
if (prefix->name == poolStart(&parser->m_tempPool)) {
prefix->name = poolCopyString(&dtd->pool, prefix->name);
- if (!prefix->name)
+ if (! prefix->name)
return XML_FALSE;
}
poolDiscard(&parser->m_tempPool);
}
- for (context = s + 1;
- *context != CONTEXT_SEP && *context != XML_T('\0');
+ for (context = s + 1; *context != CONTEXT_SEP && *context != XML_T('\0');
context++)
- if (!poolAppendChar(&parser->m_tempPool, *context))
+ if (! poolAppendChar(&parser->m_tempPool, *context))
return XML_FALSE;
- if (!poolAppendChar(&parser->m_tempPool, XML_T('\0')))
+ if (! poolAppendChar(&parser->m_tempPool, XML_T('\0')))
return XML_FALSE;
if (addBinding(parser, prefix, NULL, poolStart(&parser->m_tempPool),
- &parser->m_inheritedBindings) != XML_ERROR_NONE)
+ &parser->m_inheritedBindings)
+ != XML_ERROR_NONE)
return XML_FALSE;
poolDiscard(&parser->m_tempPool);
if (*context != XML_T('\0'))
++context;
s = context;
- }
- else {
- if (!poolAppendChar(&parser->m_tempPool, *s))
+ } else {
+ if (! poolAppendChar(&parser->m_tempPool, *s))
return XML_FALSE;
s++;
}
}
static void FASTCALL
-normalizePublicId(XML_Char *publicId)
-{
+normalizePublicId(XML_Char *publicId) {
XML_Char *p = publicId;
XML_Char *s;
for (s = publicId; *s; s++) {
}
static DTD *
-dtdCreate(const XML_Memory_Handling_Suite *ms)
-{
+dtdCreate(const XML_Memory_Handling_Suite *ms) {
DTD *p = (DTD *)ms->malloc_fcn(sizeof(DTD));
if (p == NULL)
return p;
}
static void
-dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms)
-{
+dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms) {
HASH_TABLE_ITER iter;
hashTableIterInit(&iter, &(p->elementTypes));
for (;;) {
ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
- if (!e)
+ if (! e)
break;
if (e->allocDefaultAtts != 0)
ms->free_fcn(e->defaultAtts);
}
static void
-dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms)
-{
+dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms) {
HASH_TABLE_ITER iter;
hashTableIterInit(&iter, &(p->elementTypes));
for (;;) {
ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
- if (!e)
+ if (! e)
break;
if (e->allocDefaultAtts != 0)
ms->free_fcn(e->defaultAtts);
The new DTD has already been initialized.
*/
static int
-dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms)
-{
+dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
+ const XML_Memory_Handling_Suite *ms) {
HASH_TABLE_ITER iter;
/* Copy the prefix table. */
for (;;) {
const XML_Char *name;
const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
- if (!oldP)
+ if (! oldP)
break;
name = poolCopyString(&(newDtd->pool), oldP->name);
- if (!name)
+ if (! name)
return 0;
- if (!lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX)))
+ if (! lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX)))
return 0;
}
const XML_Char *name;
const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
- if (!oldA)
+ if (! oldA)
break;
/* Remember to allocate the scratch byte before the name. */
- if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
+ if (! poolAppendChar(&(newDtd->pool), XML_T('\0')))
return 0;
name = poolCopyString(&(newDtd->pool), oldA->name);
- if (!name)
+ if (! name)
return 0;
++name;
newA = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), name,
sizeof(ATTRIBUTE_ID));
- if (!newA)
+ if (! newA)
return 0;
newA->maybeTokenized = oldA->maybeTokenized;
if (oldA->prefix) {
ELEMENT_TYPE *newE;
const XML_Char *name;
const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
- if (!oldE)
+ if (! oldE)
break;
name = poolCopyString(&(newDtd->pool), oldE->name);
- if (!name)
+ if (! name)
return 0;
newE = (ELEMENT_TYPE *)lookup(oldParser, &(newDtd->elementTypes), name,
sizeof(ELEMENT_TYPE));
- if (!newE)
+ if (! newE)
return 0;
if (oldE->nDefaultAtts) {
- newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
- ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
- if (!newE->defaultAtts) {
+ newE->defaultAtts = (DEFAULT_ATTRIBUTE *)ms->malloc_fcn(
+ oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
+ if (! newE->defaultAtts) {
return 0;
}
}
if (oldE->idAtt)
- newE->idAtt = (ATTRIBUTE_ID *)
- lookup(oldParser, &(newDtd->attributeIds), oldE->idAtt->name, 0);
+ newE->idAtt = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds),
+ oldE->idAtt->name, 0);
newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
if (oldE->prefix)
newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
oldE->prefix->name, 0);
for (i = 0; i < newE->nDefaultAtts; i++) {
- newE->defaultAtts[i].id = (ATTRIBUTE_ID *)
- lookup(oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
+ newE->defaultAtts[i].id = (ATTRIBUTE_ID *)lookup(
+ oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
if (oldE->defaultAtts[i].value) {
newE->defaultAtts[i].value
= poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
- if (!newE->defaultAtts[i].value)
+ if (! newE->defaultAtts[i].value)
return 0;
- }
- else
+ } else
newE->defaultAtts[i].value = NULL;
}
}
/* Copy the entity tables. */
- if (!copyEntityTable(oldParser,
- &(newDtd->generalEntities),
- &(newDtd->pool),
- &(oldDtd->generalEntities)))
- return 0;
+ if (! copyEntityTable(oldParser, &(newDtd->generalEntities), &(newDtd->pool),
+ &(oldDtd->generalEntities)))
+ return 0;
#ifdef XML_DTD
- if (!copyEntityTable(oldParser,
- &(newDtd->paramEntities),
- &(newDtd->pool),
- &(oldDtd->paramEntities)))
- return 0;
+ if (! copyEntityTable(oldParser, &(newDtd->paramEntities), &(newDtd->pool),
+ &(oldDtd->paramEntities)))
+ return 0;
newDtd->paramEntityRead = oldDtd->paramEntityRead;
#endif /* XML_DTD */
newDtd->scaffIndex = oldDtd->scaffIndex;
return 1;
-} /* End dtdCopy */
+} /* End dtdCopy */
static int
-copyEntityTable(XML_Parser oldParser,
- HASH_TABLE *newTable,
- STRING_POOL *newPool,
- const HASH_TABLE *oldTable)
-{
+copyEntityTable(XML_Parser oldParser, HASH_TABLE *newTable,
+ STRING_POOL *newPool, const HASH_TABLE *oldTable) {
HASH_TABLE_ITER iter;
const XML_Char *cachedOldBase = NULL;
const XML_Char *cachedNewBase = NULL;
ENTITY *newE;
const XML_Char *name;
const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
- if (!oldE)
+ if (! oldE)
break;
name = poolCopyString(newPool, oldE->name);
- if (!name)
+ if (! name)
return 0;
newE = (ENTITY *)lookup(oldParser, newTable, name, sizeof(ENTITY));
- if (!newE)
+ if (! newE)
return 0;
if (oldE->systemId) {
const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
- if (!tem)
+ if (! tem)
return 0;
newE->systemId = tem;
if (oldE->base) {
else {
cachedOldBase = oldE->base;
tem = poolCopyString(newPool, cachedOldBase);
- if (!tem)
+ if (! tem)
return 0;
cachedNewBase = newE->base = tem;
}
}
if (oldE->publicId) {
tem = poolCopyString(newPool, oldE->publicId);
- if (!tem)
+ if (! tem)
return 0;
newE->publicId = tem;
}
- }
- else {
- const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr,
- oldE->textLen);
- if (!tem)
+ } else {
+ const XML_Char *tem
+ = poolCopyStringN(newPool, oldE->textPtr, oldE->textLen);
+ if (! tem)
return 0;
newE->textPtr = tem;
newE->textLen = oldE->textLen;
}
if (oldE->notation) {
const XML_Char *tem = poolCopyString(newPool, oldE->notation);
- if (!tem)
+ if (! tem)
return 0;
newE->notation = tem;
}
#define INIT_POWER 6
static XML_Bool FASTCALL
-keyeq(KEY s1, KEY s2)
-{
+keyeq(KEY s1, KEY s2) {
for (; *s1 == *s2; s1++, s2++)
if (*s1 == 0)
return XML_TRUE;
}
static size_t
-keylen(KEY s)
-{
+keylen(KEY s) {
size_t len = 0;
- for (; *s; s++, len++);
+ for (; *s; s++, len++)
+ ;
return len;
}
static void
-copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key)
-{
+copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key) {
key->k[0] = 0;
key->k[1] = get_hash_secret_salt(parser);
}
static unsigned long FASTCALL
-hash(XML_Parser parser, KEY s)
-{
+hash(XML_Parser parser, KEY s) {
struct siphash state;
struct sipkey key;
(void)sip24_valid;
}
static NAMED *
-lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize)
-{
+lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) {
size_t i;
if (table->size == 0) {
size_t tsize;
- if (!createSize)
+ if (! createSize)
return NULL;
table->power = INIT_POWER;
/* table->size is a power of 2 */
table->size = (size_t)1 << INIT_POWER;
tsize = table->size * sizeof(NAMED *);
table->v = (NAMED **)table->mem->malloc_fcn(tsize);
- if (!table->v) {
+ if (! table->v) {
table->size = 0;
return NULL;
}
memset(table->v, 0, tsize);
i = hash(parser, name) & ((unsigned long)table->size - 1);
- }
- else {
+ } else {
unsigned long h = hash(parser, name);
unsigned long mask = (unsigned long)table->size - 1;
unsigned char step = 0;
while (table->v[i]) {
if (keyeq(name, table->v[i]->name))
return table->v[i];
- if (!step)
+ if (! step)
step = PROBE_STEP(h, mask, table->power);
i < step ? (i += table->size - step) : (i -= step);
}
- if (!createSize)
+ if (! createSize)
return NULL;
/* check for overflow (table is half full) */
unsigned long newMask = (unsigned long)newSize - 1;
size_t tsize = newSize * sizeof(NAMED *);
NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
- if (!newV)
+ if (! newV)
return NULL;
memset(newV, 0, tsize);
for (i = 0; i < table->size; i++)
size_t j = newHash & newMask;
step = 0;
while (newV[j]) {
- if (!step)
+ if (! step)
step = PROBE_STEP(newHash, newMask, newPower);
j < step ? (j += newSize - step) : (j -= step);
}
i = h & newMask;
step = 0;
while (table->v[i]) {
- if (!step)
+ if (! step)
step = PROBE_STEP(h, newMask, newPower);
i < step ? (i += newSize - step) : (i -= step);
}
}
}
table->v[i] = (NAMED *)table->mem->malloc_fcn(createSize);
- if (!table->v[i])
+ if (! table->v[i])
return NULL;
memset(table->v[i], 0, createSize);
table->v[i]->name = name;
}
static void FASTCALL
-hashTableClear(HASH_TABLE *table)
-{
+hashTableClear(HASH_TABLE *table) {
size_t i;
for (i = 0; i < table->size; i++) {
table->mem->free_fcn(table->v[i]);
}
static void FASTCALL
-hashTableDestroy(HASH_TABLE *table)
-{
+hashTableDestroy(HASH_TABLE *table) {
size_t i;
for (i = 0; i < table->size; i++)
table->mem->free_fcn(table->v[i]);
}
static void FASTCALL
-hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms)
-{
+hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms) {
p->power = 0;
p->size = 0;
p->used = 0;
}
static void FASTCALL
-hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
-{
+hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) {
iter->p = table->v;
iter->end = iter->p + table->size;
}
-static NAMED * FASTCALL
-hashTableIterNext(HASH_TABLE_ITER *iter)
-{
+static NAMED *FASTCALL
+hashTableIterNext(HASH_TABLE_ITER *iter) {
while (iter->p != iter->end) {
NAMED *tem = *(iter->p)++;
if (tem)
}
static void FASTCALL
-poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms)
-{
+poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms) {
pool->blocks = NULL;
pool->freeBlocks = NULL;
pool->start = NULL;
}
static void FASTCALL
-poolClear(STRING_POOL *pool)
-{
- if (!pool->freeBlocks)
+poolClear(STRING_POOL *pool) {
+ if (! pool->freeBlocks)
pool->freeBlocks = pool->blocks;
else {
BLOCK *p = pool->blocks;
}
static void FASTCALL
-poolDestroy(STRING_POOL *pool)
-{
+poolDestroy(STRING_POOL *pool) {
BLOCK *p = pool->blocks;
while (p) {
BLOCK *tem = p->next;
}
static XML_Char *
-poolAppend(STRING_POOL *pool, const ENCODING *enc,
- const char *ptr, const char *end)
-{
- if (!pool->ptr && !poolGrow(pool))
+poolAppend(STRING_POOL *pool, const ENCODING *enc, const char *ptr,
+ const char *end) {
+ if (! pool->ptr && ! poolGrow(pool))
return NULL;
for (;;) {
- const enum XML_Convert_Result convert_res = XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
- if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
+ const enum XML_Convert_Result convert_res = XmlConvert(
+ enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
+ if ((convert_res == XML_CONVERT_COMPLETED)
+ || (convert_res == XML_CONVERT_INPUT_INCOMPLETE))
break;
- if (!poolGrow(pool))
+ if (! poolGrow(pool))
return NULL;
}
return pool->start;
}
-static const XML_Char * FASTCALL
-poolCopyString(STRING_POOL *pool, const XML_Char *s)
-{
+static const XML_Char *FASTCALL
+poolCopyString(STRING_POOL *pool, const XML_Char *s) {
do {
- if (!poolAppendChar(pool, *s))
+ if (! poolAppendChar(pool, *s))
return NULL;
} while (*s++);
s = pool->start;
}
static const XML_Char *
-poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
-{
- if (!pool->ptr && !poolGrow(pool)) {
+poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n) {
+ if (! pool->ptr && ! poolGrow(pool)) {
/* The following line is unreachable given the current usage of
* poolCopyStringN(). Currently it is called from exactly one
* place to copy the text of a simple general entity. By that
return NULL; /* LCOV_EXCL_LINE */
}
for (; n > 0; --n, s++) {
- if (!poolAppendChar(pool, *s))
+ if (! poolAppendChar(pool, *s))
return NULL;
}
s = pool->start;
return s;
}
-static const XML_Char * FASTCALL
-poolAppendString(STRING_POOL *pool, const XML_Char *s)
-{
+static const XML_Char *FASTCALL
+poolAppendString(STRING_POOL *pool, const XML_Char *s) {
while (*s) {
- if (!poolAppendChar(pool, *s))
+ if (! poolAppendChar(pool, *s))
return NULL;
s++;
}
}
static XML_Char *
-poolStoreString(STRING_POOL *pool, const ENCODING *enc,
- const char *ptr, const char *end)
-{
- if (!poolAppend(pool, enc, ptr, end))
+poolStoreString(STRING_POOL *pool, const ENCODING *enc, const char *ptr,
+ const char *end) {
+ if (! poolAppend(pool, enc, ptr, end))
return NULL;
- if (pool->ptr == pool->end && !poolGrow(pool))
+ if (pool->ptr == pool->end && ! poolGrow(pool))
return NULL;
*(pool->ptr)++ = 0;
return pool->start;
}
static size_t
-poolBytesToAllocateFor(int blockSize)
-{
+poolBytesToAllocateFor(int blockSize) {
/* Unprotected math would be:
** return offsetof(BLOCK, s) + blockSize * sizeof(XML_Char);
**
** For a + b * c we check b * c in isolation first, so that addition of a
** on top has no chance of making us accept a small non-negative number
*/
- const size_t stretch = sizeof(XML_Char); /* can be 4 bytes */
+ const size_t stretch = sizeof(XML_Char); /* can be 4 bytes */
if (blockSize <= 0)
return 0;
{
const int stretchedBlockSize = blockSize * (int)stretch;
- const int bytesToAllocate = (int)(
- offsetof(BLOCK, s) + (unsigned)stretchedBlockSize);
+ const int bytesToAllocate
+ = (int)(offsetof(BLOCK, s) + (unsigned)stretchedBlockSize);
if (bytesToAllocate < 0)
return 0;
}
static XML_Bool FASTCALL
-poolGrow(STRING_POOL *pool)
-{
+poolGrow(STRING_POOL *pool) {
if (pool->freeBlocks) {
if (pool->start == 0) {
pool->blocks = pool->freeBlocks;
}
if (pool->blocks && pool->start == pool->blocks->s) {
BLOCK *temp;
- int blockSize = (int)((unsigned)(pool->end - pool->start)*2U);
+ int blockSize = (int)((unsigned)(pool->end - pool->start) * 2U);
size_t bytesToAllocate;
/* NOTE: Needs to be calculated prior to calling `realloc`
if (bytesToAllocate == 0)
return XML_FALSE;
- temp = (BLOCK *)
- pool->mem->realloc_fcn(pool->blocks, (unsigned)bytesToAllocate);
+ temp = (BLOCK *)pool->mem->realloc_fcn(pool->blocks,
+ (unsigned)bytesToAllocate);
if (temp == NULL)
return XML_FALSE;
pool->blocks = temp;
pool->ptr = pool->blocks->s + offsetInsideBlock;
pool->start = pool->blocks->s;
pool->end = pool->start + blockSize;
- }
- else {
+ } else {
BLOCK *tem;
int blockSize = (int)(pool->end - pool->start);
size_t bytesToAllocate;
* function). Either way it isn't readily testable, so we
* exclude it from the coverage statistics.
*/
- return XML_FALSE; /* LCOV_EXCL_LINE */
+ return XML_FALSE; /* LCOV_EXCL_LINE */
}
if (blockSize < INIT_BLOCK_SIZE)
return XML_FALSE;
tem = (BLOCK *)pool->mem->malloc_fcn(bytesToAllocate);
- if (!tem)
+ if (! tem)
return XML_FALSE;
tem->size = blockSize;
tem->next = pool->blocks;
pool->blocks = tem;
if (pool->ptr != pool->start)
- memcpy(tem->s, pool->start,
- (pool->ptr - pool->start) * sizeof(XML_Char));
+ memcpy(tem->s, pool->start, (pool->ptr - pool->start) * sizeof(XML_Char));
pool->ptr = tem->s + (pool->ptr - pool->start);
pool->start = tem->s;
pool->end = tem->s + blockSize;
}
static int FASTCALL
-nextScaffoldPart(XML_Parser parser)
-{
- DTD * const dtd = parser->m_dtd; /* save one level of indirection */
- CONTENT_SCAFFOLD * me;
+nextScaffoldPart(XML_Parser parser) {
+ DTD *const dtd = parser->m_dtd; /* save one level of indirection */
+ CONTENT_SCAFFOLD *me;
int next;
- if (!dtd->scaffIndex) {
+ if (! dtd->scaffIndex) {
dtd->scaffIndex = (int *)MALLOC(parser, parser->m_groupSize * sizeof(int));
- if (!dtd->scaffIndex)
+ if (! dtd->scaffIndex)
return -1;
dtd->scaffIndex[0] = 0;
}
if (dtd->scaffCount >= dtd->scaffSize) {
CONTENT_SCAFFOLD *temp;
if (dtd->scaffold) {
- temp = (CONTENT_SCAFFOLD *)
- REALLOC(parser, dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
+ temp = (CONTENT_SCAFFOLD *)REALLOC(
+ parser, dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
if (temp == NULL)
return -1;
dtd->scaffSize *= 2;
- }
- else {
+ } else {
temp = (CONTENT_SCAFFOLD *)MALLOC(parser, INIT_SCAFFOLD_ELEMENTS
- * sizeof(CONTENT_SCAFFOLD));
+ * sizeof(CONTENT_SCAFFOLD));
if (temp == NULL)
return -1;
dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS;
next = dtd->scaffCount++;
me = &dtd->scaffold[next];
if (dtd->scaffLevel) {
- CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel-1]];
+ CONTENT_SCAFFOLD *parent
+ = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]];
if (parent->lastchild) {
dtd->scaffold[parent->lastchild].nextsib = next;
}
- if (!parent->childcnt)
+ if (! parent->childcnt)
parent->firstchild = next;
parent->lastchild = next;
parent->childcnt++;
}
static void
-build_node(XML_Parser parser,
- int src_node,
- XML_Content *dest,
- XML_Content **contpos,
- XML_Char **strpos)
-{
- DTD * const dtd = parser->m_dtd; /* save one level of indirection */
+build_node(XML_Parser parser, int src_node, XML_Content *dest,
+ XML_Content **contpos, XML_Char **strpos) {
+ DTD *const dtd = parser->m_dtd; /* save one level of indirection */
dest->type = dtd->scaffold[src_node].type;
dest->quant = dtd->scaffold[src_node].quant;
if (dest->type == XML_CTYPE_NAME) {
src = dtd->scaffold[src_node].name;
for (;;) {
*(*strpos)++ = *src;
- if (!*src)
+ if (! *src)
break;
src++;
}
dest->numchildren = 0;
dest->children = NULL;
- }
- else {
+ } else {
unsigned int i;
int cn;
dest->numchildren = dtd->scaffold[src_node].childcnt;
dest->children = *contpos;
*contpos += dest->numchildren;
- for (i = 0, cn = dtd->scaffold[src_node].firstchild;
- i < dest->numchildren;
+ for (i = 0, cn = dtd->scaffold[src_node].firstchild; i < dest->numchildren;
i++, cn = dtd->scaffold[cn].nextsib) {
build_node(parser, cn, &(dest->children[i]), contpos, strpos);
}
}
static XML_Content *
-build_model (XML_Parser parser)
-{
- DTD * const dtd = parser->m_dtd; /* save one level of indirection */
+build_model(XML_Parser parser) {
+ DTD *const dtd = parser->m_dtd; /* save one level of indirection */
XML_Content *ret;
XML_Content *cpos;
- XML_Char * str;
+ XML_Char *str;
int allocsize = (dtd->scaffCount * sizeof(XML_Content)
+ (dtd->contentStringLen * sizeof(XML_Char)));
ret = (XML_Content *)MALLOC(parser, allocsize);
- if (!ret)
+ if (! ret)
return NULL;
- str = (XML_Char *) (&ret[dtd->scaffCount]);
+ str = (XML_Char *)(&ret[dtd->scaffCount]);
cpos = &ret[1];
build_node(parser, 0, ret, &cpos, &str);
}
static ELEMENT_TYPE *
-getElementType(XML_Parser parser,
- const ENCODING *enc,
- const char *ptr,
- const char *end)
-{
- DTD * const dtd = parser->m_dtd; /* save one level of indirection */
+getElementType(XML_Parser parser, const ENCODING *enc, const char *ptr,
+ const char *end) {
+ DTD *const dtd = parser->m_dtd; /* save one level of indirection */
const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end);
ELEMENT_TYPE *ret;
- if (!name)
+ if (! name)
return NULL;
- ret = (ELEMENT_TYPE *) lookup(parser, &dtd->elementTypes, name, sizeof(ELEMENT_TYPE));
- if (!ret)
+ ret = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name,
+ sizeof(ELEMENT_TYPE));
+ if (! ret)
return NULL;
if (ret->name != name)
poolDiscard(&dtd->pool);
else {
poolFinish(&dtd->pool);
- if (!setElementTypePrefix(parser, ret))
+ if (! setElementTypePrefix(parser, ret))
return NULL;
}
return ret;
}
static XML_Char *
-copyString(const XML_Char *s,
- const XML_Memory_Handling_Suite *memsuite)
-{
- int charsRequired = 0;
- XML_Char *result;
-
- /* First determine how long the string is */
- while (s[charsRequired] != 0) {
- charsRequired++;
- }
- /* Include the terminator */
+copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) {
+ int charsRequired = 0;
+ XML_Char *result;
+
+ /* First determine how long the string is */
+ while (s[charsRequired] != 0) {
charsRequired++;
+ }
+ /* Include the terminator */
+ charsRequired++;
- /* Now allocate space for the copy */
- result = memsuite->malloc_fcn(charsRequired * sizeof(XML_Char));
- if (result == NULL)
- return NULL;
- /* Copy the original into place */
- memcpy(result, s, charsRequired * sizeof(XML_Char));
- return result;
+ /* Now allocate space for the copy */
+ result = memsuite->malloc_fcn(charsRequired * sizeof(XML_Char));
+ if (result == NULL)
+ return NULL;
+ /* Copy the original into place */
+ memcpy(result, s, charsRequired * sizeof(XML_Char));
+ return result;
}
#include <stddef.h>
#ifdef _WIN32
-#include "winconfig.h"
+# include "winconfig.h"
#else
-#ifdef HAVE_EXPAT_CONFIG_H
-#include <expat_config.h>
-#endif
+# ifdef HAVE_EXPAT_CONFIG_H
+# include <expat_config.h>
+# endif
#endif /* ndef _WIN32 */
#include "expat_external.h"
*/
-static const char KW_ANY[] = {
- ASCII_A, ASCII_N, ASCII_Y, '\0' };
-static const char KW_ATTLIST[] = {
- ASCII_A, ASCII_T, ASCII_T, ASCII_L, ASCII_I, ASCII_S, ASCII_T, '\0' };
-static const char KW_CDATA[] = {
- ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
-static const char KW_DOCTYPE[] = {
- ASCII_D, ASCII_O, ASCII_C, ASCII_T, ASCII_Y, ASCII_P, ASCII_E, '\0' };
-static const char KW_ELEMENT[] = {
- ASCII_E, ASCII_L, ASCII_E, ASCII_M, ASCII_E, ASCII_N, ASCII_T, '\0' };
-static const char KW_EMPTY[] = {
- ASCII_E, ASCII_M, ASCII_P, ASCII_T, ASCII_Y, '\0' };
-static const char KW_ENTITIES[] = {
- ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S,
- '\0' };
-static const char KW_ENTITY[] = {
- ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' };
-static const char KW_FIXED[] = {
- ASCII_F, ASCII_I, ASCII_X, ASCII_E, ASCII_D, '\0' };
-static const char KW_ID[] = {
- ASCII_I, ASCII_D, '\0' };
-static const char KW_IDREF[] = {
- ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' };
-static const char KW_IDREFS[] = {
- ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' };
+static const char KW_ANY[] = {ASCII_A, ASCII_N, ASCII_Y, '\0'};
+static const char KW_ATTLIST[]
+ = {ASCII_A, ASCII_T, ASCII_T, ASCII_L, ASCII_I, ASCII_S, ASCII_T, '\0'};
+static const char KW_CDATA[]
+ = {ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0'};
+static const char KW_DOCTYPE[]
+ = {ASCII_D, ASCII_O, ASCII_C, ASCII_T, ASCII_Y, ASCII_P, ASCII_E, '\0'};
+static const char KW_ELEMENT[]
+ = {ASCII_E, ASCII_L, ASCII_E, ASCII_M, ASCII_E, ASCII_N, ASCII_T, '\0'};
+static const char KW_EMPTY[]
+ = {ASCII_E, ASCII_M, ASCII_P, ASCII_T, ASCII_Y, '\0'};
+static const char KW_ENTITIES[] = {ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T,
+ ASCII_I, ASCII_E, ASCII_S, '\0'};
+static const char KW_ENTITY[]
+ = {ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0'};
+static const char KW_FIXED[]
+ = {ASCII_F, ASCII_I, ASCII_X, ASCII_E, ASCII_D, '\0'};
+static const char KW_ID[] = {ASCII_I, ASCII_D, '\0'};
+static const char KW_IDREF[]
+ = {ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0'};
+static const char KW_IDREFS[]
+ = {ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0'};
#ifdef XML_DTD
-static const char KW_IGNORE[] = {
- ASCII_I, ASCII_G, ASCII_N, ASCII_O, ASCII_R, ASCII_E, '\0' };
+static const char KW_IGNORE[]
+ = {ASCII_I, ASCII_G, ASCII_N, ASCII_O, ASCII_R, ASCII_E, '\0'};
#endif
-static const char KW_IMPLIED[] = {
- ASCII_I, ASCII_M, ASCII_P, ASCII_L, ASCII_I, ASCII_E, ASCII_D, '\0' };
+static const char KW_IMPLIED[]
+ = {ASCII_I, ASCII_M, ASCII_P, ASCII_L, ASCII_I, ASCII_E, ASCII_D, '\0'};
#ifdef XML_DTD
-static const char KW_INCLUDE[] = {
- ASCII_I, ASCII_N, ASCII_C, ASCII_L, ASCII_U, ASCII_D, ASCII_E, '\0' };
+static const char KW_INCLUDE[]
+ = {ASCII_I, ASCII_N, ASCII_C, ASCII_L, ASCII_U, ASCII_D, ASCII_E, '\0'};
#endif
-static const char KW_NDATA[] = {
- ASCII_N, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
-static const char KW_NMTOKEN[] = {
- ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' };
-static const char KW_NMTOKENS[] = {
- ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S,
- '\0' };
-static const char KW_NOTATION[] =
- { ASCII_N, ASCII_O, ASCII_T, ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N,
- '\0' };
-static const char KW_PCDATA[] = {
- ASCII_P, ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
-static const char KW_PUBLIC[] = {
- ASCII_P, ASCII_U, ASCII_B, ASCII_L, ASCII_I, ASCII_C, '\0' };
-static const char KW_REQUIRED[] = {
- ASCII_R, ASCII_E, ASCII_Q, ASCII_U, ASCII_I, ASCII_R, ASCII_E, ASCII_D,
- '\0' };
-static const char KW_SYSTEM[] = {
- ASCII_S, ASCII_Y, ASCII_S, ASCII_T, ASCII_E, ASCII_M, '\0' };
+static const char KW_NDATA[]
+ = {ASCII_N, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0'};
+static const char KW_NMTOKEN[]
+ = {ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0'};
+static const char KW_NMTOKENS[] = {ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K,
+ ASCII_E, ASCII_N, ASCII_S, '\0'};
+static const char KW_NOTATION[] = {ASCII_N, ASCII_O, ASCII_T, ASCII_A, ASCII_T,
+ ASCII_I, ASCII_O, ASCII_N, '\0'};
+static const char KW_PCDATA[]
+ = {ASCII_P, ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0'};
+static const char KW_PUBLIC[]
+ = {ASCII_P, ASCII_U, ASCII_B, ASCII_L, ASCII_I, ASCII_C, '\0'};
+static const char KW_REQUIRED[] = {ASCII_R, ASCII_E, ASCII_Q, ASCII_U, ASCII_I,
+ ASCII_R, ASCII_E, ASCII_D, '\0'};
+static const char KW_SYSTEM[]
+ = {ASCII_S, ASCII_Y, ASCII_S, ASCII_T, ASCII_E, ASCII_M, '\0'};
#ifndef MIN_BYTES_PER_CHAR
-#define MIN_BYTES_PER_CHAR(enc) ((enc)->minBytesPerChar)
+# define MIN_BYTES_PER_CHAR(enc) ((enc)->minBytesPerChar)
#endif
#ifdef XML_DTD
-#define setTopLevel(state) \
- ((state)->handler = ((state)->documentEntity \
- ? internalSubset \
- : externalSubset1))
+# define setTopLevel(state) \
+ ((state)->handler \
+ = ((state)->documentEntity ? internalSubset : externalSubset1))
#else /* not XML_DTD */
-#define setTopLevel(state) ((state)->handler = internalSubset)
+# define setTopLevel(state) ((state)->handler = internalSubset)
#endif /* not XML_DTD */
-typedef int PTRCALL PROLOG_HANDLER(PROLOG_STATE *state,
- int tok,
- const char *ptr,
- const char *end,
+typedef int PTRCALL PROLOG_HANDLER(PROLOG_STATE *state, int tok,
+ const char *ptr, const char *end,
const ENCODING *enc);
-static PROLOG_HANDLER
- prolog0, prolog1, prolog2,
- doctype0, doctype1, doctype2, doctype3, doctype4, doctype5,
- internalSubset,
- entity0, entity1, entity2, entity3, entity4, entity5, entity6,
- entity7, entity8, entity9, entity10,
- notation0, notation1, notation2, notation3, notation4,
- attlist0, attlist1, attlist2, attlist3, attlist4, attlist5, attlist6,
- attlist7, attlist8, attlist9,
- element0, element1, element2, element3, element4, element5, element6,
- element7,
+static PROLOG_HANDLER prolog0, prolog1, prolog2, doctype0, doctype1, doctype2,
+ doctype3, doctype4, doctype5, internalSubset, entity0, entity1, entity2,
+ entity3, entity4, entity5, entity6, entity7, entity8, entity9, entity10,
+ notation0, notation1, notation2, notation3, notation4, attlist0, attlist1,
+ attlist2, attlist3, attlist4, attlist5, attlist6, attlist7, attlist8,
+ attlist9, element0, element1, element2, element3, element4, element5,
+ element6, element7,
#ifdef XML_DTD
- externalSubset0, externalSubset1,
- condSect0, condSect1, condSect2,
+ externalSubset0, externalSubset1, condSect0, condSect1, condSect2,
#endif /* XML_DTD */
- declClose,
- error;
+ declClose, error;
static int FASTCALL common(PROLOG_STATE *state, int tok);
static int PTRCALL
-prolog0(PROLOG_STATE *state,
- int tok,
- const char *ptr,
- const char *end,
- const ENCODING *enc)
-{
+prolog0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
switch (tok) {
case XML_TOK_PROLOG_S:
state->handler = prolog1;
case XML_TOK_BOM:
return XML_ROLE_NONE;
case XML_TOK_DECL_OPEN:
- if (!XmlNameMatchesAscii(enc,
- ptr + 2 * MIN_BYTES_PER_CHAR(enc),
- end,
- KW_DOCTYPE))
+ if (! XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end,
+ KW_DOCTYPE))
break;
state->handler = doctype0;
return XML_ROLE_DOCTYPE_NONE;
}
static int PTRCALL
-prolog1(PROLOG_STATE *state,
- int tok,
- const char *ptr,
- const char *end,
- const ENCODING *enc)
-{
+prolog1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_NONE;
*/
return XML_ROLE_NONE; /* LCOV_EXCL_LINE */
case XML_TOK_DECL_OPEN:
- if (!XmlNameMatchesAscii(enc,
- ptr + 2 * MIN_BYTES_PER_CHAR(enc),
- end,
- KW_DOCTYPE))
+ if (! XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end,
+ KW_DOCTYPE))
break;
state->handler = doctype0;
return XML_ROLE_DOCTYPE_NONE;
}
static int PTRCALL
-prolog2(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+prolog2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_NONE;
}
static int PTRCALL
-doctype0(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+doctype0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_DOCTYPE_NONE;
}
static int PTRCALL
-doctype1(PROLOG_STATE *state,
- int tok,
- const char *ptr,
- const char *end,
- const ENCODING *enc)
-{
+doctype1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_DOCTYPE_NONE;
}
static int PTRCALL
-doctype2(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+doctype2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_DOCTYPE_NONE;
}
static int PTRCALL
-doctype3(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+doctype3(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_DOCTYPE_NONE;
}
static int PTRCALL
-doctype4(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+doctype4(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_DOCTYPE_NONE;
}
static int PTRCALL
-doctype5(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+doctype5(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_DOCTYPE_NONE;
}
static int PTRCALL
-internalSubset(PROLOG_STATE *state,
- int tok,
- const char *ptr,
- const char *end,
- const ENCODING *enc)
-{
+internalSubset(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_NONE;
case XML_TOK_DECL_OPEN:
- if (XmlNameMatchesAscii(enc,
- ptr + 2 * MIN_BYTES_PER_CHAR(enc),
- end,
+ if (XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end,
KW_ENTITY)) {
state->handler = entity0;
return XML_ROLE_ENTITY_NONE;
}
- if (XmlNameMatchesAscii(enc,
- ptr + 2 * MIN_BYTES_PER_CHAR(enc),
- end,
+ if (XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end,
KW_ATTLIST)) {
state->handler = attlist0;
return XML_ROLE_ATTLIST_NONE;
}
- if (XmlNameMatchesAscii(enc,
- ptr + 2 * MIN_BYTES_PER_CHAR(enc),
- end,
+ if (XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end,
KW_ELEMENT)) {
state->handler = element0;
return XML_ROLE_ELEMENT_NONE;
}
- if (XmlNameMatchesAscii(enc,
- ptr + 2 * MIN_BYTES_PER_CHAR(enc),
- end,
+ if (XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end,
KW_NOTATION)) {
state->handler = notation0;
return XML_ROLE_NOTATION_NONE;
#ifdef XML_DTD
static int PTRCALL
-externalSubset0(PROLOG_STATE *state,
- int tok,
- const char *ptr,
- const char *end,
- const ENCODING *enc)
-{
+externalSubset0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
state->handler = externalSubset1;
if (tok == XML_TOK_XML_DECL)
return XML_ROLE_TEXT_DECL;
}
static int PTRCALL
-externalSubset1(PROLOG_STATE *state,
- int tok,
- const char *ptr,
- const char *end,
- const ENCODING *enc)
-{
+externalSubset1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
switch (tok) {
case XML_TOK_COND_SECT_OPEN:
state->handler = condSect0;
#endif /* XML_DTD */
static int PTRCALL
-entity0(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+entity0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ENTITY_NONE;
}
static int PTRCALL
-entity1(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+entity1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ENTITY_NONE;
}
static int PTRCALL
-entity2(PROLOG_STATE *state,
- int tok,
- const char *ptr,
- const char *end,
- const ENCODING *enc)
-{
+entity2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ENTITY_NONE;
}
static int PTRCALL
-entity3(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+entity3(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ENTITY_NONE;
}
static int PTRCALL
-entity4(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+entity4(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ENTITY_NONE;
}
static int PTRCALL
-entity5(PROLOG_STATE *state,
- int tok,
- const char *ptr,
- const char *end,
- const ENCODING *enc)
-{
+entity5(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ENTITY_NONE;
}
static int PTRCALL
-entity6(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+entity6(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ENTITY_NONE;
}
static int PTRCALL
-entity7(PROLOG_STATE *state,
- int tok,
- const char *ptr,
- const char *end,
- const ENCODING *enc)
-{
+entity7(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ENTITY_NONE;
}
static int PTRCALL
-entity8(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+entity8(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ENTITY_NONE;
}
static int PTRCALL
-entity9(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+entity9(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ENTITY_NONE;
}
static int PTRCALL
-entity10(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+entity10(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ENTITY_NONE;
}
static int PTRCALL
-notation0(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+notation0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_NOTATION_NONE;
}
static int PTRCALL
-notation1(PROLOG_STATE *state,
- int tok,
- const char *ptr,
- const char *end,
- const ENCODING *enc)
-{
+notation1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_NOTATION_NONE;
}
static int PTRCALL
-notation2(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+notation2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_NOTATION_NONE;
}
static int PTRCALL
-notation3(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+notation3(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_NOTATION_NONE;
}
static int PTRCALL
-notation4(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+notation4(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_NOTATION_NONE;
}
static int PTRCALL
-attlist0(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+attlist0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ATTLIST_NONE;
}
static int PTRCALL
-attlist1(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+attlist1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ATTLIST_NONE;
}
static int PTRCALL
-attlist2(PROLOG_STATE *state,
- int tok,
- const char *ptr,
- const char *end,
- const ENCODING *enc)
-{
+attlist2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ATTLIST_NONE;
- case XML_TOK_NAME:
- {
- static const char * const types[] = {
- KW_CDATA,
- KW_ID,
- KW_IDREF,
- KW_IDREFS,
- KW_ENTITY,
- KW_ENTITIES,
- KW_NMTOKEN,
- KW_NMTOKENS,
- };
- int i;
- for (i = 0; i < (int)(sizeof(types)/sizeof(types[0])); i++)
- if (XmlNameMatchesAscii(enc, ptr, end, types[i])) {
- state->handler = attlist8;
- return XML_ROLE_ATTRIBUTE_TYPE_CDATA + i;
- }
- }
+ case XML_TOK_NAME: {
+ static const char *const types[] = {
+ KW_CDATA, KW_ID, KW_IDREF, KW_IDREFS,
+ KW_ENTITY, KW_ENTITIES, KW_NMTOKEN, KW_NMTOKENS,
+ };
+ int i;
+ for (i = 0; i < (int)(sizeof(types) / sizeof(types[0])); i++)
+ if (XmlNameMatchesAscii(enc, ptr, end, types[i])) {
+ state->handler = attlist8;
+ return XML_ROLE_ATTRIBUTE_TYPE_CDATA + i;
+ }
+ }
if (XmlNameMatchesAscii(enc, ptr, end, KW_NOTATION)) {
state->handler = attlist5;
return XML_ROLE_ATTLIST_NONE;
}
static int PTRCALL
-attlist3(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+attlist3(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ATTLIST_NONE;
}
static int PTRCALL
-attlist4(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+attlist4(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ATTLIST_NONE;
}
static int PTRCALL
-attlist5(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+attlist5(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ATTLIST_NONE;
}
static int PTRCALL
-attlist6(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+attlist6(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ATTLIST_NONE;
}
static int PTRCALL
-attlist7(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+attlist7(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ATTLIST_NONE;
/* default value */
static int PTRCALL
-attlist8(PROLOG_STATE *state,
- int tok,
- const char *ptr,
- const char *end,
- const ENCODING *enc)
-{
+attlist8(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ATTLIST_NONE;
case XML_TOK_POUND_NAME:
- if (XmlNameMatchesAscii(enc,
- ptr + MIN_BYTES_PER_CHAR(enc),
- end,
+ if (XmlNameMatchesAscii(enc, ptr + MIN_BYTES_PER_CHAR(enc), end,
KW_IMPLIED)) {
state->handler = attlist1;
return XML_ROLE_IMPLIED_ATTRIBUTE_VALUE;
}
- if (XmlNameMatchesAscii(enc,
- ptr + MIN_BYTES_PER_CHAR(enc),
- end,
+ if (XmlNameMatchesAscii(enc, ptr + MIN_BYTES_PER_CHAR(enc), end,
KW_REQUIRED)) {
state->handler = attlist1;
return XML_ROLE_REQUIRED_ATTRIBUTE_VALUE;
}
- if (XmlNameMatchesAscii(enc,
- ptr + MIN_BYTES_PER_CHAR(enc),
- end,
+ if (XmlNameMatchesAscii(enc, ptr + MIN_BYTES_PER_CHAR(enc), end,
KW_FIXED)) {
state->handler = attlist9;
return XML_ROLE_ATTLIST_NONE;
}
static int PTRCALL
-attlist9(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+attlist9(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ATTLIST_NONE;
}
static int PTRCALL
-element0(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+element0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ELEMENT_NONE;
}
static int PTRCALL
-element1(PROLOG_STATE *state,
- int tok,
- const char *ptr,
- const char *end,
- const ENCODING *enc)
-{
+element1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ELEMENT_NONE;
}
static int PTRCALL
-element2(PROLOG_STATE *state,
- int tok,
- const char *ptr,
- const char *end,
- const ENCODING *enc)
-{
+element2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ELEMENT_NONE;
case XML_TOK_POUND_NAME:
- if (XmlNameMatchesAscii(enc,
- ptr + MIN_BYTES_PER_CHAR(enc),
- end,
+ if (XmlNameMatchesAscii(enc, ptr + MIN_BYTES_PER_CHAR(enc), end,
KW_PCDATA)) {
state->handler = element3;
return XML_ROLE_CONTENT_PCDATA;
}
static int PTRCALL
-element3(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+element3(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ELEMENT_NONE;
}
static int PTRCALL
-element4(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+element4(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ELEMENT_NONE;
}
static int PTRCALL
-element5(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+element5(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ELEMENT_NONE;
}
static int PTRCALL
-element6(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+element6(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ELEMENT_NONE;
}
static int PTRCALL
-element7(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+element7(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_ELEMENT_NONE;
#ifdef XML_DTD
static int PTRCALL
-condSect0(PROLOG_STATE *state,
- int tok,
- const char *ptr,
- const char *end,
- const ENCODING *enc)
-{
+condSect0(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_NONE;
}
static int PTRCALL
-condSect1(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+condSect1(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_NONE;
}
static int PTRCALL
-condSect2(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+condSect2(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return XML_ROLE_NONE;
#endif /* XML_DTD */
static int PTRCALL
-declClose(PROLOG_STATE *state,
- int tok,
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+declClose(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
switch (tok) {
case XML_TOK_PROLOG_S:
return state->role_none;
* LCOV_EXCL_START
*/
static int PTRCALL
-error(PROLOG_STATE *UNUSED_P(state),
- int UNUSED_P(tok),
- const char *UNUSED_P(ptr),
- const char *UNUSED_P(end),
- const ENCODING *UNUSED_P(enc))
-{
+error(PROLOG_STATE *state, int tok, const char *ptr, const char *end,
+ const ENCODING *enc) {
+ UNUSED_P(state);
+ UNUSED_P(tok);
+ UNUSED_P(ptr);
+ UNUSED_P(end);
+ UNUSED_P(enc);
return XML_ROLE_NONE;
}
/* LCOV_EXCL_STOP */
static int FASTCALL
-common(PROLOG_STATE *state, int tok)
-{
+common(PROLOG_STATE *state, int tok) {
#ifdef XML_DTD
- if (!state->documentEntity && tok == XML_TOK_PARAM_ENTITY_REF)
+ if (! state->documentEntity && tok == XML_TOK_PARAM_ENTITY_REF)
return XML_ROLE_INNER_PARAM_ENTITY_REF;
#endif
state->handler = error;
}
void
-XmlPrologStateInit(PROLOG_STATE *state)
-{
+XmlPrologStateInit(PROLOG_STATE *state) {
state->handler = prolog0;
#ifdef XML_DTD
state->documentEntity = 1;
#ifdef XML_DTD
void
-XmlPrologStateInitExternalEntity(PROLOG_STATE *state)
-{
+XmlPrologStateInitExternalEntity(PROLOG_STATE *state) {
state->handler = externalSubset0;
state->documentEntity = 0;
state->includeLevel = 0;
#ifdef __VMS
/* 0 1 2 3 0 1 2 3
1234567890123456789012345678901 1234567890123456789012345678901 */
-#define XmlPrologStateInitExternalEntity XmlPrologStateInitExternalEnt
+# define XmlPrologStateInitExternalEntity XmlPrologStateInitExternalEnt
#endif
#include "xmltok.h"
};
typedef struct prolog_state {
- int (PTRCALL *handler) (struct prolog_state *state,
- int tok,
- const char *ptr,
- const char *end,
- const ENCODING *enc);
+ int(PTRCALL *handler)(struct prolog_state *state, int tok, const char *ptr,
+ const char *end, const ENCODING *enc);
unsigned level;
int role_none;
#ifdef XML_DTD
void XmlPrologStateInitExternalEntity(PROLOG_STATE *);
#endif /* XML_DTD */
-#define XmlTokenRole(state, tok, ptr, end, enc) \
- (((state)->handler)(state, tok, ptr, end, enc))
+#define XmlTokenRole(state, tok, ptr, end, enc) \
+ (((state)->handler)(state, tok, ptr, end, enc))
#ifdef __cplusplus
}
*/
#include <stddef.h>
-#include <string.h> /* memcpy */
+#include <string.h> /* memcpy */
#if defined(_MSC_VER) && (_MSC_VER <= 1700)
- /* for vs2012/11.0/1700 and earlier Visual Studio compilers */
-# define bool int
-# define false 0
-# define true 1
+/* for vs2012/11.0/1700 and earlier Visual Studio compilers */
+# define bool int
+# define false 0
+# define true 1
#else
-# include <stdbool.h>
+# include <stdbool.h>
#endif
-
#ifdef _WIN32
-#include "winconfig.h"
+# include "winconfig.h"
#else
-#ifdef HAVE_EXPAT_CONFIG_H
-#include <expat_config.h>
-#endif
+# ifdef HAVE_EXPAT_CONFIG_H
+# include <expat_config.h>
+# endif
#endif /* ndef _WIN32 */
#include "expat_external.h"
#include "nametab.h"
#ifdef XML_DTD
-#define IGNORE_SECTION_TOK_VTABLE , PREFIX(ignoreSectionTok)
+# define IGNORE_SECTION_TOK_VTABLE , PREFIX(ignoreSectionTok)
#else
-#define IGNORE_SECTION_TOK_VTABLE /* as nothing */
+# define IGNORE_SECTION_TOK_VTABLE /* as nothing */
#endif
-#define VTABLE1 \
- { PREFIX(prologTok), PREFIX(contentTok), \
- PREFIX(cdataSectionTok) IGNORE_SECTION_TOK_VTABLE }, \
- { PREFIX(attributeValueTok), PREFIX(entityValueTok) }, \
- PREFIX(nameMatchesAscii), \
- PREFIX(nameLength), \
- PREFIX(skipS), \
- PREFIX(getAtts), \
- PREFIX(charRefNumber), \
- PREFIX(predefinedEntityName), \
- PREFIX(updatePosition), \
- PREFIX(isPublicId)
+#define VTABLE1 \
+ {PREFIX(prologTok), PREFIX(contentTok), \
+ PREFIX(cdataSectionTok) IGNORE_SECTION_TOK_VTABLE}, \
+ {PREFIX(attributeValueTok), PREFIX(entityValueTok)}, \
+ PREFIX(nameMatchesAscii), PREFIX(nameLength), PREFIX(skipS), \
+ PREFIX(getAtts), PREFIX(charRefNumber), PREFIX(predefinedEntityName), \
+ PREFIX(updatePosition), PREFIX(isPublicId)
#define VTABLE VTABLE1, PREFIX(toUtf8), PREFIX(toUtf16)
-#define UCS2_GET_NAMING(pages, hi, lo) \
- (namingBitmap[(pages[hi] << 3) + ((lo) >> 5)] & (1u << ((lo) & 0x1F)))
+#define UCS2_GET_NAMING(pages, hi, lo) \
+ (namingBitmap[(pages[hi] << 3) + ((lo) >> 5)] & (1u << ((lo)&0x1F)))
/* A 2 byte UTF-8 representation splits the characters 11 bits between
the bottom 5 and 6 bits of the bytes. We need 8 bits to index into
pages, 3 bits to add to that index and 5 bits to generate the mask.
*/
-#define UTF8_GET_NAMING2(pages, byte) \
- (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3) \
- + ((((byte)[0]) & 3) << 1) \
- + ((((byte)[1]) >> 5) & 1)] \
- & (1u << (((byte)[1]) & 0x1F)))
+#define UTF8_GET_NAMING2(pages, byte) \
+ (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3) \
+ + ((((byte)[0]) & 3) << 1) + ((((byte)[1]) >> 5) & 1)] \
+ & (1u << (((byte)[1]) & 0x1F)))
/* A 3 byte UTF-8 representation splits the characters 16 bits between
the bottom 4, 6 and 6 bits of the bytes. We need 8 bits to index
into pages, 3 bits to add to that index and 5 bits to generate the
mask.
*/
-#define UTF8_GET_NAMING3(pages, byte) \
- (namingBitmap[((pages)[((((byte)[0]) & 0xF) << 4) \
- + ((((byte)[1]) >> 2) & 0xF)] \
- << 3) \
- + ((((byte)[1]) & 3) << 1) \
- + ((((byte)[2]) >> 5) & 1)] \
- & (1u << (((byte)[2]) & 0x1F)))
-
-#define UTF8_GET_NAMING(pages, p, n) \
- ((n) == 2 \
- ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \
- : ((n) == 3 \
- ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) \
- : 0))
+#define UTF8_GET_NAMING3(pages, byte) \
+ (namingBitmap \
+ [((pages)[((((byte)[0]) & 0xF) << 4) + ((((byte)[1]) >> 2) & 0xF)] \
+ << 3) \
+ + ((((byte)[1]) & 3) << 1) + ((((byte)[2]) >> 5) & 1)] \
+ & (1u << (((byte)[2]) & 0x1F)))
+
+#define UTF8_GET_NAMING(pages, p, n) \
+ ((n) == 2 \
+ ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \
+ : ((n) == 3 ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) : 0))
/* Detection of invalid UTF-8 sequences is based on Table 3.1B
of Unicode 3.2: http://www.unicode.org/unicode/reports/tr28/
(A & 0xC0) == 0xC0 means A > 0xBF
*/
-#define UTF8_INVALID2(p) \
+#define UTF8_INVALID2(p) \
((*p) < 0xC2 || ((p)[1] & 0x80) == 0 || ((p)[1] & 0xC0) == 0xC0)
-#define UTF8_INVALID3(p) \
- (((p)[2] & 0x80) == 0 \
- || \
- ((*p) == 0xEF && (p)[1] == 0xBF \
- ? \
- (p)[2] > 0xBD \
- : \
- ((p)[2] & 0xC0) == 0xC0) \
- || \
- ((*p) == 0xE0 \
- ? \
- (p)[1] < 0xA0 || ((p)[1] & 0xC0) == 0xC0 \
- : \
- ((p)[1] & 0x80) == 0 \
- || \
- ((*p) == 0xED ? (p)[1] > 0x9F : ((p)[1] & 0xC0) == 0xC0)))
-
-#define UTF8_INVALID4(p) \
- (((p)[3] & 0x80) == 0 || ((p)[3] & 0xC0) == 0xC0 \
- || \
- ((p)[2] & 0x80) == 0 || ((p)[2] & 0xC0) == 0xC0 \
- || \
- ((*p) == 0xF0 \
- ? \
- (p)[1] < 0x90 || ((p)[1] & 0xC0) == 0xC0 \
- : \
- ((p)[1] & 0x80) == 0 \
- || \
- ((*p) == 0xF4 ? (p)[1] > 0x8F : ((p)[1] & 0xC0) == 0xC0)))
+#define UTF8_INVALID3(p) \
+ (((p)[2] & 0x80) == 0 \
+ || ((*p) == 0xEF && (p)[1] == 0xBF ? (p)[2] > 0xBD \
+ : ((p)[2] & 0xC0) == 0xC0) \
+ || ((*p) == 0xE0 \
+ ? (p)[1] < 0xA0 || ((p)[1] & 0xC0) == 0xC0 \
+ : ((p)[1] & 0x80) == 0 \
+ || ((*p) == 0xED ? (p)[1] > 0x9F : ((p)[1] & 0xC0) == 0xC0)))
+
+#define UTF8_INVALID4(p) \
+ (((p)[3] & 0x80) == 0 || ((p)[3] & 0xC0) == 0xC0 || ((p)[2] & 0x80) == 0 \
+ || ((p)[2] & 0xC0) == 0xC0 \
+ || ((*p) == 0xF0 \
+ ? (p)[1] < 0x90 || ((p)[1] & 0xC0) == 0xC0 \
+ : ((p)[1] & 0x80) == 0 \
+ || ((*p) == 0xF4 ? (p)[1] > 0x8F : ((p)[1] & 0xC0) == 0xC0)))
static int PTRFASTCALL
-isNever(const ENCODING *UNUSED_P(enc), const char *UNUSED_P(p))
-{
+isNever(const ENCODING *enc, const char *p) {
+ UNUSED_P(enc);
+ UNUSED_P(p);
return 0;
}
static int PTRFASTCALL
-utf8_isName2(const ENCODING *UNUSED_P(enc), const char *p)
-{
+utf8_isName2(const ENCODING *enc, const char *p) {
+ UNUSED_P(enc);
return UTF8_GET_NAMING2(namePages, (const unsigned char *)p);
}
static int PTRFASTCALL
-utf8_isName3(const ENCODING *UNUSED_P(enc), const char *p)
-{
+utf8_isName3(const ENCODING *enc, const char *p) {
+ UNUSED_P(enc);
return UTF8_GET_NAMING3(namePages, (const unsigned char *)p);
}
#define utf8_isName4 isNever
static int PTRFASTCALL
-utf8_isNmstrt2(const ENCODING *UNUSED_P(enc), const char *p)
-{
+utf8_isNmstrt2(const ENCODING *enc, const char *p) {
+ UNUSED_P(enc);
return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p);
}
static int PTRFASTCALL
-utf8_isNmstrt3(const ENCODING *UNUSED_P(enc), const char *p)
-{
+utf8_isNmstrt3(const ENCODING *enc, const char *p) {
+ UNUSED_P(enc);
return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p);
}
#define utf8_isNmstrt4 isNever
static int PTRFASTCALL
-utf8_isInvalid2(const ENCODING *UNUSED_P(enc), const char *p)
-{
+utf8_isInvalid2(const ENCODING *enc, const char *p) {
+ UNUSED_P(enc);
return UTF8_INVALID2((const unsigned char *)p);
}
static int PTRFASTCALL
-utf8_isInvalid3(const ENCODING *UNUSED_P(enc), const char *p)
-{
+utf8_isInvalid3(const ENCODING *enc, const char *p) {
+ UNUSED_P(enc);
return UTF8_INVALID3((const unsigned char *)p);
}
static int PTRFASTCALL
-utf8_isInvalid4(const ENCODING *UNUSED_P(enc), const char *p)
-{
+utf8_isInvalid4(const ENCODING *enc, const char *p) {
+ UNUSED_P(enc);
return UTF8_INVALID4((const unsigned char *)p);
}
ENCODING enc;
unsigned char type[256];
#ifdef XML_MIN_SIZE
- int (PTRFASTCALL *byteType)(const ENCODING *, const char *);
- int (PTRFASTCALL *isNameMin)(const ENCODING *, const char *);
- int (PTRFASTCALL *isNmstrtMin)(const ENCODING *, const char *);
- int (PTRFASTCALL *byteToAscii)(const ENCODING *, const char *);
- int (PTRCALL *charMatches)(const ENCODING *, const char *, int);
+ int(PTRFASTCALL *byteType)(const ENCODING *, const char *);
+ int(PTRFASTCALL *isNameMin)(const ENCODING *, const char *);
+ int(PTRFASTCALL *isNmstrtMin)(const ENCODING *, const char *);
+ int(PTRFASTCALL *byteToAscii)(const ENCODING *, const char *);
+ int(PTRCALL *charMatches)(const ENCODING *, const char *, int);
#endif /* XML_MIN_SIZE */
- int (PTRFASTCALL *isName2)(const ENCODING *, const char *);
- int (PTRFASTCALL *isName3)(const ENCODING *, const char *);
- int (PTRFASTCALL *isName4)(const ENCODING *, const char *);
- int (PTRFASTCALL *isNmstrt2)(const ENCODING *, const char *);
- int (PTRFASTCALL *isNmstrt3)(const ENCODING *, const char *);
- int (PTRFASTCALL *isNmstrt4)(const ENCODING *, const char *);
- int (PTRFASTCALL *isInvalid2)(const ENCODING *, const char *);
- int (PTRFASTCALL *isInvalid3)(const ENCODING *, const char *);
- int (PTRFASTCALL *isInvalid4)(const ENCODING *, const char *);
+ int(PTRFASTCALL *isName2)(const ENCODING *, const char *);
+ int(PTRFASTCALL *isName3)(const ENCODING *, const char *);
+ int(PTRFASTCALL *isName4)(const ENCODING *, const char *);
+ int(PTRFASTCALL *isNmstrt2)(const ENCODING *, const char *);
+ int(PTRFASTCALL *isNmstrt3)(const ENCODING *, const char *);
+ int(PTRFASTCALL *isNmstrt4)(const ENCODING *, const char *);
+ int(PTRFASTCALL *isInvalid2)(const ENCODING *, const char *);
+ int(PTRFASTCALL *isInvalid3)(const ENCODING *, const char *);
+ int(PTRFASTCALL *isInvalid4)(const ENCODING *, const char *);
};
-#define AS_NORMAL_ENCODING(enc) ((const struct normal_encoding *) (enc))
+#define AS_NORMAL_ENCODING(enc) ((const struct normal_encoding *)(enc))
#ifdef XML_MIN_SIZE
-#define STANDARD_VTABLE(E) \
- E ## byteType, \
- E ## isNameMin, \
- E ## isNmstrtMin, \
- E ## byteToAscii, \
- E ## charMatches,
+# define STANDARD_VTABLE(E) \
+ E##byteType, E##isNameMin, E##isNmstrtMin, E##byteToAscii, E##charMatches,
#else
-#define STANDARD_VTABLE(E) /* as nothing */
+# define STANDARD_VTABLE(E) /* as nothing */
#endif
-#define NORMAL_VTABLE(E) \
- E ## isName2, \
- E ## isName3, \
- E ## isName4, \
- E ## isNmstrt2, \
- E ## isNmstrt3, \
- E ## isNmstrt4, \
- E ## isInvalid2, \
- E ## isInvalid3, \
- E ## isInvalid4
-
-#define NULL_VTABLE \
- /* isName2 */ NULL, \
- /* isName3 */ NULL, \
- /* isName4 */ NULL, \
- /* isNmstrt2 */ NULL, \
- /* isNmstrt3 */ NULL, \
- /* isNmstrt4 */ NULL, \
- /* isInvalid2 */ NULL, \
- /* isInvalid3 */ NULL, \
- /* isInvalid4 */ NULL
+#define NORMAL_VTABLE(E) \
+ E##isName2, E##isName3, E##isName4, E##isNmstrt2, E##isNmstrt3, \
+ E##isNmstrt4, E##isInvalid2, E##isInvalid3, E##isInvalid4
+
+#define NULL_VTABLE \
+ /* isName2 */ NULL, /* isName3 */ NULL, /* isName4 */ NULL, \
+ /* isNmstrt2 */ NULL, /* isNmstrt3 */ NULL, /* isNmstrt4 */ NULL, \
+ /* isInvalid2 */ NULL, /* isInvalid3 */ NULL, /* isInvalid4 */ NULL
static int FASTCALL checkCharRefNumber(int);
#include "ascii.h"
#ifdef XML_MIN_SIZE
-#define sb_isNameMin isNever
-#define sb_isNmstrtMin isNever
+# define sb_isNameMin isNever
+# define sb_isNmstrtMin isNever
#endif
#ifdef XML_MIN_SIZE
-#define MINBPC(enc) ((enc)->minBytesPerChar)
+# define MINBPC(enc) ((enc)->minBytesPerChar)
#else
/* minimum bytes per character */
-#define MINBPC(enc) 1
+# define MINBPC(enc) 1
#endif
-#define SB_BYTE_TYPE(enc, p) \
+#define SB_BYTE_TYPE(enc, p) \
(((struct normal_encoding *)(enc))->type[(unsigned char)*(p)])
#ifdef XML_MIN_SIZE
static int PTRFASTCALL
-sb_byteType(const ENCODING *enc, const char *p)
-{
+sb_byteType(const ENCODING *enc, const char *p) {
return SB_BYTE_TYPE(enc, p);
}
-#define BYTE_TYPE(enc, p) \
- (AS_NORMAL_ENCODING(enc)->byteType(enc, p))
+# define BYTE_TYPE(enc, p) (AS_NORMAL_ENCODING(enc)->byteType(enc, p))
#else
-#define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p)
+# define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p)
#endif
#ifdef XML_MIN_SIZE
-#define BYTE_TO_ASCII(enc, p) \
- (AS_NORMAL_ENCODING(enc)->byteToAscii(enc, p))
+# define BYTE_TO_ASCII(enc, p) (AS_NORMAL_ENCODING(enc)->byteToAscii(enc, p))
static int PTRFASTCALL
-sb_byteToAscii(const ENCODING *enc, const char *p)
-{
+sb_byteToAscii(const ENCODING *enc, const char *p) {
+ UNUSED_P(enc);
return *p;
}
#else
-#define BYTE_TO_ASCII(enc, p) (*(p))
+# define BYTE_TO_ASCII(enc, p) (*(p))
#endif
-#define IS_NAME_CHAR(enc, p, n) \
- (AS_NORMAL_ENCODING(enc)->isName ## n(enc, p))
-#define IS_NMSTRT_CHAR(enc, p, n) \
- (AS_NORMAL_ENCODING(enc)->isNmstrt ## n(enc, p))
-#define IS_INVALID_CHAR(enc, p, n) \
- (AS_NORMAL_ENCODING(enc)->isInvalid ## n(enc, p))
+#define IS_NAME_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isName##n(enc, p))
+#define IS_NMSTRT_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isNmstrt##n(enc, p))
+#define IS_INVALID_CHAR(enc, p, n) \
+ (AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p))
#ifdef XML_MIN_SIZE
-#define IS_NAME_CHAR_MINBPC(enc, p) \
- (AS_NORMAL_ENCODING(enc)->isNameMin(enc, p))
-#define IS_NMSTRT_CHAR_MINBPC(enc, p) \
- (AS_NORMAL_ENCODING(enc)->isNmstrtMin(enc, p))
+# define IS_NAME_CHAR_MINBPC(enc, p) \
+ (AS_NORMAL_ENCODING(enc)->isNameMin(enc, p))
+# define IS_NMSTRT_CHAR_MINBPC(enc, p) \
+ (AS_NORMAL_ENCODING(enc)->isNmstrtMin(enc, p))
#else
-#define IS_NAME_CHAR_MINBPC(enc, p) (0)
-#define IS_NMSTRT_CHAR_MINBPC(enc, p) (0)
+# define IS_NAME_CHAR_MINBPC(enc, p) (0)
+# define IS_NMSTRT_CHAR_MINBPC(enc, p) (0)
#endif
#ifdef XML_MIN_SIZE
-#define CHAR_MATCHES(enc, p, c) \
- (AS_NORMAL_ENCODING(enc)->charMatches(enc, p, c))
+# define CHAR_MATCHES(enc, p, c) \
+ (AS_NORMAL_ENCODING(enc)->charMatches(enc, p, c))
static int PTRCALL
-sb_charMatches(const ENCODING *enc, const char *p, int c)
-{
+sb_charMatches(const ENCODING *enc, const char *p, int c) {
+ UNUSED_P(enc);
return *p == c;
}
#else
/* c is an ASCII character */
-#define CHAR_MATCHES(enc, p, c) (*(p) == c)
+# define CHAR_MATCHES(enc, p, c) (*(p) == c)
#endif
-#define PREFIX(ident) normal_ ## ident
+#define PREFIX(ident) normal_##ident
#define XML_TOK_IMPL_C
#include "xmltok_impl.c"
#undef XML_TOK_IMPL_C
#undef IS_NMSTRT_CHAR_MINBPC
#undef IS_INVALID_CHAR
-enum { /* UTF8_cvalN is value of masked first byte of N byte sequence */
- UTF8_cval1 = 0x00,
- UTF8_cval2 = 0xc0,
- UTF8_cval3 = 0xe0,
- UTF8_cval4 = 0xf0
+enum { /* UTF8_cvalN is value of masked first byte of N byte sequence */
+ UTF8_cval1 = 0x00,
+ UTF8_cval2 = 0xc0,
+ UTF8_cval3 = 0xe0,
+ UTF8_cval4 = 0xf0
};
void
-_INTERNAL_trim_to_complete_utf8_characters(const char * from, const char ** fromLimRef)
-{
- const char * fromLim = *fromLimRef;
+_INTERNAL_trim_to_complete_utf8_characters(const char *from,
+ const char **fromLimRef) {
+ const char *fromLim = *fromLimRef;
size_t walked = 0;
for (; fromLim > from; fromLim--, walked++) {
const unsigned char prev = (unsigned char)fromLim[-1];
- if ((prev & 0xf8u) == 0xf0u) { /* 4-byte character, lead by 0b11110xxx byte */
+ if ((prev & 0xf8u)
+ == 0xf0u) { /* 4-byte character, lead by 0b11110xxx byte */
if (walked + 1 >= 4) {
fromLim += 4 - 1;
break;
} else {
walked = 0;
}
- } else if ((prev & 0xf0u) == 0xe0u) { /* 3-byte character, lead by 0b1110xxxx byte */
+ } else if ((prev & 0xf0u)
+ == 0xe0u) { /* 3-byte character, lead by 0b1110xxxx byte */
if (walked + 1 >= 3) {
fromLim += 3 - 1;
break;
} else {
walked = 0;
}
- } else if ((prev & 0xe0u) == 0xc0u) { /* 2-byte character, lead by 0b110xxxxx byte */
+ } else if ((prev & 0xe0u)
+ == 0xc0u) { /* 2-byte character, lead by 0b110xxxxx byte */
if (walked + 1 >= 2) {
fromLim += 2 - 1;
break;
} else {
walked = 0;
}
- } else if ((prev & 0x80u) == 0x00u) { /* 1-byte character, matching 0b0xxxxxxx */
+ } else if ((prev & 0x80u)
+ == 0x00u) { /* 1-byte character, matching 0b0xxxxxxx */
break;
}
}
}
static enum XML_Convert_Result PTRCALL
-utf8_toUtf8(const ENCODING *UNUSED_P(enc),
- const char **fromP, const char *fromLim,
- char **toP, const char *toLim)
-{
+utf8_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
+ char **toP, const char *toLim) {
bool input_incomplete = false;
bool output_exhausted = false;
/* Avoid copying partial characters (due to limited space). */
const ptrdiff_t bytesAvailable = fromLim - *fromP;
const ptrdiff_t bytesStorable = toLim - *toP;
+ UNUSED_P(enc);
if (bytesAvailable > bytesStorable) {
fromLim = *fromP + bytesStorable;
output_exhausted = true;
/* Avoid copying partial characters (from incomplete input). */
{
- const char * const fromLimBefore = fromLim;
+ const char *const fromLimBefore = fromLim;
_INTERNAL_trim_to_complete_utf8_characters(*fromP, &fromLim);
if (fromLim < fromLimBefore) {
input_incomplete = true;
*toP += bytesToCopy;
}
- if (output_exhausted) /* needs to go first */
+ if (output_exhausted) /* needs to go first */
return XML_CONVERT_OUTPUT_EXHAUSTED;
else if (input_incomplete)
return XML_CONVERT_INPUT_INCOMPLETE;
}
static enum XML_Convert_Result PTRCALL
-utf8_toUtf16(const ENCODING *enc,
- const char **fromP, const char *fromLim,
- unsigned short **toP, const unsigned short *toLim)
-{
+utf8_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim,
+ unsigned short **toP, const unsigned short *toLim) {
enum XML_Convert_Result res = XML_CONVERT_COMPLETED;
unsigned short *to = *toP;
const char *from = *fromP;
res = XML_CONVERT_INPUT_INCOMPLETE;
goto after;
}
- *to++ = (unsigned short)(((from[0] & 0xf) << 12)
- | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f));
+ *to++ = (unsigned short)(((from[0] & 0xf) << 12) | ((from[1] & 0x3f) << 6)
+ | (from[2] & 0x3f));
from += 3;
break;
- case BT_LEAD4:
- {
- unsigned long n;
- if (toLim - to < 2) {
- res = XML_CONVERT_OUTPUT_EXHAUSTED;
- goto after;
- }
- if (fromLim - from < 4) {
- res = XML_CONVERT_INPUT_INCOMPLETE;
- goto after;
- }
- n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12)
- | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f);
- n -= 0x10000;
- to[0] = (unsigned short)((n >> 10) | 0xD800);
- to[1] = (unsigned short)((n & 0x3FF) | 0xDC00);
- to += 2;
- from += 4;
+ case BT_LEAD4: {
+ unsigned long n;
+ if (toLim - to < 2) {
+ res = XML_CONVERT_OUTPUT_EXHAUSTED;
+ goto after;
}
- break;
+ if (fromLim - from < 4) {
+ res = XML_CONVERT_INPUT_INCOMPLETE;
+ goto after;
+ }
+ n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12)
+ | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f);
+ n -= 0x10000;
+ to[0] = (unsigned short)((n >> 10) | 0xD800);
+ to[1] = (unsigned short)((n & 0x3FF) | 0xDC00);
+ to += 2;
+ from += 4;
+ } break;
default:
*to++ = *from++;
break;
}
#ifdef XML_NS
-static const struct normal_encoding utf8_encoding_ns = {
- { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
- {
-#include "asciitab.h"
-#include "utf8tab.h"
- },
- STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
-};
+static const struct normal_encoding utf8_encoding_ns
+ = {{VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0},
+ {
+# include "asciitab.h"
+# include "utf8tab.h"
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)};
#endif
-static const struct normal_encoding utf8_encoding = {
- { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
- {
+static const struct normal_encoding utf8_encoding
+ = {{VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0},
+ {
#define BT_COLON BT_NMSTRT
#include "asciitab.h"
#undef BT_COLON
#include "utf8tab.h"
- },
- STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
-};
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)};
#ifdef XML_NS
-static const struct normal_encoding internal_utf8_encoding_ns = {
- { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
- {
-#include "iasciitab.h"
-#include "utf8tab.h"
- },
- STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
-};
+static const struct normal_encoding internal_utf8_encoding_ns
+ = {{VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0},
+ {
+# include "iasciitab.h"
+# include "utf8tab.h"
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)};
#endif
-static const struct normal_encoding internal_utf8_encoding = {
- { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
- {
+static const struct normal_encoding internal_utf8_encoding
+ = {{VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0},
+ {
#define BT_COLON BT_NMSTRT
#include "iasciitab.h"
#undef BT_COLON
#include "utf8tab.h"
- },
- STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
-};
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)};
static enum XML_Convert_Result PTRCALL
-latin1_toUtf8(const ENCODING *UNUSED_P(enc),
- const char **fromP, const char *fromLim,
- char **toP, const char *toLim)
-{
+latin1_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
+ char **toP, const char *toLim) {
+ UNUSED_P(enc);
for (;;) {
unsigned char c;
if (*fromP == fromLim)
*(*toP)++ = (char)((c >> 6) | UTF8_cval2);
*(*toP)++ = (char)((c & 0x3f) | 0x80);
(*fromP)++;
- }
- else {
+ } else {
if (*toP == toLim)
return XML_CONVERT_OUTPUT_EXHAUSTED;
*(*toP)++ = *(*fromP)++;
}
static enum XML_Convert_Result PTRCALL
-latin1_toUtf16(const ENCODING *UNUSED_P(enc),
- const char **fromP, const char *fromLim,
- unsigned short **toP, const unsigned short *toLim)
-{
+latin1_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim,
+ unsigned short **toP, const unsigned short *toLim) {
+ UNUSED_P(enc);
while (*fromP < fromLim && *toP < toLim)
*(*toP)++ = (unsigned char)*(*fromP)++;
#ifdef XML_NS
-static const struct normal_encoding latin1_encoding_ns = {
- { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 },
- {
-#include "asciitab.h"
-#include "latin1tab.h"
- },
- STANDARD_VTABLE(sb_) NULL_VTABLE
-};
+static const struct normal_encoding latin1_encoding_ns
+ = {{VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0},
+ {
+# include "asciitab.h"
+# include "latin1tab.h"
+ },
+ STANDARD_VTABLE(sb_) NULL_VTABLE};
#endif
-static const struct normal_encoding latin1_encoding = {
- { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 },
- {
+static const struct normal_encoding latin1_encoding
+ = {{VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0},
+ {
#define BT_COLON BT_NMSTRT
#include "asciitab.h"
#undef BT_COLON
#include "latin1tab.h"
- },
- STANDARD_VTABLE(sb_) NULL_VTABLE
-};
+ },
+ STANDARD_VTABLE(sb_) NULL_VTABLE};
static enum XML_Convert_Result PTRCALL
-ascii_toUtf8(const ENCODING *UNUSED_P(enc),
- const char **fromP, const char *fromLim,
- char **toP, const char *toLim)
-{
+ascii_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
+ char **toP, const char *toLim) {
+ UNUSED_P(enc);
while (*fromP < fromLim && *toP < toLim)
*(*toP)++ = *(*fromP)++;
#ifdef XML_NS
-static const struct normal_encoding ascii_encoding_ns = {
- { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 },
- {
-#include "asciitab.h"
-/* BT_NONXML == 0 */
- },
- STANDARD_VTABLE(sb_) NULL_VTABLE
-};
+static const struct normal_encoding ascii_encoding_ns
+ = {{VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0},
+ {
+# include "asciitab.h"
+ /* BT_NONXML == 0 */
+ },
+ STANDARD_VTABLE(sb_) NULL_VTABLE};
#endif
-static const struct normal_encoding ascii_encoding = {
- { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 },
- {
+static const struct normal_encoding ascii_encoding
+ = {{VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0},
+ {
#define BT_COLON BT_NMSTRT
#include "asciitab.h"
#undef BT_COLON
-/* BT_NONXML == 0 */
- },
- STANDARD_VTABLE(sb_) NULL_VTABLE
-};
+ /* BT_NONXML == 0 */
+ },
+ STANDARD_VTABLE(sb_) NULL_VTABLE};
static int PTRFASTCALL
-unicode_byte_type(char hi, char lo)
-{
+unicode_byte_type(char hi, char lo) {
switch ((unsigned char)hi) {
- case 0xD8: case 0xD9: case 0xDA: case 0xDB:
+ /* 0xD800–0xDBFF first 16-bit code unit or high surrogate (W1) */
+ case 0xD8:
+ case 0xD9:
+ case 0xDA:
+ case 0xDB:
return BT_LEAD4;
- case 0xDC: case 0xDD: case 0xDE: case 0xDF:
+ /* 0xDC00–0xDFFF second 16-bit code unit or low surrogate (W2) */
+ case 0xDC:
+ case 0xDD:
+ case 0xDE:
+ case 0xDF:
return BT_TRAIL;
case 0xFF:
switch ((unsigned char)lo) {
- case 0xFF:
- case 0xFE:
+ case 0xFF: /* noncharacter-FFFF */
+ case 0xFE: /* noncharacter-FFFE */
return BT_NONXML;
}
break;
return BT_NONASCII;
}
-#define DEFINE_UTF16_TO_UTF8(E) \
-static enum XML_Convert_Result PTRCALL \
-E ## toUtf8(const ENCODING *UNUSED_P(enc), \
- const char **fromP, const char *fromLim, \
- char **toP, const char *toLim) \
-{ \
- const char *from = *fromP; \
- fromLim = from + (((fromLim - from) >> 1) << 1); /* shrink to even */ \
- for (; from < fromLim; from += 2) { \
- int plane; \
- unsigned char lo2; \
- unsigned char lo = GET_LO(from); \
- unsigned char hi = GET_HI(from); \
- switch (hi) { \
- case 0: \
- if (lo < 0x80) { \
- if (*toP == toLim) { \
- *fromP = from; \
- return XML_CONVERT_OUTPUT_EXHAUSTED; \
- } \
- *(*toP)++ = lo; \
- break; \
- } \
- /* fall through */ \
- case 0x1: case 0x2: case 0x3: \
- case 0x4: case 0x5: case 0x6: case 0x7: \
- if (toLim - *toP < 2) { \
- *fromP = from; \
- return XML_CONVERT_OUTPUT_EXHAUSTED; \
- } \
- *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2); \
- *(*toP)++ = ((lo & 0x3f) | 0x80); \
- break; \
- default: \
- if (toLim - *toP < 3) { \
- *fromP = from; \
- return XML_CONVERT_OUTPUT_EXHAUSTED; \
- } \
- /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \
- *(*toP)++ = ((hi >> 4) | UTF8_cval3); \
- *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80); \
- *(*toP)++ = ((lo & 0x3f) | 0x80); \
- break; \
- case 0xD8: case 0xD9: case 0xDA: case 0xDB: \
- if (toLim - *toP < 4) { \
- *fromP = from; \
- return XML_CONVERT_OUTPUT_EXHAUSTED; \
- } \
- if (fromLim - from < 4) { \
- *fromP = from; \
- return XML_CONVERT_INPUT_INCOMPLETE; \
- } \
- plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \
- *(*toP)++ = ((plane >> 2) | UTF8_cval4); \
- *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80); \
- from += 2; \
- lo2 = GET_LO(from); \
- *(*toP)++ = (((lo & 0x3) << 4) \
- | ((GET_HI(from) & 0x3) << 2) \
- | (lo2 >> 6) \
- | 0x80); \
- *(*toP)++ = ((lo2 & 0x3f) | 0x80); \
- break; \
- } \
- } \
- *fromP = from; \
- if (from < fromLim) \
- return XML_CONVERT_INPUT_INCOMPLETE; \
- else \
- return XML_CONVERT_COMPLETED; \
-}
+#define DEFINE_UTF16_TO_UTF8(E) \
+ static enum XML_Convert_Result PTRCALL E##toUtf8( \
+ const ENCODING *enc, const char **fromP, const char *fromLim, \
+ char **toP, const char *toLim) { \
+ const char *from = *fromP; \
+ UNUSED_P(enc); \
+ fromLim = from + (((fromLim - from) >> 1) << 1); /* shrink to even */ \
+ for (; from < fromLim; from += 2) { \
+ int plane; \
+ unsigned char lo2; \
+ unsigned char lo = GET_LO(from); \
+ unsigned char hi = GET_HI(from); \
+ switch (hi) { \
+ case 0: \
+ if (lo < 0x80) { \
+ if (*toP == toLim) { \
+ *fromP = from; \
+ return XML_CONVERT_OUTPUT_EXHAUSTED; \
+ } \
+ *(*toP)++ = lo; \
+ break; \
+ } \
+ /* fall through */ \
+ case 0x1: \
+ case 0x2: \
+ case 0x3: \
+ case 0x4: \
+ case 0x5: \
+ case 0x6: \
+ case 0x7: \
+ if (toLim - *toP < 2) { \
+ *fromP = from; \
+ return XML_CONVERT_OUTPUT_EXHAUSTED; \
+ } \
+ *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2); \
+ *(*toP)++ = ((lo & 0x3f) | 0x80); \
+ break; \
+ default: \
+ if (toLim - *toP < 3) { \
+ *fromP = from; \
+ return XML_CONVERT_OUTPUT_EXHAUSTED; \
+ } \
+ /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \
+ *(*toP)++ = ((hi >> 4) | UTF8_cval3); \
+ *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80); \
+ *(*toP)++ = ((lo & 0x3f) | 0x80); \
+ break; \
+ case 0xD8: \
+ case 0xD9: \
+ case 0xDA: \
+ case 0xDB: \
+ if (toLim - *toP < 4) { \
+ *fromP = from; \
+ return XML_CONVERT_OUTPUT_EXHAUSTED; \
+ } \
+ if (fromLim - from < 4) { \
+ *fromP = from; \
+ return XML_CONVERT_INPUT_INCOMPLETE; \
+ } \
+ plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \
+ *(*toP)++ = (char)((plane >> 2) | UTF8_cval4); \
+ *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80); \
+ from += 2; \
+ lo2 = GET_LO(from); \
+ *(*toP)++ = (((lo & 0x3) << 4) | ((GET_HI(from) & 0x3) << 2) \
+ | (lo2 >> 6) | 0x80); \
+ *(*toP)++ = ((lo2 & 0x3f) | 0x80); \
+ break; \
+ } \
+ } \
+ *fromP = from; \
+ if (from < fromLim) \
+ return XML_CONVERT_INPUT_INCOMPLETE; \
+ else \
+ return XML_CONVERT_COMPLETED; \
+ }
-#define DEFINE_UTF16_TO_UTF16(E) \
-static enum XML_Convert_Result PTRCALL \
-E ## toUtf16(const ENCODING *UNUSED_P(enc), \
- const char **fromP, const char *fromLim, \
- unsigned short **toP, const unsigned short *toLim) \
-{ \
- enum XML_Convert_Result res = XML_CONVERT_COMPLETED; \
- fromLim = *fromP + (((fromLim - *fromP) >> 1) << 1); /* shrink to even */ \
- /* Avoid copying first half only of surrogate */ \
- if (fromLim - *fromP > ((toLim - *toP) << 1) \
- && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) { \
- fromLim -= 2; \
- res = XML_CONVERT_INPUT_INCOMPLETE; \
- } \
- for (; *fromP < fromLim && *toP < toLim; *fromP += 2) \
- *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \
- if ((*toP == toLim) && (*fromP < fromLim)) \
- return XML_CONVERT_OUTPUT_EXHAUSTED; \
- else \
- return res; \
-}
+#define DEFINE_UTF16_TO_UTF16(E) \
+ static enum XML_Convert_Result PTRCALL E##toUtf16( \
+ const ENCODING *enc, const char **fromP, const char *fromLim, \
+ unsigned short **toP, const unsigned short *toLim) { \
+ enum XML_Convert_Result res = XML_CONVERT_COMPLETED; \
+ UNUSED_P(enc); \
+ fromLim = *fromP + (((fromLim - *fromP) >> 1) << 1); /* shrink to even */ \
+ /* Avoid copying first half only of surrogate */ \
+ if (fromLim - *fromP > ((toLim - *toP) << 1) \
+ && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) { \
+ fromLim -= 2; \
+ res = XML_CONVERT_INPUT_INCOMPLETE; \
+ } \
+ for (; *fromP < fromLim && *toP < toLim; *fromP += 2) \
+ *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \
+ if ((*toP == toLim) && (*fromP < fromLim)) \
+ return XML_CONVERT_OUTPUT_EXHAUSTED; \
+ else \
+ return res; \
+ }
-#define SET2(ptr, ch) \
- (((ptr)[0] = ((ch) & 0xff)), ((ptr)[1] = ((ch) >> 8)))
+#define SET2(ptr, ch) (((ptr)[0] = ((ch)&0xff)), ((ptr)[1] = ((ch) >> 8)))
#define GET_LO(ptr) ((unsigned char)(ptr)[0])
#define GET_HI(ptr) ((unsigned char)(ptr)[1])
#undef GET_LO
#undef GET_HI
-#define SET2(ptr, ch) \
- (((ptr)[0] = ((ch) >> 8)), ((ptr)[1] = ((ch) & 0xFF)))
+#define SET2(ptr, ch) (((ptr)[0] = ((ch) >> 8)), ((ptr)[1] = ((ch)&0xFF)))
#define GET_LO(ptr) ((unsigned char)(ptr)[1])
#define GET_HI(ptr) ((unsigned char)(ptr)[0])
#undef GET_LO
#undef GET_HI
-#define LITTLE2_BYTE_TYPE(enc, p) \
- ((p)[1] == 0 \
- ? ((struct normal_encoding *)(enc))->type[(unsigned char)*(p)] \
- : unicode_byte_type((p)[1], (p)[0]))
-#define LITTLE2_BYTE_TO_ASCII(enc, p) ((p)[1] == 0 ? (p)[0] : -1)
-#define LITTLE2_CHAR_MATCHES(enc, p, c) ((p)[1] == 0 && (p)[0] == c)
-#define LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) \
+#define LITTLE2_BYTE_TYPE(enc, p) \
+ ((p)[1] == 0 ? ((struct normal_encoding *)(enc))->type[(unsigned char)*(p)] \
+ : unicode_byte_type((p)[1], (p)[0]))
+#define LITTLE2_BYTE_TO_ASCII(p) ((p)[1] == 0 ? (p)[0] : -1)
+#define LITTLE2_CHAR_MATCHES(p, c) ((p)[1] == 0 && (p)[0] == c)
+#define LITTLE2_IS_NAME_CHAR_MINBPC(p) \
UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0])
-#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) \
+#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(p) \
UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0])
#ifdef XML_MIN_SIZE
static int PTRFASTCALL
-little2_byteType(const ENCODING *enc, const char *p)
-{
+little2_byteType(const ENCODING *enc, const char *p) {
return LITTLE2_BYTE_TYPE(enc, p);
}
static int PTRFASTCALL
-little2_byteToAscii(const ENCODING *enc, const char *p)
-{
- return LITTLE2_BYTE_TO_ASCII(enc, p);
+little2_byteToAscii(const ENCODING *enc, const char *p) {
+ UNUSED_P(enc);
+ return LITTLE2_BYTE_TO_ASCII(p);
}
static int PTRCALL
-little2_charMatches(const ENCODING *enc, const char *p, int c)
-{
- return LITTLE2_CHAR_MATCHES(enc, p, c);
+little2_charMatches(const ENCODING *enc, const char *p, int c) {
+ UNUSED_P(enc);
+ return LITTLE2_CHAR_MATCHES(p, c);
}
static int PTRFASTCALL
-little2_isNameMin(const ENCODING *enc, const char *p)
-{
- return LITTLE2_IS_NAME_CHAR_MINBPC(enc, p);
+little2_isNameMin(const ENCODING *enc, const char *p) {
+ UNUSED_P(enc);
+ return LITTLE2_IS_NAME_CHAR_MINBPC(p);
}
static int PTRFASTCALL
-little2_isNmstrtMin(const ENCODING *enc, const char *p)
-{
- return LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p);
+little2_isNmstrtMin(const ENCODING *enc, const char *p) {
+ UNUSED_P(enc);
+ return LITTLE2_IS_NMSTRT_CHAR_MINBPC(p);
}
-#undef VTABLE
-#define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16
+# undef VTABLE
+# define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16
#else /* not XML_MIN_SIZE */
-#undef PREFIX
-#define PREFIX(ident) little2_ ## ident
-#define MINBPC(enc) 2
+# undef PREFIX
+# define PREFIX(ident) little2_##ident
+# define MINBPC(enc) 2
/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
-#define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p)
-#define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(enc, p)
-#define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(enc, p, c)
-#define IS_NAME_CHAR(enc, p, n) 0
-#define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(enc, p)
-#define IS_NMSTRT_CHAR(enc, p, n) (0)
-#define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p)
-
-#define XML_TOK_IMPL_C
-#include "xmltok_impl.c"
-#undef XML_TOK_IMPL_C
-
-#undef MINBPC
-#undef BYTE_TYPE
-#undef BYTE_TO_ASCII
-#undef CHAR_MATCHES
-#undef IS_NAME_CHAR
-#undef IS_NAME_CHAR_MINBPC
-#undef IS_NMSTRT_CHAR
-#undef IS_NMSTRT_CHAR_MINBPC
-#undef IS_INVALID_CHAR
+# define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p)
+# define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(p)
+# define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(p, c)
+# define IS_NAME_CHAR(enc, p, n) 0
+# define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(p)
+# define IS_NMSTRT_CHAR(enc, p, n) (0)
+# define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(p)
+
+# define XML_TOK_IMPL_C
+# include "xmltok_impl.c"
+# undef XML_TOK_IMPL_C
+
+# undef MINBPC
+# undef BYTE_TYPE
+# undef BYTE_TO_ASCII
+# undef CHAR_MATCHES
+# undef IS_NAME_CHAR
+# undef IS_NAME_CHAR_MINBPC
+# undef IS_NMSTRT_CHAR
+# undef IS_NMSTRT_CHAR_MINBPC
+# undef IS_INVALID_CHAR
#endif /* not XML_MIN_SIZE */
#ifdef XML_NS
-static const struct normal_encoding little2_encoding_ns = {
- { VTABLE, 2, 0,
-#if BYTEORDER == 1234
- 1
-#else
- 0
-#endif
- },
- {
-#include "asciitab.h"
-#include "latin1tab.h"
- },
- STANDARD_VTABLE(little2_) NULL_VTABLE
-};
+static const struct normal_encoding little2_encoding_ns
+ = {{VTABLE, 2, 0,
+# if BYTEORDER == 1234
+ 1
+# else
+ 0
+# endif
+ },
+ {
+# include "asciitab.h"
+# include "latin1tab.h"
+ },
+ STANDARD_VTABLE(little2_) NULL_VTABLE};
#endif
-static const struct normal_encoding little2_encoding = {
- { VTABLE, 2, 0,
+static const struct normal_encoding little2_encoding
+ = {{VTABLE, 2, 0,
#if BYTEORDER == 1234
- 1
+ 1
#else
- 0
+ 0
#endif
- },
- {
+ },
+ {
#define BT_COLON BT_NMSTRT
#include "asciitab.h"
#undef BT_COLON
#include "latin1tab.h"
- },
- STANDARD_VTABLE(little2_) NULL_VTABLE
-};
+ },
+ STANDARD_VTABLE(little2_) NULL_VTABLE};
#if BYTEORDER != 4321
-#ifdef XML_NS
+# ifdef XML_NS
-static const struct normal_encoding internal_little2_encoding_ns = {
- { VTABLE, 2, 0, 1 },
- {
-#include "iasciitab.h"
-#include "latin1tab.h"
- },
- STANDARD_VTABLE(little2_) NULL_VTABLE
-};
+static const struct normal_encoding internal_little2_encoding_ns
+ = {{VTABLE, 2, 0, 1},
+ {
+# include "iasciitab.h"
+# include "latin1tab.h"
+ },
+ STANDARD_VTABLE(little2_) NULL_VTABLE};
-#endif
+# endif
-static const struct normal_encoding internal_little2_encoding = {
- { VTABLE, 2, 0, 1 },
- {
-#define BT_COLON BT_NMSTRT
-#include "iasciitab.h"
-#undef BT_COLON
-#include "latin1tab.h"
- },
- STANDARD_VTABLE(little2_) NULL_VTABLE
-};
+static const struct normal_encoding internal_little2_encoding
+ = {{VTABLE, 2, 0, 1},
+ {
+# define BT_COLON BT_NMSTRT
+# include "iasciitab.h"
+# undef BT_COLON
+# include "latin1tab.h"
+ },
+ STANDARD_VTABLE(little2_) NULL_VTABLE};
#endif
-
-#define BIG2_BYTE_TYPE(enc, p) \
- ((p)[0] == 0 \
- ? ((struct normal_encoding *)(enc))->type[(unsigned char)(p)[1]] \
- : unicode_byte_type((p)[0], (p)[1]))
-#define BIG2_BYTE_TO_ASCII(enc, p) ((p)[0] == 0 ? (p)[1] : -1)
-#define BIG2_CHAR_MATCHES(enc, p, c) ((p)[0] == 0 && (p)[1] == c)
-#define BIG2_IS_NAME_CHAR_MINBPC(enc, p) \
+#define BIG2_BYTE_TYPE(enc, p) \
+ ((p)[0] == 0 \
+ ? ((struct normal_encoding *)(enc))->type[(unsigned char)(p)[1]] \
+ : unicode_byte_type((p)[0], (p)[1]))
+#define BIG2_BYTE_TO_ASCII(p) ((p)[0] == 0 ? (p)[1] : -1)
+#define BIG2_CHAR_MATCHES(p, c) ((p)[0] == 0 && (p)[1] == c)
+#define BIG2_IS_NAME_CHAR_MINBPC(p) \
UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1])
-#define BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) \
+#define BIG2_IS_NMSTRT_CHAR_MINBPC(p) \
UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1])
#ifdef XML_MIN_SIZE
static int PTRFASTCALL
-big2_byteType(const ENCODING *enc, const char *p)
-{
+big2_byteType(const ENCODING *enc, const char *p) {
return BIG2_BYTE_TYPE(enc, p);
}
static int PTRFASTCALL
-big2_byteToAscii(const ENCODING *enc, const char *p)
-{
- return BIG2_BYTE_TO_ASCII(enc, p);
+big2_byteToAscii(const ENCODING *enc, const char *p) {
+ UNUSED_P(enc);
+ return BIG2_BYTE_TO_ASCII(p);
}
static int PTRCALL
-big2_charMatches(const ENCODING *enc, const char *p, int c)
-{
- return BIG2_CHAR_MATCHES(enc, p, c);
+big2_charMatches(const ENCODING *enc, const char *p, int c) {
+ UNUSED_P(enc);
+ return BIG2_CHAR_MATCHES(p, c);
}
static int PTRFASTCALL
-big2_isNameMin(const ENCODING *enc, const char *p)
-{
- return BIG2_IS_NAME_CHAR_MINBPC(enc, p);
+big2_isNameMin(const ENCODING *enc, const char *p) {
+ UNUSED_P(enc);
+ return BIG2_IS_NAME_CHAR_MINBPC(p);
}
static int PTRFASTCALL
-big2_isNmstrtMin(const ENCODING *enc, const char *p)
-{
- return BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p);
+big2_isNmstrtMin(const ENCODING *enc, const char *p) {
+ UNUSED_P(enc);
+ return BIG2_IS_NMSTRT_CHAR_MINBPC(p);
}
-#undef VTABLE
-#define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16
+# undef VTABLE
+# define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16
#else /* not XML_MIN_SIZE */
-#undef PREFIX
-#define PREFIX(ident) big2_ ## ident
-#define MINBPC(enc) 2
+# undef PREFIX
+# define PREFIX(ident) big2_##ident
+# define MINBPC(enc) 2
/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
-#define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p)
-#define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(enc, p)
-#define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(enc, p, c)
-#define IS_NAME_CHAR(enc, p, n) 0
-#define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(enc, p)
-#define IS_NMSTRT_CHAR(enc, p, n) (0)
-#define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p)
-
-#define XML_TOK_IMPL_C
-#include "xmltok_impl.c"
-#undef XML_TOK_IMPL_C
-
-#undef MINBPC
-#undef BYTE_TYPE
-#undef BYTE_TO_ASCII
-#undef CHAR_MATCHES
-#undef IS_NAME_CHAR
-#undef IS_NAME_CHAR_MINBPC
-#undef IS_NMSTRT_CHAR
-#undef IS_NMSTRT_CHAR_MINBPC
-#undef IS_INVALID_CHAR
+# define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p)
+# define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(p)
+# define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(p, c)
+# define IS_NAME_CHAR(enc, p, n) 0
+# define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(p)
+# define IS_NMSTRT_CHAR(enc, p, n) (0)
+# define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(p)
+
+# define XML_TOK_IMPL_C
+# include "xmltok_impl.c"
+# undef XML_TOK_IMPL_C
+
+# undef MINBPC
+# undef BYTE_TYPE
+# undef BYTE_TO_ASCII
+# undef CHAR_MATCHES
+# undef IS_NAME_CHAR
+# undef IS_NAME_CHAR_MINBPC
+# undef IS_NMSTRT_CHAR
+# undef IS_NMSTRT_CHAR_MINBPC
+# undef IS_INVALID_CHAR
#endif /* not XML_MIN_SIZE */
#ifdef XML_NS
-static const struct normal_encoding big2_encoding_ns = {
- { VTABLE, 2, 0,
-#if BYTEORDER == 4321
- 1
-#else
- 0
-#endif
- },
- {
-#include "asciitab.h"
-#include "latin1tab.h"
- },
- STANDARD_VTABLE(big2_) NULL_VTABLE
-};
+static const struct normal_encoding big2_encoding_ns
+ = {{VTABLE, 2, 0,
+# if BYTEORDER == 4321
+ 1
+# else
+ 0
+# endif
+ },
+ {
+# include "asciitab.h"
+# include "latin1tab.h"
+ },
+ STANDARD_VTABLE(big2_) NULL_VTABLE};
#endif
-static const struct normal_encoding big2_encoding = {
- { VTABLE, 2, 0,
+static const struct normal_encoding big2_encoding
+ = {{VTABLE, 2, 0,
#if BYTEORDER == 4321
- 1
+ 1
#else
- 0
+ 0
#endif
- },
- {
+ },
+ {
#define BT_COLON BT_NMSTRT
#include "asciitab.h"
#undef BT_COLON
#include "latin1tab.h"
- },
- STANDARD_VTABLE(big2_) NULL_VTABLE
-};
+ },
+ STANDARD_VTABLE(big2_) NULL_VTABLE};
#if BYTEORDER != 1234
-#ifdef XML_NS
+# ifdef XML_NS
-static const struct normal_encoding internal_big2_encoding_ns = {
- { VTABLE, 2, 0, 1 },
- {
-#include "iasciitab.h"
-#include "latin1tab.h"
- },
- STANDARD_VTABLE(big2_) NULL_VTABLE
-};
+static const struct normal_encoding internal_big2_encoding_ns
+ = {{VTABLE, 2, 0, 1},
+ {
+# include "iasciitab.h"
+# include "latin1tab.h"
+ },
+ STANDARD_VTABLE(big2_) NULL_VTABLE};
-#endif
+# endif
-static const struct normal_encoding internal_big2_encoding = {
- { VTABLE, 2, 0, 1 },
- {
-#define BT_COLON BT_NMSTRT
-#include "iasciitab.h"
-#undef BT_COLON
-#include "latin1tab.h"
- },
- STANDARD_VTABLE(big2_) NULL_VTABLE
-};
+static const struct normal_encoding internal_big2_encoding
+ = {{VTABLE, 2, 0, 1},
+ {
+# define BT_COLON BT_NMSTRT
+# include "iasciitab.h"
+# undef BT_COLON
+# include "latin1tab.h"
+ },
+ STANDARD_VTABLE(big2_) NULL_VTABLE};
#endif
#undef PREFIX
static int FASTCALL
-streqci(const char *s1, const char *s2)
-{
+streqci(const char *s1, const char *s2) {
for (;;) {
char c1 = *s1++;
char c2 = *s2++;
c2 += ASCII_A - ASCII_a; /* LCOV_EXCL_LINE */
if (c1 != c2)
return 0;
- if (!c1)
+ if (! c1)
break;
}
return 1;
}
static void PTRCALL
-initUpdatePosition(const ENCODING *UNUSED_P(enc), const char *ptr,
- const char *end, POSITION *pos)
-{
+initUpdatePosition(const ENCODING *enc, const char *ptr, const char *end,
+ POSITION *pos) {
+ UNUSED_P(enc);
normal_updatePosition(&utf8_encoding.enc, ptr, end, pos);
}
static int
-toAscii(const ENCODING *enc, const char *ptr, const char *end)
-{
+toAscii(const ENCODING *enc, const char *ptr, const char *end) {
char buf[1];
char *p = buf;
XmlUtf8Convert(enc, &ptr, end, &p, p + 1);
}
static int FASTCALL
-isSpace(int c)
-{
+isSpace(int c) {
switch (c) {
case 0x20:
case 0xD:
followed by name=val.
*/
static int
-parsePseudoAttribute(const ENCODING *enc,
- const char *ptr,
- const char *end,
- const char **namePtr,
- const char **nameEndPtr,
- const char **valPtr,
- const char **nextTokPtr)
-{
+parsePseudoAttribute(const ENCODING *enc, const char *ptr, const char *end,
+ const char **namePtr, const char **nameEndPtr,
+ const char **valPtr, const char **nextTokPtr) {
int c;
char open;
if (ptr == end) {
*namePtr = NULL;
return 1;
}
- if (!isSpace(toAscii(enc, ptr, end))) {
+ if (! isSpace(toAscii(enc, ptr, end))) {
*nextTokPtr = ptr;
return 0;
}
c = toAscii(enc, ptr, end);
if (c == open)
break;
- if (!(ASCII_a <= c && c <= ASCII_z)
- && !(ASCII_A <= c && c <= ASCII_Z)
- && !(ASCII_0 <= c && c <= ASCII_9)
- && c != ASCII_PERIOD
- && c != ASCII_MINUS
- && c != ASCII_UNDERSCORE) {
+ if (! (ASCII_a <= c && c <= ASCII_z) && ! (ASCII_A <= c && c <= ASCII_Z)
+ && ! (ASCII_0 <= c && c <= ASCII_9) && c != ASCII_PERIOD
+ && c != ASCII_MINUS && c != ASCII_UNDERSCORE) {
*nextTokPtr = ptr;
return 0;
}
return 1;
}
-static const char KW_version[] = {
- ASCII_v, ASCII_e, ASCII_r, ASCII_s, ASCII_i, ASCII_o, ASCII_n, '\0'
-};
+static const char KW_version[]
+ = {ASCII_v, ASCII_e, ASCII_r, ASCII_s, ASCII_i, ASCII_o, ASCII_n, '\0'};
-static const char KW_encoding[] = {
- ASCII_e, ASCII_n, ASCII_c, ASCII_o, ASCII_d, ASCII_i, ASCII_n, ASCII_g, '\0'
-};
+static const char KW_encoding[] = {ASCII_e, ASCII_n, ASCII_c, ASCII_o, ASCII_d,
+ ASCII_i, ASCII_n, ASCII_g, '\0'};
-static const char KW_standalone[] = {
- ASCII_s, ASCII_t, ASCII_a, ASCII_n, ASCII_d, ASCII_a, ASCII_l, ASCII_o,
- ASCII_n, ASCII_e, '\0'
-};
+static const char KW_standalone[]
+ = {ASCII_s, ASCII_t, ASCII_a, ASCII_n, ASCII_d, ASCII_a,
+ ASCII_l, ASCII_o, ASCII_n, ASCII_e, '\0'};
-static const char KW_yes[] = {
- ASCII_y, ASCII_e, ASCII_s, '\0'
-};
+static const char KW_yes[] = {ASCII_y, ASCII_e, ASCII_s, '\0'};
-static const char KW_no[] = {
- ASCII_n, ASCII_o, '\0'
-};
+static const char KW_no[] = {ASCII_n, ASCII_o, '\0'};
static int
-doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *,
- const char *,
+doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *, const char *,
const char *),
- int isGeneralTextEntity,
- const ENCODING *enc,
- const char *ptr,
- const char *end,
- const char **badPtr,
- const char **versionPtr,
- const char **versionEndPtr,
- const char **encodingName,
- const ENCODING **encoding,
- int *standalone)
-{
+ int isGeneralTextEntity, const ENCODING *enc, const char *ptr,
+ const char *end, const char **badPtr, const char **versionPtr,
+ const char **versionEndPtr, const char **encodingName,
+ const ENCODING **encoding, int *standalone) {
const char *val = NULL;
const char *name = NULL;
const char *nameEnd = NULL;
ptr += 5 * enc->minBytesPerChar;
end -= 2 * enc->minBytesPerChar;
- if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)
- || !name) {
+ if (! parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)
+ || ! name) {
*badPtr = ptr;
return 0;
}
- if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_version)) {
- if (!isGeneralTextEntity) {
+ if (! XmlNameMatchesAscii(enc, name, nameEnd, KW_version)) {
+ if (! isGeneralTextEntity) {
*badPtr = name;
return 0;
}
- }
- else {
+ } else {
if (versionPtr)
*versionPtr = val;
if (versionEndPtr)
*versionEndPtr = ptr;
- if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
+ if (! parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
*badPtr = ptr;
return 0;
}
- if (!name) {
+ if (! name) {
if (isGeneralTextEntity) {
/* a TextDecl must have an EncodingDecl */
*badPtr = ptr;
}
if (XmlNameMatchesAscii(enc, name, nameEnd, KW_encoding)) {
int c = toAscii(enc, val, end);
- if (!(ASCII_a <= c && c <= ASCII_z) && !(ASCII_A <= c && c <= ASCII_Z)) {
+ if (! (ASCII_a <= c && c <= ASCII_z) && ! (ASCII_A <= c && c <= ASCII_Z)) {
*badPtr = val;
return 0;
}
*encodingName = val;
if (encoding)
*encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar);
- if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
+ if (! parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
*badPtr = ptr;
return 0;
}
- if (!name)
+ if (! name)
return 1;
}
- if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_standalone)
+ if (! XmlNameMatchesAscii(enc, name, nameEnd, KW_standalone)
|| isGeneralTextEntity) {
*badPtr = name;
return 0;
if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_yes)) {
if (standalone)
*standalone = 1;
- }
- else if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_no)) {
+ } else if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_no)) {
if (standalone)
*standalone = 0;
- }
- else {
+ } else {
*badPtr = val;
return 0;
}
}
static int FASTCALL
-checkCharRefNumber(int result)
-{
+checkCharRefNumber(int result) {
switch (result >> 8) {
- case 0xD8: case 0xD9: case 0xDA: case 0xDB:
- case 0xDC: case 0xDD: case 0xDE: case 0xDF:
+ case 0xD8:
+ case 0xD9:
+ case 0xDA:
+ case 0xDB:
+ case 0xDC:
+ case 0xDD:
+ case 0xDE:
+ case 0xDF:
return -1;
case 0:
if (latin1_encoding.type[result] == BT_NONXML)
}
int FASTCALL
-XmlUtf8Encode(int c, char *buf)
-{
+XmlUtf8Encode(int c, char *buf) {
enum {
/* minN is minimum legal resulting value for N byte sequence */
min2 = 0x80,
}
int FASTCALL
-XmlUtf16Encode(int charNum, unsigned short *buf)
-{
+XmlUtf16Encode(int charNum, unsigned short *buf) {
if (charNum < 0)
return 0;
if (charNum < 0x10000) {
char utf8[256][4];
};
-#define AS_UNKNOWN_ENCODING(enc) ((const struct unknown_encoding *) (enc))
+#define AS_UNKNOWN_ENCODING(enc) ((const struct unknown_encoding *)(enc))
int
-XmlSizeOfUnknownEncoding(void)
-{
+XmlSizeOfUnknownEncoding(void) {
return sizeof(struct unknown_encoding);
}
static int PTRFASTCALL
-unknown_isName(const ENCODING *enc, const char *p)
-{
+unknown_isName(const ENCODING *enc, const char *p) {
const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
int c = uenc->convert(uenc->userData, p);
if (c & ~0xFFFF)
}
static int PTRFASTCALL
-unknown_isNmstrt(const ENCODING *enc, const char *p)
-{
+unknown_isNmstrt(const ENCODING *enc, const char *p) {
const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
int c = uenc->convert(uenc->userData, p);
if (c & ~0xFFFF)
}
static int PTRFASTCALL
-unknown_isInvalid(const ENCODING *enc, const char *p)
-{
+unknown_isInvalid(const ENCODING *enc, const char *p) {
const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
int c = uenc->convert(uenc->userData, p);
return (c & ~0xFFFF) || checkCharRefNumber(c) < 0;
}
static enum XML_Convert_Result PTRCALL
-unknown_toUtf8(const ENCODING *enc,
- const char **fromP, const char *fromLim,
- char **toP, const char *toLim)
-{
+unknown_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim,
+ char **toP, const char *toLim) {
const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
char buf[XML_UTF8_ENCODE_MAX];
for (;;) {
utf8 = buf;
*fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP]
- (BT_LEAD2 - 2));
- }
- else {
+ } else {
if (n > toLim - *toP)
return XML_CONVERT_OUTPUT_EXHAUSTED;
(*fromP)++;
}
static enum XML_Convert_Result PTRCALL
-unknown_toUtf16(const ENCODING *enc,
- const char **fromP, const char *fromLim,
- unsigned short **toP, const unsigned short *toLim)
-{
+unknown_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim,
+ unsigned short **toP, const unsigned short *toLim) {
const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc);
while (*fromP < fromLim && *toP < toLim) {
unsigned short c = uenc->utf16[(unsigned char)**fromP];
if (c == 0) {
- c = (unsigned short)
- uenc->convert(uenc->userData, *fromP);
+ c = (unsigned short)uenc->convert(uenc->userData, *fromP);
*fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP]
- (BT_LEAD2 - 2));
- }
- else
+ } else
(*fromP)++;
*(*toP)++ = c;
}
}
ENCODING *
-XmlInitUnknownEncoding(void *mem,
- int *table,
- CONVERTER convert,
- void *userData)
-{
+XmlInitUnknownEncoding(void *mem, int *table, CONVERTER convert,
+ void *userData) {
int i;
struct unknown_encoding *e = (struct unknown_encoding *)mem;
- for (i = 0; i < (int)sizeof(struct normal_encoding); i++)
- ((char *)mem)[i] = ((char *)&latin1_encoding)[i];
+ memcpy(mem, &latin1_encoding, sizeof(struct normal_encoding));
for (i = 0; i < 128; i++)
if (latin1_encoding.type[i] != BT_OTHER
- && latin1_encoding.type[i] != BT_NONXML
- && table[i] != i)
+ && latin1_encoding.type[i] != BT_NONXML && table[i] != i)
return 0;
for (i = 0; i < 256; i++) {
int c = table[i];
e->utf16[i] = 0xFFFF;
e->utf8[i][0] = 1;
e->utf8[i][1] = 0;
- }
- else if (c < 0) {
+ } else if (c < 0) {
if (c < -4)
return 0;
/* Multi-byte sequences need a converter function */
- if (!convert)
+ if (! convert)
return 0;
e->normal.type[i] = (unsigned char)(BT_LEAD2 - (c + 2));
e->utf8[i][0] = 0;
e->utf16[i] = 0;
- }
- else if (c < 0x80) {
+ } else if (c < 0x80) {
if (latin1_encoding.type[c] != BT_OTHER
- && latin1_encoding.type[c] != BT_NONXML
- && c != i)
+ && latin1_encoding.type[c] != BT_NONXML && c != i)
return 0;
e->normal.type[i] = latin1_encoding.type[c];
e->utf8[i][0] = 1;
e->utf8[i][1] = (char)c;
e->utf16[i] = (unsigned short)(c == 0 ? 0xFFFF : c);
- }
- else if (checkCharRefNumber(c) < 0) {
+ } else if (checkCharRefNumber(c) < 0) {
e->normal.type[i] = BT_NONXML;
/* This shouldn't really get used. */
e->utf16[i] = 0xFFFF;
e->utf8[i][0] = 1;
e->utf8[i][1] = 0;
- }
- else {
+ } else {
if (c > 0xFFFF)
return 0;
if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff))
NO_ENC
};
-static const char KW_ISO_8859_1[] = {
- ASCII_I, ASCII_S, ASCII_O, ASCII_MINUS, ASCII_8, ASCII_8, ASCII_5, ASCII_9,
- ASCII_MINUS, ASCII_1, '\0'
-};
-static const char KW_US_ASCII[] = {
- ASCII_U, ASCII_S, ASCII_MINUS, ASCII_A, ASCII_S, ASCII_C, ASCII_I, ASCII_I,
- '\0'
-};
-static const char KW_UTF_8[] = {
- ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_8, '\0'
-};
-static const char KW_UTF_16[] = {
- ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, '\0'
-};
-static const char KW_UTF_16BE[] = {
- ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_B, ASCII_E,
- '\0'
-};
-static const char KW_UTF_16LE[] = {
- ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_L, ASCII_E,
- '\0'
-};
+static const char KW_ISO_8859_1[]
+ = {ASCII_I, ASCII_S, ASCII_O, ASCII_MINUS, ASCII_8, ASCII_8,
+ ASCII_5, ASCII_9, ASCII_MINUS, ASCII_1, '\0'};
+static const char KW_US_ASCII[]
+ = {ASCII_U, ASCII_S, ASCII_MINUS, ASCII_A, ASCII_S,
+ ASCII_C, ASCII_I, ASCII_I, '\0'};
+static const char KW_UTF_8[]
+ = {ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_8, '\0'};
+static const char KW_UTF_16[]
+ = {ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, '\0'};
+static const char KW_UTF_16BE[]
+ = {ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1,
+ ASCII_6, ASCII_B, ASCII_E, '\0'};
+static const char KW_UTF_16LE[]
+ = {ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1,
+ ASCII_6, ASCII_L, ASCII_E, '\0'};
static int FASTCALL
-getEncodingIndex(const char *name)
-{
- static const char * const encodingNames[] = {
- KW_ISO_8859_1,
- KW_US_ASCII,
- KW_UTF_8,
- KW_UTF_16,
- KW_UTF_16BE,
- KW_UTF_16LE,
+getEncodingIndex(const char *name) {
+ static const char *const encodingNames[] = {
+ KW_ISO_8859_1, KW_US_ASCII, KW_UTF_8, KW_UTF_16, KW_UTF_16BE, KW_UTF_16LE,
};
int i;
if (name == NULL)
return NO_ENC;
- for (i = 0; i < (int)(sizeof(encodingNames)/sizeof(encodingNames[0])); i++)
+ for (i = 0; i < (int)(sizeof(encodingNames) / sizeof(encodingNames[0])); i++)
if (streqci(name, encodingNames[i]))
return i;
return UNKNOWN_ENC;
XML_PROLOG_STATE otherwise.
*/
-
static int
-initScan(const ENCODING * const *encodingTable,
- const INIT_ENCODING *enc,
- int state,
- const char *ptr,
- const char *end,
- const char **nextTokPtr)
-{
+initScan(const ENCODING *const *encodingTable, const INIT_ENCODING *enc,
+ int state, const char *ptr, const char *end, const char **nextTokPtr) {
const ENCODING **encPtr;
if (ptr >= end)
case 0xFE:
case 0xFF:
case 0xEF: /* possibly first byte of UTF-8 BOM */
- if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
- && state == XML_CONTENT_STATE)
+ if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
break;
/* fall through */
case 0x00:
case 0x3C:
return XML_TOK_PARTIAL;
}
- }
- else {
+ } else {
switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) {
case 0xFEFF:
- if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
- && state == XML_CONTENT_STATE)
+ if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
break;
*nextTokPtr = ptr + 2;
*encPtr = encodingTable[UTF_16BE_ENC];
*encPtr = encodingTable[UTF_16LE_ENC];
return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
case 0xFFFE:
- if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
- && state == XML_CONTENT_STATE)
+ if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE)
break;
*nextTokPtr = ptr + 2;
*encPtr = encodingTable[UTF_16LE_ENC];
*/
if (state == XML_CONTENT_STATE) {
int e = INIT_ENC_INDEX(enc);
- if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC
- || e == UTF_16LE_ENC || e == UTF_16_ENC)
+ if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC || e == UTF_16LE_ENC
+ || e == UTF_16_ENC)
break;
}
if (ptr + 2 == end)
break;
*encPtr = encodingTable[UTF_16BE_ENC];
return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
- }
- else if (ptr[1] == '\0') {
+ } else if (ptr[1] == '\0') {
/* We could recover here in the case:
- parsing an external entity
- second byte is 0
return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
}
-
#define NS(x) x
#define ns(x) x
#define XML_TOK_NS_C
#ifdef XML_NS
-#define NS(x) x ## NS
-#define ns(x) x ## _ns
+# define NS(x) x##NS
+# define ns(x) x##_ns
-#define XML_TOK_NS_C
-#include "xmltok_ns.c"
-#undef XML_TOK_NS_C
+# define XML_TOK_NS_C
+# include "xmltok_ns.c"
+# undef XML_TOK_NS_C
-#undef NS
-#undef ns
+# undef NS
+# undef ns
ENCODING *
-XmlInitUnknownEncodingNS(void *mem,
- int *table,
- CONVERTER convert,
- void *userData)
-{
+XmlInitUnknownEncodingNS(void *mem, int *table, CONVERTER convert,
+ void *userData) {
ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData);
if (enc)
((struct normal_encoding *)enc)->type[ASCII_COLON] = BT_COLON;
#endif
/* The following token may be returned by XmlContentTok */
-#define XML_TOK_TRAILING_RSQB -5 /* ] or ]] at the end of the scan; might be
- start of illegal ]]> sequence */
+#define XML_TOK_TRAILING_RSQB \
+ -5 /* ] or ]] at the end of the scan; might be \
+ start of illegal ]]> sequence */
/* The following tokens may be returned by both XmlPrologTok and
XmlContentTok.
*/
-#define XML_TOK_NONE -4 /* The string to be scanned is empty */
-#define XML_TOK_TRAILING_CR -3 /* A CR at the end of the scan;
- might be part of CRLF sequence */
-#define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */
-#define XML_TOK_PARTIAL -1 /* only part of a token */
+#define XML_TOK_NONE -4 /* The string to be scanned is empty */
+#define XML_TOK_TRAILING_CR \
+ -3 /* A CR at the end of the scan; \
+ might be part of CRLF sequence */
+#define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */
+#define XML_TOK_PARTIAL -1 /* only part of a token */
#define XML_TOK_INVALID 0
/* The following tokens are returned by XmlContentTok; some are also
#define XML_TOK_DATA_NEWLINE 7
#define XML_TOK_CDATA_SECT_OPEN 8
#define XML_TOK_ENTITY_REF 9
-#define XML_TOK_CHAR_REF 10 /* numeric character reference */
+#define XML_TOK_CHAR_REF 10 /* numeric character reference */
/* The following tokens may be returned by both XmlPrologTok and
XmlContentTok.
*/
-#define XML_TOK_PI 11 /* processing instruction */
-#define XML_TOK_XML_DECL 12 /* XML decl or text decl */
+#define XML_TOK_PI 11 /* processing instruction */
+#define XML_TOK_XML_DECL 12 /* XML decl or text decl */
#define XML_TOK_COMMENT 13
-#define XML_TOK_BOM 14 /* Byte order mark */
+#define XML_TOK_BOM 14 /* Byte order mark */
/* The following tokens are returned only by XmlPrologTok */
#define XML_TOK_PROLOG_S 15
-#define XML_TOK_DECL_OPEN 16 /* <!foo */
-#define XML_TOK_DECL_CLOSE 17 /* > */
+#define XML_TOK_DECL_OPEN 16 /* <!foo */
+#define XML_TOK_DECL_CLOSE 17 /* > */
#define XML_TOK_NAME 18
#define XML_TOK_NMTOKEN 19
-#define XML_TOK_POUND_NAME 20 /* #name */
-#define XML_TOK_OR 21 /* | */
+#define XML_TOK_POUND_NAME 20 /* #name */
+#define XML_TOK_OR 21 /* | */
#define XML_TOK_PERCENT 22
#define XML_TOK_OPEN_PAREN 23
#define XML_TOK_CLOSE_PAREN 24
#define XML_TOK_INSTANCE_START 29
/* The following occur only in element type declarations */
-#define XML_TOK_NAME_QUESTION 30 /* name? */
-#define XML_TOK_NAME_ASTERISK 31 /* name* */
-#define XML_TOK_NAME_PLUS 32 /* name+ */
-#define XML_TOK_COND_SECT_OPEN 33 /* <![ */
-#define XML_TOK_COND_SECT_CLOSE 34 /* ]]> */
-#define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */
-#define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */
-#define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */
+#define XML_TOK_NAME_QUESTION 30 /* name? */
+#define XML_TOK_NAME_ASTERISK 31 /* name* */
+#define XML_TOK_NAME_PLUS 32 /* name+ */
+#define XML_TOK_COND_SECT_OPEN 33 /* <![ */
+#define XML_TOK_COND_SECT_CLOSE 34 /* ]]> */
+#define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */
+#define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */
+#define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */
#define XML_TOK_COMMA 38
/* The following token is returned only by XmlAttributeValueTok */
#define XML_TOK_PREFIXED_NAME 41
#ifdef XML_DTD
-#define XML_TOK_IGNORE_SECT 42
+# define XML_TOK_IGNORE_SECT 42
#endif /* XML_DTD */
#ifdef XML_DTD
-#define XML_N_STATES 4
+# define XML_N_STATES 4
#else /* not XML_DTD */
-#define XML_N_STATES 3
+# define XML_N_STATES 3
#endif /* not XML_DTD */
#define XML_PROLOG_STATE 0
#define XML_CONTENT_STATE 1
#define XML_CDATA_SECTION_STATE 2
#ifdef XML_DTD
-#define XML_IGNORE_SECTION_STATE 3
+# define XML_IGNORE_SECTION_STATE 3
#endif /* XML_DTD */
#define XML_N_LITERAL_TYPES 2
struct encoding;
typedef struct encoding ENCODING;
-typedef int (PTRCALL *SCANNER)(const ENCODING *,
- const char *,
- const char *,
- const char **);
+typedef int(PTRCALL *SCANNER)(const ENCODING *, const char *, const char *,
+ const char **);
enum XML_Convert_Result {
XML_CONVERT_COMPLETED = 0,
XML_CONVERT_INPUT_INCOMPLETE = 1,
- XML_CONVERT_OUTPUT_EXHAUSTED = 2 /* and therefore potentially input remaining as well */
+ XML_CONVERT_OUTPUT_EXHAUSTED
+ = 2 /* and therefore potentially input remaining as well */
};
struct encoding {
SCANNER scanners[XML_N_STATES];
SCANNER literalScanners[XML_N_LITERAL_TYPES];
- int (PTRCALL *nameMatchesAscii)(const ENCODING *,
- const char *,
- const char *,
- const char *);
- int (PTRFASTCALL *nameLength)(const ENCODING *, const char *);
+ int(PTRCALL *nameMatchesAscii)(const ENCODING *, const char *, const char *,
+ const char *);
+ int(PTRFASTCALL *nameLength)(const ENCODING *, const char *);
const char *(PTRFASTCALL *skipS)(const ENCODING *, const char *);
- int (PTRCALL *getAtts)(const ENCODING *enc,
- const char *ptr,
- int attsMax,
- ATTRIBUTE *atts);
- int (PTRFASTCALL *charRefNumber)(const ENCODING *enc, const char *ptr);
- int (PTRCALL *predefinedEntityName)(const ENCODING *,
- const char *,
- const char *);
- void (PTRCALL *updatePosition)(const ENCODING *,
- const char *ptr,
- const char *end,
- POSITION *);
- int (PTRCALL *isPublicId)(const ENCODING *enc,
- const char *ptr,
- const char *end,
- const char **badPtr);
- enum XML_Convert_Result (PTRCALL *utf8Convert)(const ENCODING *enc,
- const char **fromP,
- const char *fromLim,
- char **toP,
- const char *toLim);
- enum XML_Convert_Result (PTRCALL *utf16Convert)(const ENCODING *enc,
- const char **fromP,
- const char *fromLim,
- unsigned short **toP,
- const unsigned short *toLim);
+ int(PTRCALL *getAtts)(const ENCODING *enc, const char *ptr, int attsMax,
+ ATTRIBUTE *atts);
+ int(PTRFASTCALL *charRefNumber)(const ENCODING *enc, const char *ptr);
+ int(PTRCALL *predefinedEntityName)(const ENCODING *, const char *,
+ const char *);
+ void(PTRCALL *updatePosition)(const ENCODING *, const char *ptr,
+ const char *end, POSITION *);
+ int(PTRCALL *isPublicId)(const ENCODING *enc, const char *ptr,
+ const char *end, const char **badPtr);
+ enum XML_Convert_Result(PTRCALL *utf8Convert)(const ENCODING *enc,
+ const char **fromP,
+ const char *fromLim, char **toP,
+ const char *toLim);
+ enum XML_Convert_Result(PTRCALL *utf16Convert)(const ENCODING *enc,
+ const char **fromP,
+ const char *fromLim,
+ unsigned short **toP,
+ const unsigned short *toLim);
int minBytesPerChar;
char isUtf8;
char isUtf16;
the prolog outside literals, comments and processing instructions.
*/
-
-#define XmlTok(enc, state, ptr, end, nextTokPtr) \
+#define XmlTok(enc, state, ptr, end, nextTokPtr) \
(((enc)->scanners[state])(enc, ptr, end, nextTokPtr))
-#define XmlPrologTok(enc, ptr, end, nextTokPtr) \
- XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr)
+#define XmlPrologTok(enc, ptr, end, nextTokPtr) \
+ XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr)
-#define XmlContentTok(enc, ptr, end, nextTokPtr) \
- XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr)
+#define XmlContentTok(enc, ptr, end, nextTokPtr) \
+ XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr)
-#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \
- XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr)
+#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \
+ XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr)
#ifdef XML_DTD
-#define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) \
- XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr)
+# define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) \
+ XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr)
#endif /* XML_DTD */
/* This is used for performing a 2nd-level tokenization on the content
of a literal that has already been returned by XmlTok.
*/
-#define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \
+#define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \
(((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr))
-#define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \
- XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr)
+#define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \
+ XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr)
-#define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \
- XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr)
+#define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \
+ XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr)
-#define XmlNameMatchesAscii(enc, ptr1, end1, ptr2) \
+#define XmlNameMatchesAscii(enc, ptr1, end1, ptr2) \
(((enc)->nameMatchesAscii)(enc, ptr1, end1, ptr2))
-#define XmlNameLength(enc, ptr) \
- (((enc)->nameLength)(enc, ptr))
+#define XmlNameLength(enc, ptr) (((enc)->nameLength)(enc, ptr))
-#define XmlSkipS(enc, ptr) \
- (((enc)->skipS)(enc, ptr))
+#define XmlSkipS(enc, ptr) (((enc)->skipS)(enc, ptr))
-#define XmlGetAttributes(enc, ptr, attsMax, atts) \
+#define XmlGetAttributes(enc, ptr, attsMax, atts) \
(((enc)->getAtts)(enc, ptr, attsMax, atts))
-#define XmlCharRefNumber(enc, ptr) \
- (((enc)->charRefNumber)(enc, ptr))
+#define XmlCharRefNumber(enc, ptr) (((enc)->charRefNumber)(enc, ptr))
-#define XmlPredefinedEntityName(enc, ptr, end) \
+#define XmlPredefinedEntityName(enc, ptr, end) \
(((enc)->predefinedEntityName)(enc, ptr, end))
-#define XmlUpdatePosition(enc, ptr, end, pos) \
+#define XmlUpdatePosition(enc, ptr, end, pos) \
(((enc)->updatePosition)(enc, ptr, end, pos))
-#define XmlIsPublicId(enc, ptr, end, badPtr) \
+#define XmlIsPublicId(enc, ptr, end, badPtr) \
(((enc)->isPublicId)(enc, ptr, end, badPtr))
-#define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \
+#define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \
(((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim))
-#define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \
+#define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \
(((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim))
typedef struct {
const ENCODING **encPtr;
} INIT_ENCODING;
-int XmlParseXmlDecl(int isGeneralTextEntity,
- const ENCODING *enc,
- const char *ptr,
- const char *end,
- const char **badPtr,
- const char **versionPtr,
- const char **versionEndPtr,
+int XmlParseXmlDecl(int isGeneralTextEntity, const ENCODING *enc,
+ const char *ptr, const char *end, const char **badPtr,
+ const char **versionPtr, const char **versionEndPtr,
const char **encodingNamePtr,
- const ENCODING **namedEncodingPtr,
- int *standalonePtr);
+ const ENCODING **namedEncodingPtr, int *standalonePtr);
int XmlInitEncoding(INIT_ENCODING *, const ENCODING **, const char *name);
const ENCODING *XmlGetUtf8InternalEncoding(void);
int FASTCALL XmlUtf16Encode(int charNumber, unsigned short *buf);
int XmlSizeOfUnknownEncoding(void);
+typedef int(XMLCALL *CONVERTER)(void *userData, const char *p);
-typedef int (XMLCALL *CONVERTER) (void *userData, const char *p);
-
-ENCODING *
-XmlInitUnknownEncoding(void *mem,
- int *table,
- CONVERTER convert,
- void *userData);
+ENCODING *XmlInitUnknownEncoding(void *mem, int *table, CONVERTER convert,
+ void *userData);
-int XmlParseXmlDeclNS(int isGeneralTextEntity,
- const ENCODING *enc,
- const char *ptr,
- const char *end,
- const char **badPtr,
- const char **versionPtr,
- const char **versionEndPtr,
+int XmlParseXmlDeclNS(int isGeneralTextEntity, const ENCODING *enc,
+ const char *ptr, const char *end, const char **badPtr,
+ const char **versionPtr, const char **versionEndPtr,
const char **encodingNamePtr,
- const ENCODING **namedEncodingPtr,
- int *standalonePtr);
+ const ENCODING **namedEncodingPtr, int *standalonePtr);
int XmlInitEncodingNS(INIT_ENCODING *, const ENCODING **, const char *name);
const ENCODING *XmlGetUtf8InternalEncodingNS(void);
const ENCODING *XmlGetUtf16InternalEncodingNS(void);
-ENCODING *
-XmlInitUnknownEncodingNS(void *mem,
- int *table,
- CONVERTER convert,
- void *userData);
+ENCODING *XmlInitUnknownEncodingNS(void *mem, int *table, CONVERTER convert,
+ void *userData);
#ifdef __cplusplus
}
#endif
#ifdef XML_TOK_IMPL_C
-#ifndef IS_INVALID_CHAR
-#define IS_INVALID_CHAR(enc, ptr, n) (0)
-#endif
-
-#define INVALID_LEAD_CASE(n, ptr, nextTokPtr) \
- case BT_LEAD ## n: \
- if (end - ptr < n) \
- return XML_TOK_PARTIAL_CHAR; \
- if (IS_INVALID_CHAR(enc, ptr, n)) { \
- *(nextTokPtr) = (ptr); \
- return XML_TOK_INVALID; \
- } \
- ptr += n; \
- break;
+# ifndef IS_INVALID_CHAR
+# define IS_INVALID_CHAR(enc, ptr, n) (0)
+# endif
+
+# define INVALID_LEAD_CASE(n, ptr, nextTokPtr) \
+ case BT_LEAD##n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (IS_INVALID_CHAR(enc, ptr, n)) { \
+ *(nextTokPtr) = (ptr); \
+ return XML_TOK_INVALID; \
+ } \
+ ptr += n; \
+ break;
-#define INVALID_CASES(ptr, nextTokPtr) \
- INVALID_LEAD_CASE(2, ptr, nextTokPtr) \
- INVALID_LEAD_CASE(3, ptr, nextTokPtr) \
- INVALID_LEAD_CASE(4, ptr, nextTokPtr) \
- case BT_NONXML: \
- case BT_MALFORM: \
- case BT_TRAIL: \
- *(nextTokPtr) = (ptr); \
+# define INVALID_CASES(ptr, nextTokPtr) \
+ INVALID_LEAD_CASE(2, ptr, nextTokPtr) \
+ INVALID_LEAD_CASE(3, ptr, nextTokPtr) \
+ INVALID_LEAD_CASE(4, ptr, nextTokPtr) \
+ case BT_NONXML: \
+ case BT_MALFORM: \
+ case BT_TRAIL: \
+ *(nextTokPtr) = (ptr); \
return XML_TOK_INVALID;
-#define CHECK_NAME_CASE(n, enc, ptr, end, nextTokPtr) \
- case BT_LEAD ## n: \
- if (end - ptr < n) \
- return XML_TOK_PARTIAL_CHAR; \
- if (!IS_NAME_CHAR(enc, ptr, n)) { \
- *nextTokPtr = ptr; \
- return XML_TOK_INVALID; \
- } \
- ptr += n; \
- break;
-
-#define CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) \
- case BT_NONASCII: \
- if (!IS_NAME_CHAR_MINBPC(enc, ptr)) { \
- *nextTokPtr = ptr; \
- return XML_TOK_INVALID; \
- } \
- /* fall through */ \
- case BT_NMSTRT: \
- case BT_HEX: \
- case BT_DIGIT: \
- case BT_NAME: \
- case BT_MINUS: \
- ptr += MINBPC(enc); \
- break; \
- CHECK_NAME_CASE(2, enc, ptr, end, nextTokPtr) \
- CHECK_NAME_CASE(3, enc, ptr, end, nextTokPtr) \
- CHECK_NAME_CASE(4, enc, ptr, end, nextTokPtr)
-
-#define CHECK_NMSTRT_CASE(n, enc, ptr, end, nextTokPtr) \
- case BT_LEAD ## n: \
- if (end - ptr < n) \
- return XML_TOK_PARTIAL_CHAR; \
- if (!IS_NMSTRT_CHAR(enc, ptr, n)) { \
- *nextTokPtr = ptr; \
- return XML_TOK_INVALID; \
- } \
- ptr += n; \
- break;
-
-#define CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) \
- case BT_NONASCII: \
- if (!IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { \
- *nextTokPtr = ptr; \
- return XML_TOK_INVALID; \
- } \
- /* fall through */ \
- case BT_NMSTRT: \
- case BT_HEX: \
- ptr += MINBPC(enc); \
- break; \
- CHECK_NMSTRT_CASE(2, enc, ptr, end, nextTokPtr) \
- CHECK_NMSTRT_CASE(3, enc, ptr, end, nextTokPtr) \
- CHECK_NMSTRT_CASE(4, enc, ptr, end, nextTokPtr)
-
-#ifndef PREFIX
-#define PREFIX(ident) ident
-#endif
-
-
-#define HAS_CHARS(enc, ptr, end, count) \
- (end - ptr >= count * MINBPC(enc))
+# define CHECK_NAME_CASE(n, enc, ptr, end, nextTokPtr) \
+ case BT_LEAD##n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (! IS_NAME_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ ptr += n; \
+ break;
-#define HAS_CHAR(enc, ptr, end) \
- HAS_CHARS(enc, ptr, end, 1)
+# define CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) \
+ case BT_NONASCII: \
+ if (! IS_NAME_CHAR_MINBPC(enc, ptr)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ /* fall through */ \
+ case BT_NMSTRT: \
+ case BT_HEX: \
+ case BT_DIGIT: \
+ case BT_NAME: \
+ case BT_MINUS: \
+ ptr += MINBPC(enc); \
+ break; \
+ CHECK_NAME_CASE(2, enc, ptr, end, nextTokPtr) \
+ CHECK_NAME_CASE(3, enc, ptr, end, nextTokPtr) \
+ CHECK_NAME_CASE(4, enc, ptr, end, nextTokPtr)
+
+# define CHECK_NMSTRT_CASE(n, enc, ptr, end, nextTokPtr) \
+ case BT_LEAD##n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (! IS_NMSTRT_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ ptr += n; \
+ break;
-#define REQUIRE_CHARS(enc, ptr, end, count) \
- { \
- if (! HAS_CHARS(enc, ptr, end, count)) { \
- return XML_TOK_PARTIAL; \
- } \
+# define CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) \
+ case BT_NONASCII: \
+ if (! IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ /* fall through */ \
+ case BT_NMSTRT: \
+ case BT_HEX: \
+ ptr += MINBPC(enc); \
+ break; \
+ CHECK_NMSTRT_CASE(2, enc, ptr, end, nextTokPtr) \
+ CHECK_NMSTRT_CASE(3, enc, ptr, end, nextTokPtr) \
+ CHECK_NMSTRT_CASE(4, enc, ptr, end, nextTokPtr)
+
+# ifndef PREFIX
+# define PREFIX(ident) ident
+# endif
+
+# define HAS_CHARS(enc, ptr, end, count) (end - ptr >= count * MINBPC(enc))
+
+# define HAS_CHAR(enc, ptr, end) HAS_CHARS(enc, ptr, end, 1)
+
+# define REQUIRE_CHARS(enc, ptr, end, count) \
+ { \
+ if (! HAS_CHARS(enc, ptr, end, count)) { \
+ return XML_TOK_PARTIAL; \
+ } \
}
-#define REQUIRE_CHAR(enc, ptr, end) \
- REQUIRE_CHARS(enc, ptr, end, 1)
-
+# define REQUIRE_CHAR(enc, ptr, end) REQUIRE_CHARS(enc, ptr, end, 1)
/* ptr points to character following "<!-" */
static int PTRCALL
-PREFIX(scanComment)(const ENCODING *enc, const char *ptr,
- const char *end, const char **nextTokPtr)
-{
+PREFIX(scanComment)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr) {
if (HAS_CHAR(enc, ptr, end)) {
- if (!CHAR_MATCHES(enc, ptr, ASCII_MINUS)) {
+ if (! CHAR_MATCHES(enc, ptr, ASCII_MINUS)) {
*nextTokPtr = ptr;
return XML_TOK_INVALID;
}
ptr += MINBPC(enc);
while (HAS_CHAR(enc, ptr, end)) {
switch (BYTE_TYPE(enc, ptr)) {
- INVALID_CASES(ptr, nextTokPtr)
+ INVALID_CASES(ptr, nextTokPtr)
case BT_MINUS:
ptr += MINBPC(enc);
REQUIRE_CHAR(enc, ptr, end);
if (CHAR_MATCHES(enc, ptr, ASCII_MINUS)) {
ptr += MINBPC(enc);
REQUIRE_CHAR(enc, ptr, end);
- if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ if (! CHAR_MATCHES(enc, ptr, ASCII_GT)) {
*nextTokPtr = ptr;
return XML_TOK_INVALID;
}
/* ptr points to character following "<!" */
static int PTRCALL
-PREFIX(scanDecl)(const ENCODING *enc, const char *ptr,
- const char *end, const char **nextTokPtr)
-{
+PREFIX(scanDecl)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr) {
REQUIRE_CHAR(enc, ptr, end);
switch (BYTE_TYPE(enc, ptr)) {
case BT_MINUS:
REQUIRE_CHARS(enc, ptr, end, 2);
/* don't allow <!ENTITY% foo "whatever"> */
switch (BYTE_TYPE(enc, ptr + MINBPC(enc))) {
- case BT_S: case BT_CR: case BT_LF: case BT_PERCNT:
+ case BT_S:
+ case BT_CR:
+ case BT_LF:
+ case BT_PERCNT:
*nextTokPtr = ptr;
return XML_TOK_INVALID;
}
/* fall through */
- case BT_S: case BT_CR: case BT_LF:
+ case BT_S:
+ case BT_CR:
+ case BT_LF:
*nextTokPtr = ptr;
return XML_TOK_DECL_OPEN;
case BT_NMSTRT:
}
static int PTRCALL
-PREFIX(checkPiTarget)(const ENCODING *UNUSED_P(enc), const char *ptr,
- const char *end, int *tokPtr)
-{
+PREFIX(checkPiTarget)(const ENCODING *enc, const char *ptr, const char *end,
+ int *tokPtr) {
int upper = 0;
+ UNUSED_P(enc);
*tokPtr = XML_TOK_PI;
- if (end - ptr != MINBPC(enc)*3)
+ if (end - ptr != MINBPC(enc) * 3)
return 1;
switch (BYTE_TO_ASCII(enc, ptr)) {
case ASCII_x:
/* ptr points to character following "<?" */
static int PTRCALL
-PREFIX(scanPi)(const ENCODING *enc, const char *ptr,
- const char *end, const char **nextTokPtr)
-{
+PREFIX(scanPi)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr) {
int tok;
const char *target = ptr;
REQUIRE_CHAR(enc, ptr, end);
switch (BYTE_TYPE(enc, ptr)) {
- CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
default:
*nextTokPtr = ptr;
return XML_TOK_INVALID;
}
while (HAS_CHAR(enc, ptr, end)) {
switch (BYTE_TYPE(enc, ptr)) {
- CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
- case BT_S: case BT_CR: case BT_LF:
- if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S:
+ case BT_CR:
+ case BT_LF:
+ if (! PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
*nextTokPtr = ptr;
return XML_TOK_INVALID;
}
ptr += MINBPC(enc);
while (HAS_CHAR(enc, ptr, end)) {
switch (BYTE_TYPE(enc, ptr)) {
- INVALID_CASES(ptr, nextTokPtr)
+ INVALID_CASES(ptr, nextTokPtr)
case BT_QUEST:
ptr += MINBPC(enc);
REQUIRE_CHAR(enc, ptr, end);
}
return XML_TOK_PARTIAL;
case BT_QUEST:
- if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
+ if (! PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
*nextTokPtr = ptr;
return XML_TOK_INVALID;
}
}
static int PTRCALL
-PREFIX(scanCdataSection)(const ENCODING *UNUSED_P(enc), const char *ptr,
- const char *end, const char **nextTokPtr)
-{
- static const char CDATA_LSQB[] = { ASCII_C, ASCII_D, ASCII_A,
- ASCII_T, ASCII_A, ASCII_LSQB };
+PREFIX(scanCdataSection)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr) {
+ static const char CDATA_LSQB[]
+ = {ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, ASCII_LSQB};
int i;
+ UNUSED_P(enc);
/* CDATA[ */
REQUIRE_CHARS(enc, ptr, end, 6);
for (i = 0; i < 6; i++, ptr += MINBPC(enc)) {
- if (!CHAR_MATCHES(enc, ptr, CDATA_LSQB[i])) {
+ if (! CHAR_MATCHES(enc, ptr, CDATA_LSQB[i])) {
*nextTokPtr = ptr;
return XML_TOK_INVALID;
}
}
static int PTRCALL
-PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr,
- const char *end, const char **nextTokPtr)
-{
+PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr) {
if (ptr >= end)
return XML_TOK_NONE;
if (MINBPC(enc) > 1) {
case BT_RSQB:
ptr += MINBPC(enc);
REQUIRE_CHAR(enc, ptr, end);
- if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB))
+ if (! CHAR_MATCHES(enc, ptr, ASCII_RSQB))
break;
ptr += MINBPC(enc);
REQUIRE_CHAR(enc, ptr, end);
- if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ if (! CHAR_MATCHES(enc, ptr, ASCII_GT)) {
ptr -= MINBPC(enc);
break;
}
case BT_LF:
*nextTokPtr = ptr + MINBPC(enc);
return XML_TOK_DATA_NEWLINE;
- INVALID_CASES(ptr, nextTokPtr)
+ INVALID_CASES(ptr, nextTokPtr)
default:
ptr += MINBPC(enc);
break;
}
while (HAS_CHAR(enc, ptr, end)) {
switch (BYTE_TYPE(enc, ptr)) {
-#define LEAD_CASE(n) \
- case BT_LEAD ## n: \
- if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
- *nextTokPtr = ptr; \
- return XML_TOK_DATA_CHARS; \
- } \
- ptr += n; \
- break;
- LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
-#undef LEAD_CASE
+# define LEAD_CASE(n) \
+ case BT_LEAD##n: \
+ if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_DATA_CHARS; \
+ } \
+ ptr += n; \
+ break;
+ LEAD_CASE(2)
+ LEAD_CASE(3)
+ LEAD_CASE(4)
+# undef LEAD_CASE
case BT_NONXML:
case BT_MALFORM:
case BT_TRAIL:
/* ptr points to character following "</" */
static int PTRCALL
-PREFIX(scanEndTag)(const ENCODING *enc, const char *ptr,
- const char *end, const char **nextTokPtr)
-{
+PREFIX(scanEndTag)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr) {
REQUIRE_CHAR(enc, ptr, end);
switch (BYTE_TYPE(enc, ptr)) {
- CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
default:
*nextTokPtr = ptr;
return XML_TOK_INVALID;
}
while (HAS_CHAR(enc, ptr, end)) {
switch (BYTE_TYPE(enc, ptr)) {
- CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
- case BT_S: case BT_CR: case BT_LF:
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S:
+ case BT_CR:
+ case BT_LF:
for (ptr += MINBPC(enc); HAS_CHAR(enc, ptr, end); ptr += MINBPC(enc)) {
switch (BYTE_TYPE(enc, ptr)) {
- case BT_S: case BT_CR: case BT_LF:
+ case BT_S:
+ case BT_CR:
+ case BT_LF:
break;
case BT_GT:
*nextTokPtr = ptr + MINBPC(enc);
}
}
return XML_TOK_PARTIAL;
-#ifdef XML_NS
+# ifdef XML_NS
case BT_COLON:
/* no need to check qname syntax here,
since end-tag must match exactly */
ptr += MINBPC(enc);
break;
-#endif
+# endif
case BT_GT:
*nextTokPtr = ptr + MINBPC(enc);
return XML_TOK_END_TAG;
/* ptr points to character following "&#X" */
static int PTRCALL
-PREFIX(scanHexCharRef)(const ENCODING *enc, const char *ptr,
- const char *end, const char **nextTokPtr)
-{
+PREFIX(scanHexCharRef)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr) {
if (HAS_CHAR(enc, ptr, end)) {
switch (BYTE_TYPE(enc, ptr)) {
case BT_DIGIT:
/* ptr points to character following "&#" */
static int PTRCALL
-PREFIX(scanCharRef)(const ENCODING *enc, const char *ptr,
- const char *end, const char **nextTokPtr)
-{
+PREFIX(scanCharRef)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr) {
if (HAS_CHAR(enc, ptr, end)) {
if (CHAR_MATCHES(enc, ptr, ASCII_x))
return PREFIX(scanHexCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
static int PTRCALL
PREFIX(scanRef)(const ENCODING *enc, const char *ptr, const char *end,
- const char **nextTokPtr)
-{
+ const char **nextTokPtr) {
REQUIRE_CHAR(enc, ptr, end);
switch (BYTE_TYPE(enc, ptr)) {
- CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
case BT_NUM:
return PREFIX(scanCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
default:
}
while (HAS_CHAR(enc, ptr, end)) {
switch (BYTE_TYPE(enc, ptr)) {
- CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
case BT_SEMI:
*nextTokPtr = ptr + MINBPC(enc);
return XML_TOK_ENTITY_REF;
static int PTRCALL
PREFIX(scanAtts)(const ENCODING *enc, const char *ptr, const char *end,
- const char **nextTokPtr)
-{
-#ifdef XML_NS
+ const char **nextTokPtr) {
+# ifdef XML_NS
int hadColon = 0;
-#endif
+# endif
while (HAS_CHAR(enc, ptr, end)) {
switch (BYTE_TYPE(enc, ptr)) {
- CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
-#ifdef XML_NS
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+# ifdef XML_NS
case BT_COLON:
if (hadColon) {
*nextTokPtr = ptr;
ptr += MINBPC(enc);
REQUIRE_CHAR(enc, ptr, end);
switch (BYTE_TYPE(enc, ptr)) {
- CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
default:
*nextTokPtr = ptr;
return XML_TOK_INVALID;
}
break;
-#endif
- case BT_S: case BT_CR: case BT_LF:
+# endif
+ case BT_S:
+ case BT_CR:
+ case BT_LF:
for (;;) {
int t;
}
}
/* fall through */
- case BT_EQUALS:
- {
- int open;
-#ifdef XML_NS
- hadColon = 0;
-#endif
- for (;;) {
- ptr += MINBPC(enc);
- REQUIRE_CHAR(enc, ptr, end);
- open = BYTE_TYPE(enc, ptr);
- if (open == BT_QUOT || open == BT_APOS)
- break;
- switch (open) {
- case BT_S:
- case BT_LF:
- case BT_CR:
- break;
- default:
- *nextTokPtr = ptr;
- return XML_TOK_INVALID;
- }
- }
+ case BT_EQUALS: {
+ int open;
+# ifdef XML_NS
+ hadColon = 0;
+# endif
+ for (;;) {
ptr += MINBPC(enc);
- /* in attribute value */
- for (;;) {
- int t;
- REQUIRE_CHAR(enc, ptr, end);
- t = BYTE_TYPE(enc, ptr);
- if (t == open)
- break;
- switch (t) {
+ REQUIRE_CHAR(enc, ptr, end);
+ open = BYTE_TYPE(enc, ptr);
+ if (open == BT_QUOT || open == BT_APOS)
+ break;
+ switch (open) {
+ case BT_S:
+ case BT_LF:
+ case BT_CR:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ ptr += MINBPC(enc);
+ /* in attribute value */
+ for (;;) {
+ int t;
+ REQUIRE_CHAR(enc, ptr, end);
+ t = BYTE_TYPE(enc, ptr);
+ if (t == open)
+ break;
+ switch (t) {
INVALID_CASES(ptr, nextTokPtr)
- case BT_AMP:
- {
- int tok = PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, &ptr);
- if (tok <= 0) {
- if (tok == XML_TOK_INVALID)
- *nextTokPtr = ptr;
- return tok;
- }
- break;
- }
- case BT_LT:
- *nextTokPtr = ptr;
- return XML_TOK_INVALID;
- default:
- ptr += MINBPC(enc);
- break;
+ case BT_AMP: {
+ int tok = PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, &ptr);
+ if (tok <= 0) {
+ if (tok == XML_TOK_INVALID)
+ *nextTokPtr = ptr;
+ return tok;
}
+ break;
+ }
+ case BT_LT:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ default:
+ ptr += MINBPC(enc);
+ break;
}
+ }
+ ptr += MINBPC(enc);
+ REQUIRE_CHAR(enc, ptr, end);
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_S:
+ case BT_CR:
+ case BT_LF:
+ break;
+ case BT_SOL:
+ goto sol;
+ case BT_GT:
+ goto gt;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ /* ptr points to closing quote */
+ for (;;) {
ptr += MINBPC(enc);
REQUIRE_CHAR(enc, ptr, end);
switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
case BT_S:
case BT_CR:
case BT_LF:
- break;
- case BT_SOL:
- goto sol;
+ continue;
case BT_GT:
- goto gt;
- default:
- *nextTokPtr = ptr;
- return XML_TOK_INVALID;
- }
- /* ptr points to closing quote */
- for (;;) {
+ gt:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_START_TAG_WITH_ATTS;
+ case BT_SOL:
+ sol:
ptr += MINBPC(enc);
REQUIRE_CHAR(enc, ptr, end);
- switch (BYTE_TYPE(enc, ptr)) {
- CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
- case BT_S: case BT_CR: case BT_LF:
- continue;
- case BT_GT:
- gt:
- *nextTokPtr = ptr + MINBPC(enc);
- return XML_TOK_START_TAG_WITH_ATTS;
- case BT_SOL:
- sol:
- ptr += MINBPC(enc);
- REQUIRE_CHAR(enc, ptr, end);
- if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
- *nextTokPtr = ptr;
- return XML_TOK_INVALID;
- }
- *nextTokPtr = ptr + MINBPC(enc);
- return XML_TOK_EMPTY_ELEMENT_WITH_ATTS;
- default:
+ if (! CHAR_MATCHES(enc, ptr, ASCII_GT)) {
*nextTokPtr = ptr;
return XML_TOK_INVALID;
}
- break;
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_EMPTY_ELEMENT_WITH_ATTS;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
}
break;
}
+ break;
+ }
default:
*nextTokPtr = ptr;
return XML_TOK_INVALID;
static int PTRCALL
PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end,
- const char **nextTokPtr)
-{
-#ifdef XML_NS
+ const char **nextTokPtr) {
+# ifdef XML_NS
int hadColon;
-#endif
+# endif
REQUIRE_CHAR(enc, ptr, end);
switch (BYTE_TYPE(enc, ptr)) {
- CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
case BT_EXCL:
ptr += MINBPC(enc);
REQUIRE_CHAR(enc, ptr, end);
case BT_MINUS:
return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr);
case BT_LSQB:
- return PREFIX(scanCdataSection)(enc, ptr + MINBPC(enc),
- end, nextTokPtr);
+ return PREFIX(scanCdataSection)(enc, ptr + MINBPC(enc), end, nextTokPtr);
}
*nextTokPtr = ptr;
return XML_TOK_INVALID;
*nextTokPtr = ptr;
return XML_TOK_INVALID;
}
-#ifdef XML_NS
+# ifdef XML_NS
hadColon = 0;
-#endif
+# endif
/* we have a start-tag */
while (HAS_CHAR(enc, ptr, end)) {
switch (BYTE_TYPE(enc, ptr)) {
- CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
-#ifdef XML_NS
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+# ifdef XML_NS
case BT_COLON:
if (hadColon) {
*nextTokPtr = ptr;
ptr += MINBPC(enc);
REQUIRE_CHAR(enc, ptr, end);
switch (BYTE_TYPE(enc, ptr)) {
- CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
default:
*nextTokPtr = ptr;
return XML_TOK_INVALID;
}
break;
-#endif
- case BT_S: case BT_CR: case BT_LF:
- {
- ptr += MINBPC(enc);
- while (HAS_CHAR(enc, ptr, end)) {
- switch (BYTE_TYPE(enc, ptr)) {
+# endif
+ case BT_S:
+ case BT_CR:
+ case BT_LF: {
+ ptr += MINBPC(enc);
+ while (HAS_CHAR(enc, ptr, end)) {
+ switch (BYTE_TYPE(enc, ptr)) {
CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
- case BT_GT:
- goto gt;
- case BT_SOL:
- goto sol;
- case BT_S: case BT_CR: case BT_LF:
- ptr += MINBPC(enc);
- continue;
- default:
- *nextTokPtr = ptr;
- return XML_TOK_INVALID;
- }
- return PREFIX(scanAtts)(enc, ptr, end, nextTokPtr);
+ case BT_GT:
+ goto gt;
+ case BT_SOL:
+ goto sol;
+ case BT_S:
+ case BT_CR:
+ case BT_LF:
+ ptr += MINBPC(enc);
+ continue;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
}
- return XML_TOK_PARTIAL;
+ return PREFIX(scanAtts)(enc, ptr, end, nextTokPtr);
}
+ return XML_TOK_PARTIAL;
+ }
case BT_GT:
gt:
*nextTokPtr = ptr + MINBPC(enc);
sol:
ptr += MINBPC(enc);
REQUIRE_CHAR(enc, ptr, end);
- if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ if (! CHAR_MATCHES(enc, ptr, ASCII_GT)) {
*nextTokPtr = ptr;
return XML_TOK_INVALID;
}
static int PTRCALL
PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end,
- const char **nextTokPtr)
-{
+ const char **nextTokPtr) {
if (ptr >= end)
return XML_TOK_NONE;
if (MINBPC(enc) > 1) {
ptr += MINBPC(enc);
if (! HAS_CHAR(enc, ptr, end))
return XML_TOK_TRAILING_RSQB;
- if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB))
+ if (! CHAR_MATCHES(enc, ptr, ASCII_RSQB))
break;
ptr += MINBPC(enc);
if (! HAS_CHAR(enc, ptr, end))
return XML_TOK_TRAILING_RSQB;
- if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ if (! CHAR_MATCHES(enc, ptr, ASCII_GT)) {
ptr -= MINBPC(enc);
break;
}
*nextTokPtr = ptr;
return XML_TOK_INVALID;
- INVALID_CASES(ptr, nextTokPtr)
+ INVALID_CASES(ptr, nextTokPtr)
default:
ptr += MINBPC(enc);
break;
}
while (HAS_CHAR(enc, ptr, end)) {
switch (BYTE_TYPE(enc, ptr)) {
-#define LEAD_CASE(n) \
- case BT_LEAD ## n: \
- if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
- *nextTokPtr = ptr; \
- return XML_TOK_DATA_CHARS; \
- } \
- ptr += n; \
- break;
- LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
-#undef LEAD_CASE
+# define LEAD_CASE(n) \
+ case BT_LEAD##n: \
+ if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_DATA_CHARS; \
+ } \
+ ptr += n; \
+ break;
+ LEAD_CASE(2)
+ LEAD_CASE(3)
+ LEAD_CASE(4)
+# undef LEAD_CASE
case BT_RSQB:
if (HAS_CHARS(enc, ptr, end, 2)) {
- if (!CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_RSQB)) {
- ptr += MINBPC(enc);
- break;
- }
- if (HAS_CHARS(enc, ptr, end, 3)) {
- if (!CHAR_MATCHES(enc, ptr + 2*MINBPC(enc), ASCII_GT)) {
- ptr += MINBPC(enc);
- break;
- }
- *nextTokPtr = ptr + 2*MINBPC(enc);
- return XML_TOK_INVALID;
- }
+ if (! CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_RSQB)) {
+ ptr += MINBPC(enc);
+ break;
+ }
+ if (HAS_CHARS(enc, ptr, end, 3)) {
+ if (! CHAR_MATCHES(enc, ptr + 2 * MINBPC(enc), ASCII_GT)) {
+ ptr += MINBPC(enc);
+ break;
+ }
+ *nextTokPtr = ptr + 2 * MINBPC(enc);
+ return XML_TOK_INVALID;
+ }
}
/* fall through */
case BT_AMP:
static int PTRCALL
PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end,
- const char **nextTokPtr)
-{
+ const char **nextTokPtr) {
REQUIRE_CHAR(enc, ptr, end);
switch (BYTE_TYPE(enc, ptr)) {
- CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
- case BT_S: case BT_LF: case BT_CR: case BT_PERCNT:
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S:
+ case BT_LF:
+ case BT_CR:
+ case BT_PERCNT:
*nextTokPtr = ptr;
return XML_TOK_PERCENT;
default:
}
while (HAS_CHAR(enc, ptr, end)) {
switch (BYTE_TYPE(enc, ptr)) {
- CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
case BT_SEMI:
*nextTokPtr = ptr + MINBPC(enc);
return XML_TOK_PARAM_ENTITY_REF;
static int PTRCALL
PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end,
- const char **nextTokPtr)
-{
+ const char **nextTokPtr) {
REQUIRE_CHAR(enc, ptr, end);
switch (BYTE_TYPE(enc, ptr)) {
- CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
default:
*nextTokPtr = ptr;
return XML_TOK_INVALID;
}
while (HAS_CHAR(enc, ptr, end)) {
switch (BYTE_TYPE(enc, ptr)) {
- CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
- case BT_CR: case BT_LF: case BT_S:
- case BT_RPAR: case BT_GT: case BT_PERCNT: case BT_VERBAR:
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_CR:
+ case BT_LF:
+ case BT_S:
+ case BT_RPAR:
+ case BT_GT:
+ case BT_PERCNT:
+ case BT_VERBAR:
*nextTokPtr = ptr;
return XML_TOK_POUND_NAME;
default:
}
static int PTRCALL
-PREFIX(scanLit)(int open, const ENCODING *enc,
- const char *ptr, const char *end,
- const char **nextTokPtr)
-{
+PREFIX(scanLit)(int open, const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr) {
while (HAS_CHAR(enc, ptr, end)) {
int t = BYTE_TYPE(enc, ptr);
switch (t) {
- INVALID_CASES(ptr, nextTokPtr)
+ INVALID_CASES(ptr, nextTokPtr)
case BT_QUOT:
case BT_APOS:
ptr += MINBPC(enc);
return -XML_TOK_LITERAL;
*nextTokPtr = ptr;
switch (BYTE_TYPE(enc, ptr)) {
- case BT_S: case BT_CR: case BT_LF:
- case BT_GT: case BT_PERCNT: case BT_LSQB:
+ case BT_S:
+ case BT_CR:
+ case BT_LF:
+ case BT_GT:
+ case BT_PERCNT:
+ case BT_LSQB:
return XML_TOK_LITERAL;
default:
return XML_TOK_INVALID;
static int PTRCALL
PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end,
- const char **nextTokPtr)
-{
+ const char **nextTokPtr) {
int tok;
if (ptr >= end)
return XML_TOK_NONE;
return PREFIX(scanLit)(BT_QUOT, enc, ptr + MINBPC(enc), end, nextTokPtr);
case BT_APOS:
return PREFIX(scanLit)(BT_APOS, enc, ptr + MINBPC(enc), end, nextTokPtr);
- case BT_LT:
- {
- ptr += MINBPC(enc);
- REQUIRE_CHAR(enc, ptr, end);
- switch (BYTE_TYPE(enc, ptr)) {
- case BT_EXCL:
- return PREFIX(scanDecl)(enc, ptr + MINBPC(enc), end, nextTokPtr);
- case BT_QUEST:
- return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr);
- case BT_NMSTRT:
- case BT_HEX:
- case BT_NONASCII:
- case BT_LEAD2:
- case BT_LEAD3:
- case BT_LEAD4:
- *nextTokPtr = ptr - MINBPC(enc);
- return XML_TOK_INSTANCE_START;
- }
- *nextTokPtr = ptr;
- return XML_TOK_INVALID;
+ case BT_LT: {
+ ptr += MINBPC(enc);
+ REQUIRE_CHAR(enc, ptr, end);
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_EXCL:
+ return PREFIX(scanDecl)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_QUEST:
+ return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_NMSTRT:
+ case BT_HEX:
+ case BT_NONASCII:
+ case BT_LEAD2:
+ case BT_LEAD3:
+ case BT_LEAD4:
+ *nextTokPtr = ptr - MINBPC(enc);
+ return XML_TOK_INSTANCE_START;
}
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
case BT_CR:
if (ptr + MINBPC(enc) == end) {
*nextTokPtr = end;
return -XML_TOK_PROLOG_S;
}
/* fall through */
- case BT_S: case BT_LF:
+ case BT_S:
+ case BT_LF:
for (;;) {
ptr += MINBPC(enc);
if (! HAS_CHAR(enc, ptr, end))
break;
switch (BYTE_TYPE(enc, ptr)) {
- case BT_S: case BT_LF:
+ case BT_S:
+ case BT_LF:
break;
case BT_CR:
/* don't split CR/LF pair */
if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) {
REQUIRE_CHARS(enc, ptr, end, 2);
if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_GT)) {
- *nextTokPtr = ptr + 2*MINBPC(enc);
+ *nextTokPtr = ptr + 2 * MINBPC(enc);
return XML_TOK_COND_SECT_CLOSE;
}
}
case BT_PLUS:
*nextTokPtr = ptr + MINBPC(enc);
return XML_TOK_CLOSE_PAREN_PLUS;
- case BT_CR: case BT_LF: case BT_S:
- case BT_GT: case BT_COMMA: case BT_VERBAR:
+ case BT_CR:
+ case BT_LF:
+ case BT_S:
+ case BT_GT:
+ case BT_COMMA:
+ case BT_VERBAR:
case BT_RPAR:
*nextTokPtr = ptr;
return XML_TOK_CLOSE_PAREN;
return XML_TOK_DECL_CLOSE;
case BT_NUM:
return PREFIX(scanPoundName)(enc, ptr + MINBPC(enc), end, nextTokPtr);
-#define LEAD_CASE(n) \
- case BT_LEAD ## n: \
- if (end - ptr < n) \
- return XML_TOK_PARTIAL_CHAR; \
- if (IS_NMSTRT_CHAR(enc, ptr, n)) { \
- ptr += n; \
- tok = XML_TOK_NAME; \
- break; \
- } \
- if (IS_NAME_CHAR(enc, ptr, n)) { \
- ptr += n; \
- tok = XML_TOK_NMTOKEN; \
- break; \
- } \
- *nextTokPtr = ptr; \
+# define LEAD_CASE(n) \
+ case BT_LEAD##n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (IS_NMSTRT_CHAR(enc, ptr, n)) { \
+ ptr += n; \
+ tok = XML_TOK_NAME; \
+ break; \
+ } \
+ if (IS_NAME_CHAR(enc, ptr, n)) { \
+ ptr += n; \
+ tok = XML_TOK_NMTOKEN; \
+ break; \
+ } \
+ *nextTokPtr = ptr; \
return XML_TOK_INVALID;
- LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
-#undef LEAD_CASE
+ LEAD_CASE(2)
+ LEAD_CASE(3)
+ LEAD_CASE(4)
+# undef LEAD_CASE
case BT_NMSTRT:
case BT_HEX:
tok = XML_TOK_NAME;
case BT_DIGIT:
case BT_NAME:
case BT_MINUS:
-#ifdef XML_NS
+# ifdef XML_NS
case BT_COLON:
-#endif
+# endif
tok = XML_TOK_NMTOKEN;
ptr += MINBPC(enc);
break;
}
while (HAS_CHAR(enc, ptr, end)) {
switch (BYTE_TYPE(enc, ptr)) {
- CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
- case BT_GT: case BT_RPAR: case BT_COMMA:
- case BT_VERBAR: case BT_LSQB: case BT_PERCNT:
- case BT_S: case BT_CR: case BT_LF:
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_GT:
+ case BT_RPAR:
+ case BT_COMMA:
+ case BT_VERBAR:
+ case BT_LSQB:
+ case BT_PERCNT:
+ case BT_S:
+ case BT_CR:
+ case BT_LF:
*nextTokPtr = ptr;
return tok;
-#ifdef XML_NS
+# ifdef XML_NS
case BT_COLON:
ptr += MINBPC(enc);
switch (tok) {
REQUIRE_CHAR(enc, ptr, end);
tok = XML_TOK_PREFIXED_NAME;
switch (BYTE_TYPE(enc, ptr)) {
- CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
default:
tok = XML_TOK_NMTOKEN;
break;
break;
}
break;
-#endif
+# endif
case BT_PLUS:
- if (tok == XML_TOK_NMTOKEN) {
+ if (tok == XML_TOK_NMTOKEN) {
*nextTokPtr = ptr;
return XML_TOK_INVALID;
}
*nextTokPtr = ptr + MINBPC(enc);
return XML_TOK_NAME_PLUS;
case BT_AST:
- if (tok == XML_TOK_NMTOKEN) {
+ if (tok == XML_TOK_NMTOKEN) {
*nextTokPtr = ptr;
return XML_TOK_INVALID;
}
*nextTokPtr = ptr + MINBPC(enc);
return XML_TOK_NAME_ASTERISK;
case BT_QUEST:
- if (tok == XML_TOK_NMTOKEN) {
+ if (tok == XML_TOK_NMTOKEN) {
*nextTokPtr = ptr;
return XML_TOK_INVALID;
}
}
static int PTRCALL
-PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr,
- const char *end, const char **nextTokPtr)
-{
+PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr) {
const char *start;
if (ptr >= end)
return XML_TOK_NONE;
start = ptr;
while (HAS_CHAR(enc, ptr, end)) {
switch (BYTE_TYPE(enc, ptr)) {
-#define LEAD_CASE(n) \
- case BT_LEAD ## n: ptr += n; break;
- LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
-#undef LEAD_CASE
+# define LEAD_CASE(n) \
+ case BT_LEAD##n: \
+ ptr += n; \
+ break;
+ LEAD_CASE(2)
+ LEAD_CASE(3)
+ LEAD_CASE(4)
+# undef LEAD_CASE
case BT_AMP:
if (ptr == start)
return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
}
static int PTRCALL
-PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr,
- const char *end, const char **nextTokPtr)
-{
+PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr) {
const char *start;
if (ptr >= end)
return XML_TOK_NONE;
start = ptr;
while (HAS_CHAR(enc, ptr, end)) {
switch (BYTE_TYPE(enc, ptr)) {
-#define LEAD_CASE(n) \
- case BT_LEAD ## n: ptr += n; break;
- LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
-#undef LEAD_CASE
+# define LEAD_CASE(n) \
+ case BT_LEAD##n: \
+ ptr += n; \
+ break;
+ LEAD_CASE(2)
+ LEAD_CASE(3)
+ LEAD_CASE(4)
+# undef LEAD_CASE
case BT_AMP:
if (ptr == start)
return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
return XML_TOK_DATA_CHARS;
case BT_PERCNT:
if (ptr == start) {
- int tok = PREFIX(scanPercent)(enc, ptr + MINBPC(enc),
- end, nextTokPtr);
+ int tok = PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr);
return (tok == XML_TOK_PERCENT) ? XML_TOK_INVALID : tok;
}
*nextTokPtr = ptr;
return XML_TOK_DATA_CHARS;
}
-#ifdef XML_DTD
+# ifdef XML_DTD
static int PTRCALL
-PREFIX(ignoreSectionTok)(const ENCODING *enc, const char *ptr,
- const char *end, const char **nextTokPtr)
-{
+PREFIX(ignoreSectionTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr) {
int level = 0;
if (MINBPC(enc) > 1) {
size_t n = end - ptr;
}
while (HAS_CHAR(enc, ptr, end)) {
switch (BYTE_TYPE(enc, ptr)) {
- INVALID_CASES(ptr, nextTokPtr)
+ INVALID_CASES(ptr, nextTokPtr)
case BT_LT:
ptr += MINBPC(enc);
REQUIRE_CHAR(enc, ptr, end);
return XML_TOK_PARTIAL;
}
-#endif /* XML_DTD */
+# endif /* XML_DTD */
static int PTRCALL
PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
- const char **badPtr)
-{
+ const char **badPtr) {
ptr += MINBPC(enc);
end -= MINBPC(enc);
for (; HAS_CHAR(enc, ptr, end); ptr += MINBPC(enc)) {
case BT_AST:
case BT_PERCNT:
case BT_NUM:
-#ifdef XML_NS
+# ifdef XML_NS
case BT_COLON:
-#endif
+# endif
break;
case BT_S:
if (CHAR_MATCHES(enc, ptr, ASCII_TAB)) {
break;
case BT_NAME:
case BT_NMSTRT:
- if (!(BYTE_TO_ASCII(enc, ptr) & ~0x7f))
+ if (! (BYTE_TO_ASCII(enc, ptr) & ~0x7f))
break;
/* fall through */
default:
*/
static int PTRCALL
-PREFIX(getAtts)(const ENCODING *enc, const char *ptr,
- int attsMax, ATTRIBUTE *atts)
-{
+PREFIX(getAtts)(const ENCODING *enc, const char *ptr, int attsMax,
+ ATTRIBUTE *atts) {
enum { other, inName, inValue } state = inName;
int nAtts = 0;
int open = 0; /* defined when state == inValue;
for (ptr += MINBPC(enc);; ptr += MINBPC(enc)) {
switch (BYTE_TYPE(enc, ptr)) {
-#define START_NAME \
- if (state == other) { \
- if (nAtts < attsMax) { \
- atts[nAtts].name = ptr; \
- atts[nAtts].normalized = 1; \
- } \
- state = inName; \
- }
-#define LEAD_CASE(n) \
- case BT_LEAD ## n: START_NAME ptr += (n - MINBPC(enc)); break;
- LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
-#undef LEAD_CASE
+# define START_NAME \
+ if (state == other) { \
+ if (nAtts < attsMax) { \
+ atts[nAtts].name = ptr; \
+ atts[nAtts].normalized = 1; \
+ } \
+ state = inName; \
+ }
+# define LEAD_CASE(n) \
+ case BT_LEAD##n: \
+ START_NAME ptr += (n - MINBPC(enc)); \
+ break;
+ LEAD_CASE(2)
+ LEAD_CASE(3)
+ LEAD_CASE(4)
+# undef LEAD_CASE
case BT_NONASCII:
case BT_NMSTRT:
case BT_HEX:
START_NAME
break;
-#undef START_NAME
+# undef START_NAME
case BT_QUOT:
if (state != inValue) {
if (nAtts < attsMax)
atts[nAtts].valuePtr = ptr + MINBPC(enc);
state = inValue;
open = BT_QUOT;
- }
- else if (open == BT_QUOT) {
+ } else if (open == BT_QUOT) {
state = other;
if (nAtts < attsMax)
atts[nAtts].valueEnd = ptr;
atts[nAtts].valuePtr = ptr + MINBPC(enc);
state = inValue;
open = BT_APOS;
- }
- else if (open == BT_APOS) {
+ } else if (open == BT_APOS) {
state = other;
if (nAtts < attsMax)
atts[nAtts].valueEnd = ptr;
case BT_S:
if (state == inName)
state = other;
- else if (state == inValue
- && nAtts < attsMax
- && atts[nAtts].normalized
+ else if (state == inValue && nAtts < attsMax && atts[nAtts].normalized
&& (ptr == atts[nAtts].valuePtr
|| BYTE_TO_ASCII(enc, ptr) != ASCII_SPACE
|| BYTE_TO_ASCII(enc, ptr + MINBPC(enc)) == ASCII_SPACE
|| BYTE_TYPE(enc, ptr + MINBPC(enc)) == open))
atts[nAtts].normalized = 0;
break;
- case BT_CR: case BT_LF:
+ case BT_CR:
+ case BT_LF:
/* This case ensures that the first attribute name is counted
Apart from that we could just change state on the quote. */
if (state == inName)
}
static int PTRFASTCALL
-PREFIX(charRefNumber)(const ENCODING *UNUSED_P(enc), const char *ptr)
-{
+PREFIX(charRefNumber)(const ENCODING *enc, const char *ptr) {
int result = 0;
/* skip &# */
- ptr += 2*MINBPC(enc);
+ UNUSED_P(enc);
+ ptr += 2 * MINBPC(enc);
if (CHAR_MATCHES(enc, ptr, ASCII_x)) {
- for (ptr += MINBPC(enc);
- !CHAR_MATCHES(enc, ptr, ASCII_SEMI);
+ for (ptr += MINBPC(enc); ! CHAR_MATCHES(enc, ptr, ASCII_SEMI);
ptr += MINBPC(enc)) {
int c = BYTE_TO_ASCII(enc, ptr);
switch (c) {
- case ASCII_0: case ASCII_1: case ASCII_2: case ASCII_3: case ASCII_4:
- case ASCII_5: case ASCII_6: case ASCII_7: case ASCII_8: case ASCII_9:
+ case ASCII_0:
+ case ASCII_1:
+ case ASCII_2:
+ case ASCII_3:
+ case ASCII_4:
+ case ASCII_5:
+ case ASCII_6:
+ case ASCII_7:
+ case ASCII_8:
+ case ASCII_9:
result <<= 4;
result |= (c - ASCII_0);
break;
- case ASCII_A: case ASCII_B: case ASCII_C:
- case ASCII_D: case ASCII_E: case ASCII_F:
+ case ASCII_A:
+ case ASCII_B:
+ case ASCII_C:
+ case ASCII_D:
+ case ASCII_E:
+ case ASCII_F:
result <<= 4;
result += 10 + (c - ASCII_A);
break;
- case ASCII_a: case ASCII_b: case ASCII_c:
- case ASCII_d: case ASCII_e: case ASCII_f:
+ case ASCII_a:
+ case ASCII_b:
+ case ASCII_c:
+ case ASCII_d:
+ case ASCII_e:
+ case ASCII_f:
result <<= 4;
result += 10 + (c - ASCII_a);
break;
if (result >= 0x110000)
return -1;
}
- }
- else {
- for (; !CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) {
+ } else {
+ for (; ! CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) {
int c = BYTE_TO_ASCII(enc, ptr);
result *= 10;
result += (c - ASCII_0);
}
static int PTRCALL
-PREFIX(predefinedEntityName)(const ENCODING *UNUSED_P(enc), const char *ptr,
- const char *end)
-{
- switch ((end - ptr)/MINBPC(enc)) {
+PREFIX(predefinedEntityName)(const ENCODING *enc, const char *ptr,
+ const char *end) {
+ UNUSED_P(enc);
+ switch ((end - ptr) / MINBPC(enc)) {
case 2:
if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_t)) {
switch (BYTE_TO_ASCII(enc, ptr)) {
}
static int PTRCALL
-PREFIX(nameMatchesAscii)(const ENCODING *UNUSED_P(enc), const char *ptr1,
- const char *end1, const char *ptr2)
-{
+PREFIX(nameMatchesAscii)(const ENCODING *enc, const char *ptr1,
+ const char *end1, const char *ptr2) {
+ UNUSED_P(enc);
for (; *ptr2; ptr1 += MINBPC(enc), ptr2++) {
if (end1 - ptr1 < MINBPC(enc)) {
/* This line cannot be executed. The incoming data has already
*/
return 0; /* LCOV_EXCL_LINE */
}
- if (!CHAR_MATCHES(enc, ptr1, *ptr2))
+ if (! CHAR_MATCHES(enc, ptr1, *ptr2))
return 0;
}
return ptr1 == end1;
}
static int PTRFASTCALL
-PREFIX(nameLength)(const ENCODING *enc, const char *ptr)
-{
+PREFIX(nameLength)(const ENCODING *enc, const char *ptr) {
const char *start = ptr;
for (;;) {
switch (BYTE_TYPE(enc, ptr)) {
-#define LEAD_CASE(n) \
- case BT_LEAD ## n: ptr += n; break;
- LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
-#undef LEAD_CASE
+# define LEAD_CASE(n) \
+ case BT_LEAD##n: \
+ ptr += n; \
+ break;
+ LEAD_CASE(2)
+ LEAD_CASE(3)
+ LEAD_CASE(4)
+# undef LEAD_CASE
case BT_NONASCII:
case BT_NMSTRT:
-#ifdef XML_NS
+# ifdef XML_NS
case BT_COLON:
-#endif
+# endif
case BT_HEX:
case BT_DIGIT:
case BT_NAME:
}
}
-static const char * PTRFASTCALL
-PREFIX(skipS)(const ENCODING *enc, const char *ptr)
-{
+static const char *PTRFASTCALL
+PREFIX(skipS)(const ENCODING *enc, const char *ptr) {
for (;;) {
switch (BYTE_TYPE(enc, ptr)) {
case BT_LF:
}
static void PTRCALL
-PREFIX(updatePosition)(const ENCODING *enc,
- const char *ptr,
- const char *end,
- POSITION *pos)
-{
+PREFIX(updatePosition)(const ENCODING *enc, const char *ptr, const char *end,
+ POSITION *pos) {
while (HAS_CHAR(enc, ptr, end)) {
switch (BYTE_TYPE(enc, ptr)) {
-#define LEAD_CASE(n) \
- case BT_LEAD ## n: \
- ptr += n; \
- break;
- LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
-#undef LEAD_CASE
+# define LEAD_CASE(n) \
+ case BT_LEAD##n: \
+ ptr += n; \
+ break;
+ LEAD_CASE(2)
+ LEAD_CASE(3)
+ LEAD_CASE(4)
+# undef LEAD_CASE
case BT_LF:
pos->columnNumber = (XML_Size)-1;
pos->lineNumber++;
}
}
-#undef DO_LEAD_CASE
-#undef MULTIBYTE_CASES
-#undef INVALID_CASES
-#undef CHECK_NAME_CASE
-#undef CHECK_NAME_CASES
-#undef CHECK_NMSTRT_CASE
-#undef CHECK_NMSTRT_CASES
+# undef DO_LEAD_CASE
+# undef MULTIBYTE_CASES
+# undef INVALID_CASES
+# undef CHECK_NAME_CASE
+# undef CHECK_NAME_CASES
+# undef CHECK_NMSTRT_CASE
+# undef CHECK_NMSTRT_CASES
#endif /* XML_TOK_IMPL_C */
*/
enum {
- BT_NONXML,
- BT_MALFORM,
- BT_LT,
- BT_AMP,
- BT_RSQB,
- BT_LEAD2,
- BT_LEAD3,
- BT_LEAD4,
- BT_TRAIL,
- BT_CR,
- BT_LF,
- BT_GT,
- BT_QUOT,
- BT_APOS,
- BT_EQUALS,
- BT_QUEST,
- BT_EXCL,
- BT_SOL,
- BT_SEMI,
- BT_NUM,
- BT_LSQB,
- BT_S,
- BT_NMSTRT,
- BT_COLON,
- BT_HEX,
- BT_DIGIT,
- BT_NAME,
- BT_MINUS,
- BT_OTHER, /* known not to be a name or name start character */
+ BT_NONXML, /* e.g. noncharacter-FFFF */
+ BT_MALFORM, /* illegal, with regard to encoding */
+ BT_LT, /* less than = "<" */
+ BT_AMP, /* ampersand = "&" */
+ BT_RSQB, /* right square bracket = "[" */
+ BT_LEAD2, /* lead byte of a 2-byte UTF-8 character */
+ BT_LEAD3, /* lead byte of a 3-byte UTF-8 character */
+ BT_LEAD4, /* lead byte of a 4-byte UTF-8 character */
+ BT_TRAIL, /* trailing unit, e.g. second 16-bit unit of a 4-byte char. */
+ BT_CR, /* carriage return = "\r" */
+ BT_LF, /* line feed = "\n" */
+ BT_GT, /* greater than = ">" */
+ BT_QUOT, /* quotation character = "\"" */
+ BT_APOS, /* aposthrophe = "'" */
+ BT_EQUALS, /* equal sign = "=" */
+ BT_QUEST, /* question mark = "?" */
+ BT_EXCL, /* exclamation mark = "!" */
+ BT_SOL, /* solidus, slash = "/" */
+ BT_SEMI, /* semicolon = ";" */
+ BT_NUM, /* number sign = "#" */
+ BT_LSQB, /* left square bracket = "[" */
+ BT_S, /* white space, e.g. "\t", " "[, "\r"] */
+ BT_NMSTRT, /* non-hex name start letter = "G".."Z" + "g".."z" + "_" */
+ BT_COLON, /* colon = ":" */
+ BT_HEX, /* hex letter = "A".."F" + "a".."f" */
+ BT_DIGIT, /* digit = "0".."9" */
+ BT_NAME, /* dot and middle dot = "." + chr(0xb7) */
+ BT_MINUS, /* minus = "-" */
+ BT_OTHER, /* known not to be a name or name start character */
BT_NONASCII, /* might be a name or name start character */
- BT_PERCNT,
- BT_LPAR,
- BT_RPAR,
- BT_AST,
- BT_PLUS,
- BT_COMMA,
- BT_VERBAR
+ BT_PERCNT, /* percent sign = "%" */
+ BT_LPAR, /* left parenthesis = "(" */
+ BT_RPAR, /* right parenthesis = "(" */
+ BT_AST, /* asterisk = "*" */
+ BT_PLUS, /* plus sign = "+" */
+ BT_COMMA, /* comma = "," */
+ BT_VERBAR /* vertical bar = "|" */
};
#include <stddef.h>
#ifdef XML_TOK_NS_C
const ENCODING *
-NS(XmlGetUtf8InternalEncoding)(void)
-{
+NS(XmlGetUtf8InternalEncoding)(void) {
return &ns(internal_utf8_encoding).enc;
}
const ENCODING *
-NS(XmlGetUtf16InternalEncoding)(void)
-{
-#if BYTEORDER == 1234
+NS(XmlGetUtf16InternalEncoding)(void) {
+# if BYTEORDER == 1234
return &ns(internal_little2_encoding).enc;
-#elif BYTEORDER == 4321
+# elif BYTEORDER == 4321
return &ns(internal_big2_encoding).enc;
-#else
+# else
const short n = 1;
- return (*(const char *)&n
- ? &ns(internal_little2_encoding).enc
- : &ns(internal_big2_encoding).enc);
-#endif
+ return (*(const char *)&n ? &ns(internal_little2_encoding).enc
+ : &ns(internal_big2_encoding).enc);
+# endif
}
-static const ENCODING * const NS(encodings)[] = {
- &ns(latin1_encoding).enc,
- &ns(ascii_encoding).enc,
- &ns(utf8_encoding).enc,
- &ns(big2_encoding).enc,
- &ns(big2_encoding).enc,
- &ns(little2_encoding).enc,
- &ns(utf8_encoding).enc /* NO_ENC */
+static const ENCODING *const NS(encodings)[] = {
+ &ns(latin1_encoding).enc, &ns(ascii_encoding).enc,
+ &ns(utf8_encoding).enc, &ns(big2_encoding).enc,
+ &ns(big2_encoding).enc, &ns(little2_encoding).enc,
+ &ns(utf8_encoding).enc /* NO_ENC */
};
static int PTRCALL
NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end,
- const char **nextTokPtr)
-{
- return initScan(NS(encodings), (const INIT_ENCODING *)enc,
- XML_PROLOG_STATE, ptr, end, nextTokPtr);
+ const char **nextTokPtr) {
+ return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_PROLOG_STATE,
+ ptr, end, nextTokPtr);
}
static int PTRCALL
NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end,
- const char **nextTokPtr)
-{
- return initScan(NS(encodings), (const INIT_ENCODING *)enc,
- XML_CONTENT_STATE, ptr, end, nextTokPtr);
+ const char **nextTokPtr) {
+ return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_CONTENT_STATE,
+ ptr, end, nextTokPtr);
}
int
NS(XmlInitEncoding)(INIT_ENCODING *p, const ENCODING **encPtr,
- const char *name)
-{
+ const char *name) {
int i = getEncodingIndex(name);
if (i == UNKNOWN_ENC)
return 0;
}
static const ENCODING *
-NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end)
-{
-#define ENCODING_MAX 128
+NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end) {
+# define ENCODING_MAX 128
char buf[ENCODING_MAX];
char *p = buf;
int i;
}
int
-NS(XmlParseXmlDecl)(int isGeneralTextEntity,
- const ENCODING *enc,
- const char *ptr,
- const char *end,
- const char **badPtr,
- const char **versionPtr,
- const char **versionEndPtr,
- const char **encodingName,
- const ENCODING **encoding,
- int *standalone)
-{
- return doParseXmlDecl(NS(findEncoding),
- isGeneralTextEntity,
- enc,
- ptr,
- end,
- badPtr,
- versionPtr,
- versionEndPtr,
- encodingName,
- encoding,
- standalone);
+NS(XmlParseXmlDecl)(int isGeneralTextEntity, const ENCODING *enc,
+ const char *ptr, const char *end, const char **badPtr,
+ const char **versionPtr, const char **versionEndPtr,
+ const char **encodingName, const ENCODING **encoding,
+ int *standalone) {
+ return doParseXmlDecl(NS(findEncoding), isGeneralTextEntity, enc, ptr, end,
+ badPtr, versionPtr, versionEndPtr, encodingName,
+ encoding, standalone);
}
#endif /* XML_TOK_NS_C */
* be able to allocate memory on the stack, even on a stack overflow. If it
* fails, ignore the error. */
stack.ss_flags = 0;
- stack.ss_size = SIGSTKSZ;
+ /* bpo-21131: allocate dedicated stack of SIGSTKSZ*2 bytes, instead of just
+ SIGSTKSZ bytes. Calling the previous signal handler in faulthandler
+ signal handler uses more than SIGSTKSZ bytes of stack memory on some
+ platforms. */
+ stack.ss_size = SIGSTKSZ * 2;
stack.ss_sp = PyMem_Malloc(stack.ss_size);
if (stack.ss_sp != NULL) {
err = sigaltstack(&stack, &old_stack);
return DECODE_LOCALE_ERR("PREFIX define", len);
}
calculate->exec_prefix = Py_DecodeLocale(EXEC_PREFIX, &len);
- if (!calculate->prefix) {
+ if (!calculate->exec_prefix) {
return DECODE_LOCALE_ERR("EXEC_PREFIX define", len);
}
calculate->lib_python = Py_DecodeLocale("lib/python" VERSION, &len);
PyObject_HEAD
PyObject *it;
int numread; /* 0 <= numread <= LINKCELLS */
+ int running;
PyObject *nextlink;
PyObject *(values[LINKCELLS]);
} teedataobject;
if (tdo == NULL)
return NULL;
+ tdo->running = 0;
tdo->numread = 0;
tdo->nextlink = NULL;
Py_INCREF(it);
else {
/* this is the lead iterator, so fetch more data */
assert(i == tdo->numread);
+ if (tdo->running) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "cannot re-enter the tee iterator");
+ return NULL;
+ }
+ tdo->running = 1;
value = PyIter_Next(tdo->it);
+ tdo->running = 0;
if (value == NULL)
return NULL;
tdo->numread++;
setint(PyObject *d, const char *name, long value)
{
PyObject *o = PyLong_FromLong(value);
- if (o && PyDict_SetItemString(d, name, o) == 0) {
+ if (o) {
+ PyDict_SetItemString(d, name, o);
Py_DECREF(o);
}
}
return NULL;
n = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM,
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
code,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
}
CPU_SET_S(cpu, setsize, cpu_set);
}
+ if (PyErr_Occurred()) {
+ goto error;
+ }
Py_CLEAR(iterator);
if (sched_setaffinity(pid, setsize, cpu_set)) {
ms = _PyTime_AsMilliseconds(interval, _PyTime_ROUND_CEILING);
assert(ms <= INT_MAX);
+ /* On some OSes, typically BSD-based ones, the timeout parameter of the
+ poll() syscall, when negative, must be exactly INFTIM, where defined,
+ or -1. See issue 37811. */
+ if (ms < 0) {
+#ifdef INFTIM
+ ms = INFTIM;
+#else
+ ms = -1;
+#endif
+ }
+
Py_BEGIN_ALLOW_THREADS;
n = poll(&pollfd, 1, (int)ms);
Py_END_ALLOW_THREADS;
return -1;
}
- _PyTime_t total = utime + utime;
+ _PyTime_t total = utime + stime;
*tp = total;
return 0;
}
}
Py_DECREF(bytearray_obj);
+ if (PyErr_Occurred()) {
+ return NULL;
+ }
+
Py_RETURN_NONE;
}
* int32 for 2**16 <= dk_size <= 2**31
* int64 for 2**32 <= dk_size
-dk_entries is array of PyDictKeyEntry. It's size is USABLE_FRACTION(dk_size).
+dk_entries is array of PyDictKeyEntry. Its size is USABLE_FRACTION(dk_size).
DK_ENTRIES(dk) can be used to get pointer to entries.
NOTE: Since negative value is used for DKIX_EMPTY and DKIX_DUMMY, type of
PyDoc_STRVAR(floatinfo__doc__,
"sys.float_info\n\
\n\
-A structseq holding information about the float type. It contains low level\n\
+A named tuple holding information about the float type. It contains low level\n\
information about the precision and internal representation. Please study\n\
your system's :file:`float.h` for more information.");
{
PyObject *retval;
- if (o->agt_state == AWAITABLE_STATE_INIT) {
- PyErr_SetString(PyExc_RuntimeError, NON_INIT_CORO_MSG);
- return NULL;
- }
-
if (o->agt_state == AWAITABLE_STATE_CLOSED) {
PyErr_SetNone(PyExc_StopIteration);
return NULL;
return list_item(self, i);
}
else if (PySlice_Check(item)) {
- Py_ssize_t start, stop, step, slicelength, cur, i;
+ Py_ssize_t start, stop, step, slicelength, i;
+ size_t cur;
PyObject* result;
PyObject* it;
PyObject **src, **dest;
/* assign slice */
PyObject *ins, *seq;
PyObject **garbage, **seqitems, **selfitems;
- Py_ssize_t cur, i;
+ Py_ssize_t i;
+ size_t cur;
/* protect against a[::-1] = a */
if (self == (PyListObject*)value) {
PyDoc_STRVAR(int_info__doc__,
"sys.int_info\n\
\n\
-A struct sequence that holds information about Python's\n\
+A named tuple that holds information about Python's\n\
internal representation of integers. The attributes are read only.");
static PyStructSequence_Field int_info_fields[] = {
# define _Py_NO_ADDRESS_SAFETY_ANALYSIS \
__attribute__((no_address_safety_analysis))
# endif
- // TSAN is supported since GCC 4.8, but __SANITIZE_THREAD__ macro
+ // TSAN is supported since GCC 5.1, but __SANITIZE_THREAD__ macro
// is provided only since GCC 7.
-# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+# if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1)
# define _Py_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread))
# endif
#endif
block allocations typically result in a couple of instructions).
Unless the optimizer reorders everything, being too smart...
- Return 1 if pymalloc allocated memory and wrote the pointer into *ptr_p.
+ Return a pointer to newly allocated memory if pymalloc allocated memory.
- Return 0 if pymalloc failed to allocate the memory block: on bigger
+ Return NULL if pymalloc failed to allocate the memory block: on bigger
requests, on error in the code below (as a last chance to serve the request)
or when the max memory limit has been reached. */
-static int
-pymalloc_alloc(void *ctx, void **ptr_p, size_t nbytes)
+static void*
+pymalloc_alloc(void *ctx, size_t nbytes)
{
block *bp;
poolp pool;
running_on_valgrind = RUNNING_ON_VALGRIND;
}
if (UNLIKELY(running_on_valgrind)) {
- return 0;
+ return NULL;
}
#endif
if (nbytes == 0) {
- return 0;
+ return NULL;
}
if (nbytes > SMALL_REQUEST_THRESHOLD) {
- return 0;
+ return NULL;
}
LOCK();
success:
UNLOCK();
assert(bp != NULL);
- *ptr_p = (void *)bp;
- return 1;
+ return (void *)bp;
failed:
UNLOCK();
- return 0;
+ return NULL;
}
static void *
_PyObject_Malloc(void *ctx, size_t nbytes)
{
- void* ptr;
- if (pymalloc_alloc(ctx, &ptr, nbytes)) {
+ void* ptr = pymalloc_alloc(ctx, nbytes);
+ if (ptr != NULL) {
_Py_AllocatedBlocks++;
return ptr;
}
static void *
_PyObject_Calloc(void *ctx, size_t nelem, size_t elsize)
{
- void* ptr;
-
assert(elsize == 0 || nelem <= (size_t)PY_SSIZE_T_MAX / elsize);
size_t nbytes = nelem * elsize;
- if (pymalloc_alloc(ctx, &ptr, nbytes)) {
+ void *ptr = pymalloc_alloc(ctx, nbytes);
+ if (ptr != NULL) {
memset(ptr, 0, nbytes);
_Py_AllocatedBlocks++;
return ptr;
-/* Implementation helper: a struct that looks like a tuple. See timemodule
- and posixmodule for example uses. */
+/* Implementation helper: a struct that looks like a tuple.
+ See timemodule and posixmodule for example uses.
+
+ The structseq helper is considered an internal CPython implementation
+ detail. Docs for modules using structseqs should call them
+ "named tuples" (be sure to include a space between the two
+ words and add a link back to the term in Docs/glossary.rst).
+*/
#include "Python.h"
#include "structmember.h"
#define NEED_RETRY
#endif
+/* INT_MAX is the theoretical largest chunk (or INT_MAX / 2 when
+ transcoding from UTF-16), but INT_MAX / 4 perfoms better in
+ both cases also and avoids partial characters overrunning the
+ length limit in MultiByteToWideChar on Windows */
+#define DECODING_CHUNK_SIZE (INT_MAX/4)
+
#ifndef WC_ERR_INVALID_CHARS
# define WC_ERR_INVALID_CHARS 0x0080
#endif
do
{
#ifdef NEED_RETRY
- if (size > INT_MAX) {
- chunk_size = INT_MAX;
+ if (size > DECODING_CHUNK_SIZE) {
+ chunk_size = DECODING_CHUNK_SIZE;
final = 0;
done = 0;
}
do
{
#ifdef NEED_RETRY
- /* UTF-16 encoding may double the size, so use only INT_MAX/2
- chunks. */
- if (len > INT_MAX/2) {
- chunk_len = INT_MAX/2;
+ if (len > DECODING_CHUNK_SIZE) {
+ chunk_len = DECODING_CHUNK_SIZE;
done = 0;
}
else
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM,
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
" key\n"
" An already open key, or any one of the predefined HKEY_* constants.\n"
"\n"
-"Will generally raise NotImplemented if executed on a 32bit OS.\n"
+"Will generally raise NotImplementedError if executed on a 32bit OS.\n"
"\n"
"If the key is not on the reflection list, the function succeeds but has\n"
"no effect. Disabling reflection for a key does not affect reflection\n"
" key\n"
" An already open key, or any one of the predefined HKEY_* constants.\n"
"\n"
-"Will generally raise NotImplemented if executed on a 32bit OS.\n"
+"Will generally raise NotImplementedError if executed on a 32bit OS.\n"
"Restoring reflection for a key does not affect reflection of any\n"
"subkeys.");
" key\n"
" An already open key, or any one of the predefined HKEY_* constants.\n"
"\n"
-"Will generally raise NotImplemented if executed on a 32bit OS.");
+"Will generally raise NotImplementedError if executed on a 32bit OS.");
#define WINREG_QUERYREFLECTIONKEY_METHODDEF \
{"QueryReflectionKey", (PyCFunction)winreg_QueryReflectionKey, METH_O, winreg_QueryReflectionKey__doc__},
exit:
return return_value;
}
-/*[clinic end generated code: output=60c92ffc7438f8cf input=a9049054013a1b77]*/
+/*[clinic end generated code: output=696f627d310ac599 input=a9049054013a1b77]*/
-/* Generated file. Do not edit. */
-int winerror_to_errno(int winerror)
+int
+winerror_to_errno(int winerror)
{
- switch(winerror) {
- case 2: return 2;
- case 3: return 2;
- case 4: return 24;
- case 5: return 13;
- case 6: return 9;
- case 7: return 12;
- case 8: return 12;
- case 9: return 12;
- case 10: return 7;
- case 11: return 8;
- case 15: return 2;
- case 16: return 13;
- case 17: return 18;
- case 18: return 2;
- case 19: return 13;
- case 20: return 13;
- case 21: return 13;
- case 22: return 13;
- case 23: return 13;
- case 24: return 13;
- case 25: return 13;
- case 26: return 13;
- case 27: return 13;
- case 28: return 13;
- case 29: return 13;
- case 30: return 13;
- case 31: return 13;
- case 32: return 13;
- case 33: return 13;
- case 34: return 13;
- case 35: return 13;
- case 36: return 13;
- case 53: return 2;
- case 65: return 13;
- case 67: return 2;
- case 80: return 17;
- case 82: return 13;
- case 83: return 13;
- case 89: return 11;
- case 108: return 13;
- case 109: return 32;
- case 112: return 28;
- case 114: return 9;
- case 128: return 10;
- case 129: return 10;
- case 130: return 9;
- case 132: return 13;
- case 145: return 41;
- case 158: return 13;
- case 161: return 2;
- case 164: return 11;
- case 167: return 13;
- case 183: return 17;
- case 188: return 8;
- case 189: return 8;
- case 190: return 8;
- case 191: return 8;
- case 192: return 8;
- case 193: return 8;
- case 194: return 8;
- case 195: return 8;
- case 196: return 8;
- case 197: return 8;
- case 198: return 8;
- case 199: return 8;
- case 200: return 8;
- case 201: return 8;
- case 202: return 8;
- case 206: return 2;
- case 215: return 11;
- case 232: return 32;
- case 267: return 20;
- case 1816: return 12;
- default: return EINVAL;
+ // Unwrap FACILITY_WIN32 HRESULT errors.
+ if ((winerror & 0xFFFF0000) == 0x80070000) {
+ winerror &= 0x0000FFFF;
+ }
+
+ // Winsock error codes (10000-11999) are errno values.
+ if (winerror >= 10000 && winerror < 12000) {
+ switch (winerror) {
+ case WSAEINTR:
+ case WSAEBADF:
+ case WSAEACCES:
+ case WSAEFAULT:
+ case WSAEINVAL:
+ case WSAEMFILE:
+ // Winsock definitions of errno values. See WinSock2.h
+ return winerror - 10000;
+ default:
+ return winerror;
+ }
+ }
+
+ switch (winerror) {
+ case ERROR_FILE_NOT_FOUND: // 2
+ case ERROR_PATH_NOT_FOUND: // 3
+ case ERROR_INVALID_DRIVE: // 15
+ case ERROR_NO_MORE_FILES: // 18
+ case ERROR_BAD_NETPATH: // 53
+ case ERROR_BAD_NET_NAME: // 67
+ case ERROR_BAD_PATHNAME: // 161
+ case ERROR_FILENAME_EXCED_RANGE: // 206
+ return ENOENT;
+
+ case ERROR_BAD_ENVIRONMENT: // 10
+ return E2BIG;
+
+ case ERROR_BAD_FORMAT: // 11
+ case ERROR_INVALID_STARTING_CODESEG: // 188
+ case ERROR_INVALID_STACKSEG: // 189
+ case ERROR_INVALID_MODULETYPE: // 190
+ case ERROR_INVALID_EXE_SIGNATURE: // 191
+ case ERROR_EXE_MARKED_INVALID: // 192
+ case ERROR_BAD_EXE_FORMAT: // 193
+ case ERROR_ITERATED_DATA_EXCEEDS_64k: // 194
+ case ERROR_INVALID_MINALLOCSIZE: // 195
+ case ERROR_DYNLINK_FROM_INVALID_RING: // 196
+ case ERROR_IOPL_NOT_ENABLED: // 197
+ case ERROR_INVALID_SEGDPL: // 198
+ case ERROR_AUTODATASEG_EXCEEDS_64k: // 199
+ case ERROR_RING2SEG_MUST_BE_MOVABLE: // 200
+ case ERROR_RELOC_CHAIN_XEEDS_SEGLIM: // 201
+ case ERROR_INFLOOP_IN_RELOC_CHAIN: // 202
+ return ENOEXEC;
+
+ case ERROR_INVALID_HANDLE: // 6
+ case ERROR_INVALID_TARGET_HANDLE: // 114
+ case ERROR_DIRECT_ACCESS_HANDLE: // 130
+ return EBADF;
+
+ case ERROR_WAIT_NO_CHILDREN: // 128
+ case ERROR_CHILD_NOT_COMPLETE: // 129
+ return ECHILD;
+
+ case ERROR_NO_PROC_SLOTS: // 89
+ case ERROR_MAX_THRDS_REACHED: // 164
+ case ERROR_NESTING_NOT_ALLOWED: // 215
+ return EAGAIN;
+
+ case ERROR_ARENA_TRASHED: // 7
+ case ERROR_NOT_ENOUGH_MEMORY: // 8
+ case ERROR_INVALID_BLOCK: // 9
+ case ERROR_NOT_ENOUGH_QUOTA: // 1816
+ return ENOMEM;
+
+ case ERROR_ACCESS_DENIED: // 5
+ case ERROR_CURRENT_DIRECTORY: // 16
+ case ERROR_WRITE_PROTECT: // 19
+ case ERROR_BAD_UNIT: // 20
+ case ERROR_NOT_READY: // 21
+ case ERROR_BAD_COMMAND: // 22
+ case ERROR_CRC: // 23
+ case ERROR_BAD_LENGTH: // 24
+ case ERROR_SEEK: // 25
+ case ERROR_NOT_DOS_DISK: // 26
+ case ERROR_SECTOR_NOT_FOUND: // 27
+ case ERROR_OUT_OF_PAPER: // 28
+ case ERROR_WRITE_FAULT: // 29
+ case ERROR_READ_FAULT: // 30
+ case ERROR_GEN_FAILURE: // 31
+ case ERROR_SHARING_VIOLATION: // 32
+ case ERROR_LOCK_VIOLATION: // 33
+ case ERROR_WRONG_DISK: // 34
+ case ERROR_SHARING_BUFFER_EXCEEDED: // 36
+ case ERROR_NETWORK_ACCESS_DENIED: // 65
+ case ERROR_CANNOT_MAKE: // 82
+ case ERROR_FAIL_I24: // 83
+ case ERROR_DRIVE_LOCKED: // 108
+ case ERROR_SEEK_ON_DEVICE: // 132
+ case ERROR_NOT_LOCKED: // 158
+ case ERROR_LOCK_FAILED: // 167
+ case 35: // 35 (undefined)
+ return EACCES;
+
+ case ERROR_FILE_EXISTS: // 80
+ case ERROR_ALREADY_EXISTS: // 183
+ return EEXIST;
+
+ case ERROR_NOT_SAME_DEVICE: // 17
+ return EXDEV;
+
+ case ERROR_DIRECTORY: // 267 (bpo-12802)
+ return ENOTDIR;
+
+ case ERROR_TOO_MANY_OPEN_FILES: // 4
+ return EMFILE;
+
+ case ERROR_DISK_FULL: // 112
+ return ENOSPC;
+
+ case ERROR_BROKEN_PIPE: // 109
+ case ERROR_NO_DATA: // 232 (bpo-13063)
+ return EPIPE;
+
+ case ERROR_DIR_NOT_EMPTY: // 145
+ return ENOTEMPTY;
+
+ case ERROR_NO_UNICODE_TRANSLATION: // 1113
+ return EILSEQ;
+
+ case ERROR_INVALID_FUNCTION: // 1
+ case ERROR_INVALID_ACCESS: // 12
+ case ERROR_INVALID_DATA: // 13
+ case ERROR_INVALID_PARAMETER: // 87
+ case ERROR_NEGATIVE_SEEK: // 131
+ default:
+ return EINVAL;
}
}
+++ /dev/null
-#include <windows.h>
-#include <fcntl.h>
-#include <io.h>
-#include <stdio.h>
-#include <errno.h>
-
-/* Extract the mapping of Win32 error codes to errno */
-
-int main()
-{
- int i;
- _setmode(fileno(stdout), O_BINARY);
- printf("/* Generated file. Do not edit. */\n");
- printf("int winerror_to_errno(int winerror)\n");
- printf("{\n switch(winerror) {\n");
- for(i=1; i < 65000; i++) {
- _dosmaperr(i);
- if (errno == EINVAL) {
- /* Issue #12802 */
- if (i == ERROR_DIRECTORY)
- errno = ENOTDIR;
- /* Issue #13063 */
- else if (i == ERROR_NO_DATA)
- errno = EPIPE;
- else
- continue;
- }
- printf(" case %d: return %d;\n", i, errno);
- }
- printf(" default: return EINVAL;\n");
- printf(" }\n}\n");
-}
# define SIZEOF_FPOS_T 8
# define SIZEOF_HKEY 8
# define SIZEOF_SIZE_T 8
-/* configure.ac defines HAVE_LARGEFILE_SUPPORT iff HAVE_LONG_LONG,
+/* configure.ac defines HAVE_LARGEFILE_SUPPORT iff
sizeof(off_t) > sizeof(long), and sizeof(PY_LONG_LONG) >= sizeof(off_t).
On Win64 the second condition is not true, but if fpos_t replaces off_t
then this is true. The uses of HAVE_LARGEFILE_SUPPORT imply that Win64
int i;
wchar_t *Q;
- Q = data + len;
- for (P = data, i = 0; P < Q && *P != '\0'; P++, i++) {
+ if (len > 0 && data[len - 1] == '\0') {
+ Q = data + len - 1;
+ }
+ else {
+ Q = data + len;
+ }
+
+ for (P = data, i = 0; P < Q; P++, i++) {
str[i] = P;
- for (; P < Q && *P != '\0'; P++)
+ for (; P < Q && *P != '\0'; P++) {
;
+ }
}
}
countStrings(wchar_t *data, int len)
{
int strings;
- wchar_t *P;
- wchar_t *Q = data + len;
+ wchar_t *P, *Q;
+
+ if (len > 0 && data[len - 1] == '\0') {
+ Q = data + len - 1;
+ }
+ else {
+ Q = data + len;
+ }
- for (P = data, strings = 0; P < Q && *P != '\0'; P++, strings++)
- for (; P < Q && *P != '\0'; P++)
+ for (P = data, strings = 0; P < Q; P++, strings++) {
+ for (; P < Q && *P != '\0'; P++) {
;
+ }
+ }
return strings;
}
}
for (index = 0; index < s; index++)
{
- size_t len = wcslen(str[index]);
- if (len > INT_MAX) {
- PyErr_SetString(PyExc_OverflowError,
- "registry string is too long for a Python string");
- Py_DECREF(obData);
- PyMem_Free(str);
- return NULL;
- }
- PyObject *uni = PyUnicode_FromWideChar(str[index], len);
+ size_t slen = wcsnlen(str[index], len);
+ PyObject *uni = PyUnicode_FromWideChar(str[index], slen);
if (uni == NULL) {
Py_DECREF(obData);
PyMem_Free(str);
return NULL;
}
PyList_SET_ITEM(obData, index, uni);
+ len -= Py_SAFE_DOWNCAST(slen + 1, size_t, int);
}
PyMem_Free(str);
Disables registry reflection for 32bit processes running on a 64bit OS.
-Will generally raise NotImplemented if executed on a 32bit OS.
+Will generally raise NotImplementedError if executed on a 32bit OS.
If the key is not on the reflection list, the function succeeds but has
no effect. Disabling reflection for a key does not affect reflection
static PyObject *
winreg_DisableReflectionKey_impl(PyObject *module, HKEY key)
-/*[clinic end generated code: output=830cce504cc764b4 input=a6c9e5ca5410193c]*/
+/*[clinic end generated code: output=830cce504cc764b4 input=70bece2dee02e073]*/
{
HMODULE hMod;
typedef LONG (WINAPI *RDRKFunc)(HKEY);
Restores registry reflection for the specified disabled key.
-Will generally raise NotImplemented if executed on a 32bit OS.
+Will generally raise NotImplementedError if executed on a 32bit OS.
Restoring reflection for a key does not affect reflection of any
subkeys.
[clinic start generated code]*/
static PyObject *
winreg_EnableReflectionKey_impl(PyObject *module, HKEY key)
-/*[clinic end generated code: output=86fa1385fdd9ce57 input=7748abbacd1e166a]*/
+/*[clinic end generated code: output=86fa1385fdd9ce57 input=eeae770c6eb9f559]*/
{
HMODULE hMod;
typedef LONG (WINAPI *RERKFunc)(HKEY);
Returns the reflection state for the specified key as a bool.
-Will generally raise NotImplemented if executed on a 32bit OS.
+Will generally raise NotImplementedError if executed on a 32bit OS.
[clinic start generated code]*/
static PyObject *
winreg_QueryReflectionKey_impl(PyObject *module, HKEY key)
-/*[clinic end generated code: output=4e774af288c3ebb9 input=9f325eacb5a65d88]*/
+/*[clinic end generated code: output=4e774af288c3ebb9 input=a98fa51d55ade186]*/
{
HMODULE hMod;
typedef LONG (WINAPI *RQRKFunc)(HKEY, BOOL *);
</ItemGroup>\r
<ItemGroup>\r
<ClCompile Include="..\Modules\_elementtree.c" />\r
- <ClCompile Include="..\Modules\expat\loadlibrary.c" />\r
<ClCompile Include="..\Modules\expat\xmlparse.c" />\r
<ClCompile Include="..\Modules\expat\xmlrole.c" />\r
<ClCompile Include="..\Modules\expat\xmltok.c" />\r
<ClInclude Include="..\Modules\expat\latin1tab.h">\r
<Filter>Header Files</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\Modules\expat\loadlibrary.c">\r
- <Filter>Header Files</Filter>\r
- </ClInclude>\r
<ClInclude Include="..\Modules\expat\macconfig.h">\r
<Filter>Header Files</Filter>\r
</ClInclude>\r
\r
set libraries=\r
set libraries=%libraries% bzip2-1.0.6\r
-if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1c\r
+if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1d\r
set libraries=%libraries% sqlite-3.28.0.0\r
if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.9.0\r
if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.9.0\r
echo.Fetching external binaries...\r
\r
set binaries=\r
-if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.1c\r
+if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.1d\r
if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.9.0\r
if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06\r
\r
</ItemGroup>\r
<ItemGroup>\r
<ClCompile Include="..\Modules\pyexpat.c" />\r
- <ClCompile Include="..\Modules\expat\loadlibrary.c" />\r
<ClCompile Include="..\Modules\expat\xmlparse.c" />\r
<ClCompile Include="..\Modules\expat\xmlrole.c" />\r
<ClCompile Include="..\Modules\expat\xmltok.c" />\r
<ClCompile Include="..\Modules\pyexpat.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\Modules\expat\loadlibrary.c">\r
- <Filter>Source Files</Filter>\r
- </ClCompile>\r
<ClCompile Include="..\Modules\expat\xmlparse.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
<sqlite3Dir>$(ExternalsDir)sqlite-3.28.0.0\</sqlite3Dir>\r
<bz2Dir>$(ExternalsDir)bzip2-1.0.6\</bz2Dir>\r
<lzmaDir>$(ExternalsDir)xz-5.2.2\</lzmaDir>\r
- <opensslDir>$(ExternalsDir)openssl-1.1.1c\</opensslDir>\r
- <opensslOutDir>$(ExternalsDir)openssl-bin-1.1.1c\$(ArchName)\</opensslOutDir>\r
+ <opensslDir>$(ExternalsDir)openssl-1.1.1d\</opensslDir>\r
+ <opensslOutDir>$(ExternalsDir)openssl-bin-1.1.1d\$(ArchName)\</opensslOutDir>\r
<opensslIncludeDir>$(opensslOutDir)include</opensslIncludeDir>\r
<nasmDir>$(ExternalsDir)\nasm-2.11.06\</nasmDir>\r
<zlibDir>$(ExternalsDir)\zlib-1.2.11\</zlibDir>\r
<SubSystem>Console</SubSystem>\r
</Link>\r
</ItemDefinitionGroup>\r
+ <ItemDefinitionGroup Condition="$(Configuration) != 'Debug'">\r
+ <ClCompile>\r
+ <RuntimeLibrary>Multithreaded</RuntimeLibrary>\r
+ </ClCompile>\r
+ <Link>\r
+ <AdditionalDependencies>ucrt.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+ <IgnoreSpecificDefaultLibraries>libucrt;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\r
+ </Link>\r
+ </ItemDefinitionGroup>\r
<ItemGroup>\r
<None Include="..\PC\pycon.ico" />\r
</ItemGroup>\r
if (tok->encoding) {
encoding = (char *)PyMem_MALLOC(strlen(tok->encoding) + 1);
if (encoding)
- strcpy(encoding, tok->encoding);
+ strcpy(encoding, tok->encoding);
}
PyTokenizer_Free(tok);
return encoding;
}
PyDoc_STRVAR(warn_explicit_doc,
-"Low-level inferface to warnings functionality.");
+"Low-level interface to warnings functionality.");
static PyMethodDef warnings_functions[] = {
WARNINGS_WARN_METHODDEF
};
PyDoc_STRVAR(zip_doc,
-"zip(iter1 [,iter2 [...]]) --> zip object\n\
+"zip(*iterables) --> zip object\n\
\n\
Return a zip object whose .__next__() method returns a tuple where\n\
the i-th element comes from the i-th iterable argument. The .__next__()\n\
/* Set current line number to the line number of first statement.
This way line number for SETUP_ANNOTATIONS will always
coincide with the line number of first "real" statement in module.
- If body is empy, then lineno will be set later in assemble. */
+ If body is empty, then lineno will be set later in assemble. */
if (c->u->u_scope_type == COMPILER_SCOPE_MODULE &&
!c->u->u_lineno && asdl_seq_LEN(stmts)) {
st = (stmt_ty)asdl_seq_GET(stmts, 0);
* just means an extra spurious wakeup for a waiting thread.
* ('waiting' corresponds to the semaphore's "negative" count and
* we may end up with e.g. (waiting == -1 && sem.count == 1). When
- * a new thread comes along, it will pass right throuhgh, having
+ * a new thread comes along, it will pass right through, having
* adjusted it to (waiting == 0 && sem.count == 0).
*/
flags = HANDLE_FLAG_INHERIT;
else
flags = 0;
- if (!SetHandleInformation(handle, HANDLE_FLAG_INHERIT, flags)) {
+
+ /* This check can be removed once support for Windows 7 ends. */
+#define CONSOLE_PSEUDOHANDLE(handle) (((ULONG_PTR)(handle) & 0x3) == 0x3 && \
+ GetFileType(handle) == FILE_TYPE_CHAR)
+
+ if (!CONSOLE_PSEUDOHANDLE(handle) &&
+ !SetHandleInformation(handle, HANDLE_FLAG_INHERIT, flags)) {
if (raise)
PyErr_SetFromWindowsErr(0);
return -1;
}
+#undef CONSOLE_PSEUDOHANDLE
return 0;
#else
if (dot == -2) {
goto error;
}
-
- if (dot >= 0) {
- PyObject *substr = PyUnicode_Substring(package, 0, dot);
- if (substr == NULL) {
- goto error;
- }
- Py_SETREF(package, substr);
+ else if (dot == -1) {
+ goto no_parent_error;
}
+ PyObject *substr = PyUnicode_Substring(package, 0, dot);
+ if (substr == NULL) {
+ goto error;
+ }
+ Py_SETREF(package, substr);
}
}
last_dot = PyUnicode_GET_LENGTH(package);
if (last_dot == 0) {
- PyErr_SetString(PyExc_ImportError,
- "attempted relative import with no known parent package");
- goto error;
+ goto no_parent_error;
}
for (level_up = 1; level_up < level; level_up += 1) {
Py_DECREF(base);
return abs_name;
+ no_parent_error:
+ PyErr_SetString(PyExc_ImportError,
+ "attempted relative import "
+ "with no known parent package");
+
error:
Py_XDECREF(package);
return NULL;
if (!state->modules_by_index)
return -1;
}
- while(PyList_GET_SIZE(state->modules_by_index) <= def->m_base.m_index)
+ 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 -1;
}
index = def->m_base.m_index;
- if (state->modules_by_index) {
- if(PyList_GET_SIZE(state->modules_by_index) >= index) {
- if(module == PyList_GET_ITEM(state->modules_by_index, index)) {
- Py_FatalError("PyState_AddModule: Module already added!");
- return -1;
- }
- }
+ if (state->modules_by_index &&
+ index < PyList_GET_SIZE(state->modules_by_index) &&
+ module == PyList_GET_ITEM(state->modules_by_index, index)) {
+ Py_FatalError("PyState_AddModule: Module already added!");
+ return -1;
}
return _PyState_AddModule(module, def);
}
Py_DECREF(value);
value = message;
- line = PyUnicode_FromFormat(" File \"%U\", line %d\n",
+ line = PyUnicode_FromFormat(" File \"%S\", line %d\n",
filename, lineno);
Py_DECREF(filename);
if (line != NULL) {
PyDoc_STRVAR(asyncgen_hooks_doc,
"asyncgen_hooks\n\
\n\
-A struct sequence providing information about asynhronous\n\
+A named tuple providing information about asynchronous\n\
generators hooks. The attributes are read only.");
static PyStructSequence_Field asyncgen_hooks_fields[] = {
PyDoc_STRVAR(hash_info_doc,
"hash_info\n\
\n\
-A struct sequence providing parameters used for computing\n\
+A named tuple providing parameters used for computing\n\
hashes. The attributes are read only.");
static PyStructSequence_Field hash_info_fields[] = {
copyright -- copyright notice pertaining to this interpreter\n\
exec_prefix -- prefix used to find the machine-specific Python library\n\
executable -- absolute path of the executable binary of the Python interpreter\n\
-float_info -- a struct sequence with information about the float implementation.\n\
+float_info -- a named tuple with information about the float implementation.\n\
float_repr_style -- string indicating the style of repr() output for floats\n\
-hash_info -- a struct sequence with information about the hash algorithm.\n\
+hash_info -- a named tuple with information about the hash algorithm.\n\
hexversion -- version information encoded as a single integer\n\
implementation -- Python implementation information.\n\
-int_info -- a struct sequence with information about the int implementation.\n\
+int_info -- a named tuple with information about the int implementation.\n\
maxsize -- the largest supported length of containers.\n\
maxunicode -- the value of the largest Unicode code point\n\
platform -- platform identifier\n\
prefix -- prefix used to find the Python library\n\
-thread_info -- a struct sequence with information about the thread implementation.\n\
+thread_info -- a named tuple with information about the thread implementation.\n\
version -- the version of this interpreter as a string\n\
version_info -- version information as a named tuple\n\
"
PyDoc_STRVAR(threadinfo__doc__,
"sys.thread_info\n\
\n\
-A struct sequence holding information about the thread implementation.");
+A named tuple holding information about the thread implementation.");
static PyStructSequence_Field threadinfo_fields[] = {
{"name", "name of the thread implementation"},
-This is Python version 3.7.4
+This is Python version 3.7.5
============================
-.. image:: https://travis-ci.org/python/cpython.svg?branch=master
+.. image:: https://travis-ci.org/python/cpython.svg?branch=3.7
:alt: CPython build status on Travis CI
- :target: https://travis-ci.org/python/cpython
-
-.. image:: https://ci.appveyor.com/api/projects/status/4mew1a93xdkbf5ua/branch/master?svg=true
- :alt: CPython build status on Appveyor
- :target: https://ci.appveyor.com/project/python/cpython/branch/master
+ :target: https://travis-ci.org/python/cpython/branches
.. image:: https://dev.azure.com/python/cpython/_apis/build/status/Azure%20Pipelines%20CI?branchName=3.7
:alt: CPython build status on Azure Pipelines
:target: https://dev.azure.com/python/cpython/_build/latest?definitionId=4&branchName=3.7
-.. image:: https://codecov.io/gh/python/cpython/branch/master/graph/badge.svg
+.. image:: https://codecov.io/gh/python/cpython/branch/3.7/graph/badge.svg
:alt: CPython code coverage on Codecov
- :target: https://codecov.io/gh/python/cpython
+ :target: https://codecov.io/gh/python/cpython/branch/3.7
Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 Python Software Foundation. All
This will install Python as ``python3``.
You can pass many options to the configure script; run ``./configure --help``
-to find out more. On macOS and Cygwin, the executable is called ``python.exe``;
-elsewhere it's just ``python``.
+to find out more. On macOS case-insensitive file systems and on Cygwin,
+the executable is called ``python.exe``; elsewhere it's just ``python``.
-If you are running on macOS with the latest updates installed, make sure to install
-openSSL or some other SSL software along with Homebrew or another package manager.
-If issues persist, see https://devguide.python.org/setup/#macos-and-os-x for more
-information.
+Building a complete Python installation requires the use of various
+additional third-party libraries, depending on your build platform and
+configure options. Not all standard library modules are buildable or
+useable on all platforms. Refer to the
+`Install dependencies <https://devguide.python.org/setup/#install-dependencies>`_
+section of the `Developer Guide`_ for current detailed information on
+dependencies for various Linux distributions and macOS.
-On macOS, if you have configured Python with ``--enable-framework``, you
-should use ``make frameworkinstall`` to do the installation. Note that this
-installs the Python executable in a place that is not normally on your PATH,
-you may want to set up a symlink in ``/usr/local/bin``.
+On macOS, there are additional configure and build options related
+to macOS framework and universal builds. Refer to `Mac/README.rst
+<https://github.com/python/cpython/blob/3.7/Mac/README.rst>`_.
On Windows, see `PCbuild/readme.txt
-<https://github.com/python/cpython/blob/master/PCbuild/readme.txt>`_.
+<https://github.com/python/cpython/blob/3.7/PCbuild/readme.txt>`_.
If you wish, you can create a subdirectory and invoke configure from there.
For example::
We have a comprehensive overview of the changes in the `What's New in Python
3.7 <https://docs.python.org/3.7/whatsnew/3.7.html>`_ document. For a more
detailed change log, read `Misc/NEWS
-<https://github.com/python/cpython/blob/master/Misc/NEWS.d>`_, but a full
+<https://github.com/python/cpython/blob/3.7/Misc/NEWS.d>`_, but a full
accounting of changes can only be gleaned from the `commit history
-<https://github.com/python/cpython/commits/master>`_.
+<https://github.com/python/cpython/commits/3.7>`_.
If you want to install multiple versions of Python see the section below
entitled "Installing multiple versions".
formatting requirements.
For information about building Python's documentation, refer to `Doc/README.rst
-<https://github.com/python/cpython/blob/master/Doc/README.rst>`_.
+<https://github.com/python/cpython/blob/3.7/Doc/README.rst>`_.
Converting From Python 2.x to 3.x
BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Failed to load AssociateFiles state: error code 0x%08X", hr);
}
- _engine->SetVariableNumeric(L"Include_launcher", 1);
+ LONGLONG includeLauncher;
+ if (FAILED(BalGetNumericVariable(L"Include_launcher", &includeLauncher))
+ || includeLauncher == -1) {
+ _engine->SetVariableNumeric(L"Include_launcher", 1);
+ _engine->SetVariableNumeric(L"InstallLauncherAllUsers", fPerMachine ? 1 : 0);
+ }
_engine->SetVariableNumeric(L"DetectedOldLauncher", 1);
- _engine->SetVariableNumeric(L"InstallLauncherAllUsers", fPerMachine ? 1 : 0);
}
return CheckCanceled() ? IDCANCEL : IDNOACTION;
}
}
}
+ LONGLONG includeLauncher;
+ if (SUCCEEDED(BalGetNumericVariable(L"Include_launcher", &includeLauncher))
+ && includeLauncher != -1) {
+ detectedLauncher = FALSE;
+ }
+
if (detectedLauncher) {
/* When we detect the current version of the launcher. */
_engine->SetVariableNumeric(L"Include_launcher", 1);
_baFunction->OnDetectComplete();
}
+ if (SUCCEEDED(hrStatus)) {
+ LONGLONG includeLauncher;
+ if (SUCCEEDED(BalGetNumericVariable(L"Include_launcher", &includeLauncher))
+ && includeLauncher == -1) {
+ _engine->SetVariableNumeric(L"Include_launcher", 1);
+ }
+ }
+
if (SUCCEEDED(hrStatus)) {
hrStatus = EvaluateConditions();
}
hr = ParseOverridableVariablesFromXml(pixdManifest);
BalExitOnFailure(hr, "Failed to read overridable variables.");
+ if (_command.action == BOOTSTRAPPER_ACTION_MODIFY) {
+ LoadOptionalFeatureStates(_engine);
+ }
+
hr = ParseVariablesFromUnattendXml();
ExitOnFailure(hr, "Failed to read unattend.ini file.");
hr = UpdateUIStrings(_command.action);
BalExitOnFailure(hr, "Failed to load UI strings.");
- if (_command.action == BOOTSTRAPPER_ACTION_MODIFY) {
- LoadOptionalFeatureStates(_engine);
- }
-
GetBundleFileVersion();
// don't fail if we couldn't get the version info; best-effort only
LExit:
<Variable Name="Include_tools" Value="1" bal:Overridable="yes" />
<Variable Name="Include_tcltk" Value="1" bal:Overridable="yes" />
<Variable Name="Include_pip" Value="1" bal:Overridable="yes" />
+ <Variable Name="Include_launcher" Value="-1" bal:Overridable="yes" />
<?if "$(var.PyTestExt)"="" ?>
- <Variable Name="Include_launcher" Value="1" bal:Overridable="yes" />
<Variable Name="Include_launcherState" Value="enabled" bal:Overridable="yes" />
<?else ?>
- <Variable Name="Include_launcher" Value="0" />
<Variable Name="Include_launcherState" Value="disable" />
<?endif ?>
<Variable Name="Include_symbols" Value="0" bal:Overridable="yes" />
]
OPENSSL_RECENT_VERSIONS = [
- "1.0.2s",
- "1.1.0k",
- "1.1.1c",
+ "1.0.2t",
+ "1.1.0l",
+ "1.1.1d",
]
LIBRESSL_OLD_VERSIONS = [
]
LIBRESSL_RECENT_VERSIONS = [
- "2.7.4",
+ "2.9.2",
]
# store files in ../multissl
PGO_PROF_USE_FLAG
PGO_PROF_GEN_FLAG
LLVM_AR_FOUND
-target_os
-target_vendor
-target_cpu
-target
LLVM_AR
DEF_MAKE_RULE
DEF_MAKE_ALL_RULE
System types:
--build=BUILD configure for building on BUILD [guessed]
--host=HOST cross-compile to build programs to run on HOST [BUILD]
- --target=TARGET configure for building compilers for TARGET [HOST]
_ACEOF
fi
case $CC in
*clang*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
-$as_echo_n "checking target system type... " >&6; }
-if ${ac_cv_target+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test "x$target_alias" = x; then
- ac_cv_target=$ac_cv_host
-else
- ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
-$as_echo "$ac_cv_target" >&6; }
-case $ac_cv_target in
-*-*-*) ;;
-*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;;
-esac
-target=$ac_cv_target
-ac_save_IFS=$IFS; IFS='-'
-set x $ac_cv_target
-shift
-target_cpu=$1
-target_vendor=$2
-shift; shift
-# Remember, the first character of IFS is used to create $*,
-# except with old shells:
-target_os=$*
-IFS=$ac_save_IFS
-case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
-
-
-# The aliases save the names the user supplied, while $host etc.
-# will get canonicalized.
-test -n "$target_alias" &&
- test "$program_prefix$program_suffix$program_transform_name" = \
- NONENONEs,x,x, &&
- program_prefix=${target_alias}-
-# Extract the first word of "$target_alias-llvm-ar", so it can be a program name with args.
-set dummy $target_alias-llvm-ar; ac_word=$2
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}llvm-ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}llvm-ar; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_LLVM_AR+:} false; then :
fi
+fi
if test -z "$ac_cv_path_LLVM_AR"; then
- if test "$build" = "$target"; then
- ac_pt_LLVM_AR=$LLVM_AR
- # Extract the first word of "llvm-ar", so it can be a program name with args.
+ ac_pt_LLVM_AR=$LLVM_AR
+ # Extract the first word of "llvm-ar", so it can be a program name with args.
set dummy llvm-ar; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
done
IFS=$as_save_IFS
- test -z "$ac_cv_path_ac_pt_LLVM_AR" && ac_cv_path_ac_pt_LLVM_AR="''"
;;
esac
fi
$as_echo "no" >&6; }
fi
- LLVM_AR=$ac_pt_LLVM_AR
- else
+ if test "x$ac_pt_LLVM_AR" = x; then
LLVM_AR="''"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ LLVM_AR=$ac_pt_LLVM_AR
fi
else
LLVM_AR="$ac_cv_path_LLVM_AR"
-# Extract the first word of "$target_alias-llvm-profdata", so it can be a program name with args.
-set dummy $target_alias-llvm-profdata; ac_word=$2
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}llvm-profdata", so it can be a program name with args.
+set dummy ${ac_tool_prefix}llvm-profdata; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_LLVM_PROFDATA+:} false; then :
fi
+fi
if test -z "$ac_cv_path_LLVM_PROFDATA"; then
- if test "$build" = "$target"; then
- ac_pt_LLVM_PROFDATA=$LLVM_PROFDATA
- # Extract the first word of "llvm-profdata", so it can be a program name with args.
+ ac_pt_LLVM_PROFDATA=$LLVM_PROFDATA
+ # Extract the first word of "llvm-profdata", so it can be a program name with args.
set dummy llvm-profdata; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
done
IFS=$as_save_IFS
- test -z "$ac_cv_path_ac_pt_LLVM_PROFDATA" && ac_cv_path_ac_pt_LLVM_PROFDATA="''"
;;
esac
fi
$as_echo "no" >&6; }
fi
- LLVM_PROFDATA=$ac_pt_LLVM_PROFDATA
- else
+ if test "x$ac_pt_LLVM_PROFDATA" = x; then
LLVM_PROFDATA="''"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ LLVM_PROFDATA=$ac_pt_LLVM_PROFDATA
fi
else
LLVM_PROFDATA="$ac_cv_path_LLVM_PROFDATA"
$as_echo "#define _REENTRANT 1" >>confdefs.h
posix_threads=yes
+ if test "$ac_sys_system" = "SunOS"; then
+ CFLAGS="$CFLAGS -D_REENTRANT"
+ fi
elif test "$ac_cv_kpthread" = "yes"
then
CC="$CC -Kpthread"
case $CC in
*clang*)
AC_SUBST(LLVM_AR)
- AC_PATH_TARGET_TOOL(LLVM_AR, llvm-ar, '', ${llvm_path})
+ AC_PATH_TOOL(LLVM_AR, llvm-ar, '', ${llvm_path})
AC_SUBST(LLVM_AR_FOUND)
if test -n "${LLVM_AR}" -a -x "${LLVM_AR}"
then
AC_SUBST(LLVM_PROF_FILE)
AC_SUBST(LLVM_PROF_ERR)
AC_SUBST(LLVM_PROFDATA)
-AC_PATH_TARGET_TOOL(LLVM_PROFDATA, llvm-profdata, '', ${llvm_path})
+AC_PATH_TOOL(LLVM_PROFDATA, llvm-profdata, '', ${llvm_path})
AC_SUBST(LLVM_PROF_FOUND)
if test -n "${LLVM_PROFDATA}" -a -x "${LLVM_PROFDATA}"
then
"$ac_cv_sizeof_long_long" -ge "$ac_cv_sizeof_off_t"; then
AC_DEFINE(HAVE_LARGEFILE_SUPPORT, 1,
[Defined to enable large file support when an off_t is bigger than a long
- and long long is available and at least as big as an off_t. You may need
+ and long long is at least as big as an off_t. You may need
to add some flags for configuration and compilation to enable this mode.
(For Solaris and Linux, the necessary defines are already defined.)])
AC_MSG_RESULT(yes)
# Defining _REENTRANT on system with POSIX threads should not hurt.
AC_DEFINE(_REENTRANT)
posix_threads=yes
+ if test "$ac_sys_system" = "SunOS"; then
+ CFLAGS="$CFLAGS -D_REENTRANT"
+ fi
elif test "$ac_cv_kpthread" = "yes"
then
CC="$CC -Kpthread"
#undef HAVE_LANGINFO_H
/* Defined to enable large file support when an off_t is bigger than a long
- and long long is available and at least as big as an off_t. You may need to
- add some flags for configuration and compilation to enable this mode. (For
- Solaris and Linux, the necessary defines are already defined.) */
+ and long long is at least as big as an off_t. You may need to add some
+ flags for configuration and compilation to enable this mode. (For Solaris
+ and Linux, the necessary defines are already defined.) */
#undef HAVE_LARGEFILE_SUPPORT
/* Define to 1 if you have the 'lchflags' function. */