Showing preview only (915K chars total). Download the full file or copy to clipboard to get everything.
Repository: ned14/pcpp
Branch: master
Commit: 988cc2f5eab4
Files: 210
Total size: 861.8 KB
Directory structure:
gitextract_sih0q66g/
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ └── workflows/
│ └── ci.yml
├── .gitignore
├── .gitmodules
├── AGENTS.md
├── LICENSE.txt
├── README.rst
├── doc/
│ ├── evaluator.html
│ ├── index.html
│ ├── lextab.html
│ ├── parser.html
│ ├── parsetab.html
│ ├── pcmd.html
│ └── preprocessor.html
├── pcpp/
│ ├── __init__.py
│ ├── evaluator.py
│ ├── lextab.py
│ ├── parser.py
│ ├── parsetab.py
│ ├── pcmd.py
│ └── preprocessor.py
├── pyproject.toml
├── requirements.txt
├── setup.py
└── tests/
├── Readme.md
├── __init__.py
├── alternate_input_encodings.py
├── alternate_input_encodings1_ucs16le.c
├── alternate_input_encodings2_ucs16le.c
├── cstd.py
├── doctests.py
├── embedded.py
├── eval.py
├── issue0017/
│ ├── inc.h
│ └── issue0017.c
├── issue0017-ref.i
├── issue0017.py
├── issue0025/
│ ├── inc.h
│ └── main.c
├── issue0025-ref.i
├── issue0025.py
├── issue0027.py
├── issue0030/
│ ├── source1.c
│ ├── source2.c
│ └── source3.c
├── issue0030.py
├── issue0032.py
├── issue0037/
│ └── inc.h
├── issue0037.py
├── issue0044.h
├── issue0044.py
├── issue0051.c
├── issue0051.h
├── issue0051.py
├── issue0057.h
├── issue0057.py
├── issue0059.py
├── issue0059a.h
├── issue0059b.h
├── issue0063.c
├── issue0063.h
├── issue0063.py
├── issue0079.py
├── issue0098/
│ ├── dir1/
│ │ └── header.h
│ ├── dir2/
│ │ └── header.h
│ ├── dir3/
│ │ └── header.h
│ └── dir4/
│ └── header.h
├── issue0098.py
├── issue0103.py
├── n_std-clang.i
├── n_std-gcc.i
├── n_std-pcpp.i
├── n_std.i
├── n_std.py
├── passthru.py
└── test-c/
├── LICENSE
├── defs.h
├── e_12_8.c
├── e_14.c
├── e_14_10.c
├── e_14_7.c
├── e_14_9.c
├── e_15_3.c
├── e_16.c
├── e_17.c
├── e_18_4.c
├── e_19_3.c
├── e_23_3.c
├── e_24_6.c
├── e_25_6.c
├── e_27_7.c
├── e_29_3.c
├── e_31.c
├── e_31_3.c
├── e_32_5.c
├── e_33_2.c
├── e_35_2.c
├── e_4_3.c
├── e_7_4.c
├── e_std.c
├── header.h
├── i_32_3.c
├── i_35.c
├── i_35_3.c
├── ifdef15.h
├── line.h
├── m1024.h
├── m_33_big5.c
├── m_33_eucjp.c
├── m_33_gb.c
├── m_33_jis.c
├── m_33_ksc.c
├── m_33_sjis.c
├── m_33_utf8.c
├── m_34_big5.c
├── m_34_eucjp.c
├── m_34_gb.c
├── m_34_jis.c
├── m_34_ksc.c
├── m_34_sjis.c
├── m_34_utf8.c
├── m_36_big5.c
├── m_36_jis.c
├── m_36_sjis.c
├── n_1.c
├── n_10.c
├── n_11.c
├── n_12.c
├── n_13.c
├── n_13_13.c
├── n_13_5.c
├── n_13_7.c
├── n_13_8.c
├── n_15.c
├── n_18.c
├── n_19.c
├── n_2.c
├── n_20.c
├── n_21.c
├── n_22.c
├── n_23.c
├── n_24.c
├── n_25.c
├── n_26.c
├── n_27.c
├── n_28.c
├── n_29.c
├── n_3.c
├── n_30.c
├── n_32.c
├── n_37.c
├── n_3_4.c
├── n_4.c
├── n_5.c
├── n_6.c
├── n_7.c
├── n_8.c
├── n_8_2.c
├── n_9.c
├── n_i_.lst
├── n_std.c
├── nest1.h
├── nest10.h
├── nest11.h
├── nest12.h
├── nest13.h
├── nest14.h
├── nest15.h
├── nest2.h
├── nest3.h
├── nest4.h
├── nest5.h
├── nest6.h
├── nest7.h
├── nest8.h
├── nest9.h
├── side_cpp
├── u_1_1.c
├── u_1_11.c
├── u_1_12.c
├── u_1_13.c
├── u_1_14.c
├── u_1_17.c
├── u_1_19.c
├── u_1_22.c
├── u_1_23.c
├── u_1_24.c
├── u_1_25.c
├── u_1_27.c
├── u_1_28.c
├── u_1_5.c
├── u_1_7_big5.c
├── u_1_7_eucjp.c
├── u_1_7_gb.c
├── u_1_7_jis.c
├── u_1_7_ksc.c
├── u_1_7_sjis.c
├── u_1_7_utf8.c
├── u_1_8.c
├── u_2.c
├── unbal1.h
├── unbal2.h
├── unbal3.h
├── unbal4.h
├── unbal5.h
├── unbal6.h
├── undefs.c
├── unspcs.c
└── warns.c
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
* text=auto !eol svneol=native#text/plain
*.gitattributes text svneol=native#text/plain
# Scriptish formats
*.bat text svneol=native#text/plain
*.bsh text svneol=native#text/x-beanshell
*.cgi text svneol=native#text/plain
*.cmd text svneol=native#text/plain
*.js text svneol=native#text/javascript
*.php text svneol=native#text/x-php
*.pl text svneol=native#text/x-perl
*.pm text svneol=native#text/x-perl
*.py text svneol=native#text/x-python
*.sh eol=lf svneol=LF#text/x-sh
configure eol=lf svneol=LF#text/x-sh
# Image formats
*.bmp binary svneol=unset#image/bmp
*.gif binary svneol=unset#image/gif
*.ico binary svneol=unset#image/ico
*.jpeg binary svneol=unset#image/jpeg
*.jpg binary svneol=unset#image/jpeg
*.png binary svneol=unset#image/png
*.tif binary svneol=unset#image/tiff
*.tiff binary svneol=unset#image/tiff
*.svg text svneol=native#image/svg%2Bxml
# Data formats
*.pdf binary svneol=unset#application/pdf
*.avi binary svneol=unset#video/avi
*.doc binary svneol=unset#application/msword
*.dsp text svneol=crlf#text/plain
*.dsw text svneol=crlf#text/plain
*.eps binary svneol=unset#application/postscript
*.json text svneol=native#application/json
*.gz binary svneol=unset#application/gzip
*.mov binary svneol=unset#video/quicktime
*.mp3 binary svneol=unset#audio/mpeg
*.ppt binary svneol=unset#application/vnd.ms-powerpoint
*.ps binary svneol=unset#application/postscript
*.psd binary svneol=unset#application/photoshop
*.rdf binary svneol=unset#text/rdf
*.rss text svneol=unset#text/xml
*.rtf binary svneol=unset#text/rtf
*.sln text svneol=native#text/plain
*.swf binary svneol=unset#application/x-shockwave-flash
*.tgz binary svneol=unset#application/gzip
*.vcproj text svneol=native#text/xml
*.vcxproj text svneol=native#text/xml
*.vsprops text svneol=native#text/xml
*.wav binary svneol=unset#audio/wav
*.xls binary svneol=unset#application/vnd.ms-excel
*.zip binary svneol=unset#application/zip
# Text formats
.htaccess text svneol=native#text/plain
*.bbk text svneol=native#text/xml
*.cmake text svneol=native#text/plain
*.css text svneol=native#text/css
*.dtd text svneol=native#text/xml
*.htm text svneol=native#text/html
*.html text svneol=native#text/html
*.ini text svneol=native#text/plain
*.log text svneol=native#text/plain
*.mak text svneol=native#text/plain
*.qbk text svneol=native#text/plain
*.rst text svneol=native#text/plain
*.sql text svneol=native#text/x-sql
*.txt text svneol=native#text/plain
*.xhtml text svneol=native#text/xhtml%2Bxml
*.xml text svneol=native#text/xml
*.xsd text svneol=native#text/xml
*.xsl text svneol=native#text/xml
*.xslt text svneol=native#text/xml
*.xul text svneol=native#text/xul
*.yml text svneol=native#text/plain
boost-no-inspect text svneol=native#text/plain
CHANGES text svneol=native#text/plain
COPYING text svneol=native#text/plain
INSTALL text svneol=native#text/plain
Jamfile text svneol=native#text/plain
Jamroot text svneol=native#text/plain
Jamfile.v2 text svneol=native#text/plain
Jamrules text svneol=native#text/plain
Makefile* text svneol=native#text/plain
README text svneol=native#text/plain
TODO text svneol=native#text/plain
# Code formats
*.c text svneol=native#text/plain
*.cpp text svneol=native#text/plain
*.h text svneol=native#text/plain
*.hpp text svneol=native#text/plain
*.ipp text svneol=native#text/plain
*.tpp text svneol=native#text/plain
*.jam text svneol=native#text/plain
*.java text svneol=native#text/plain
================================================
FILE: .github/FUNDING.yml
================================================
github: ned14
================================================
FILE: .github/workflows/ci.yml
================================================
name: CI
on:
push:
branches:
- master
pull_request:
jobs:
Build:
runs-on: ubuntu-24.04
strategy:
matrix:
python-version: ['3.x', 'pypy3.11']
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- shell: bash
run: |
pip install -r requirements.txt
git submodule update --init --recursive
- name: Build
shell: bash
run: |
python setup.py build
Test:
runs-on: ubuntu-24.04
strategy:
matrix:
python-version: ['3.x', 'pypy3.11']
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- shell: bash
run: |
pip install -r requirements.txt
git submodule update --init --recursive
- name: Test
shell: bash
run: |
pip install pytest
python -m pytest tests/ -v
Install-Pip:
runs-on: ubuntu-24.04
strategy:
matrix:
python-version: ['3.x', 'pypy3.11']
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- shell: bash
run: |
pip install -r requirements.txt
git submodule update --init --recursive
- name: Install with pip
shell: bash
run: |
python setup.py install
pcpp --version
Install-Uv:
runs-on: ubuntu-24.04
strategy:
matrix:
python-version: ['3.x', 'pypy3.11']
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Install uv
shell: bash
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- shell: bash
run: |
git submodule update --init --recursive
- name: Install with uv
shell: bash
run: |
uv venv test_env
source test_env/bin/activate
uv pip install -e .
pcpp --version
Test-Uv:
runs-on: ubuntu-24.04
strategy:
matrix:
python-version: ['3.x', 'pypy3.11']
steps:
- uses: actions/checkout@v5
- uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Install uv
shell: bash
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- shell: bash
run: |
git submodule update --init --recursive
- name: Install dependencies and pcpp with uv
shell: bash
run: |
uv venv test_env
source test_env/bin/activate
uv pip install -e .
uv pip install pytest
python -m pytest tests/ -v
================================================
FILE: .gitignore
================================================
*.pyc
build/*
dist/*
pcpp.egg-info/*
================================================
FILE: .gitmodules
================================================
[submodule "pcpp/ply"]
path = pcpp/ply
url = https://github.com/ned14/ply.git
branch = master
ignore = untracked
================================================
FILE: AGENTS.md
================================================
# Agent Overview for pcpp (Pure Python C Preprocessor)
## How to build
- `python setup.py build`
## How to test
- `python setup.py test`
## Instructions
1. Ignore everything within the `ply` submodule.
2. Run tests before making a change.
3. Run tests after making a change.
4. If writing a unit test, always use the `unittest` framework.
================================================
FILE: LICENSE.txt
================================================
(C) 2018-2026 Niall Douglas http://www.nedproductions.biz/
and (C) 2007-2019 David Beazley http://www.dabeaz.com/
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the David Beazley or Dabeaz LLC may be used to
endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: README.rst
================================================
A C99 preprocessor written in pure Python
=========================================
.. role:: c(code)
:language: c
.. |travis| image:: https://github.com/ned14/pcpp/actions/workflows/ci.yml/badge.svg?branch=master
:align: middle
:target: https://github.com/ned14/pcpp/actions
\(C) 2018-2026 Niall Douglas http://www.nedproductions.biz/ and (C) 2007-2020 David Beazley http://www.dabeaz.com/
PyPI: https://pypi.python.org/pypi/pcpp Github: https://github.com/ned14/pcpp API reference docs: https://ned14.github.io/pcpp/
Travis master branch all tests passing for Python 3 and PyPy3: |travis|
A pure universal Python C (pre-)preprocessor implementation very useful for pre-preprocessing header only
C++ libraries into single file includes and other such build or packaging stage malarky.
The implementation can be used as a Python module (`see API reference <https://ned14.github.io/pcpp/>`_)
or as a command line tool ``pcpp`` which
can stand in for a conventional C preprocessor (i.e. it'll accept similar arguments).
Works great under PyPy, and you can expect performance gains of between 0.84x and 2.62x
(average = 2.2x, median = 2.31x).
To install pcpp, you can use either pip or uv:
Using pip:
::
pip install pcpp
Using uv (faster installation):
::
uv install pcpp
Your includes can be benchmarked for heft in order to improve your build times! See
the ``--times`` and ``--filetimes`` options, and you can see graphs from pcpp for the
C++ STLs at https://github.com/ned14/stl-header-heft.
A very unique facility of this C preprocessor is *partial* preprocessing so you can
programmatically control how much preprocessing is done by ``pcpp`` and how much is
done by the C or C++ compiler's preprocessor. The ultimate control is by subclassing
the :c:`Preprocessor` class in Python from which you can do anything you like, however
for your convenience the ``pcpp`` command line tool comes with the following canned
partial preprocessing algorithms:
**passthru-defines**
Pass through but still execute #defines and #undefs if not always removed by
preprocessor logic. This ensures that including the output sets exactly the same
macros as if you included the original, plus include guards work.
**passthru-unfound-includes**
If an :c:`#include` is not found, pass it through unmodified. This is very useful
for passing through includes of system headers.
**passthru-undefined-exprs**
This is one of the most powerful pass through algorithms. If an expression passed to
:c:`#if` (or its brethern) contains an unknown macro, expand the expression with
known macros and pass through *unexecuted*, and then pass through the remaining block.
Each :c:`#elif` is evaluated in turn and if it does not contain unknown macros, it will be
executed immediately. Finally, any :c:`#else` clause is always passed through *unexecuted*.
Note that include guards normally defeat this algorithm, so those are specially detected and
ignored.
**passthru-comments**
A major use case for ``pcpp`` is as a preprocessor for the `doxygen <http://www.stack.nl/~dimitri/doxygen/>`_
reference documentation tool whose preprocessor is unable to handle any preprocessing
of any complexity. ``pcpp`` can partially execute the preprocessing which doxygen
is incapable of, thus generating output which produces good results with doxygen.
Hence the ability to pass through comments containing doxygen markup is very useful.
**passthru-magic-macros**
Don't expand ``__DATE__``, ``__TIME__``, ``__FILE__``, ``__LINE__`` nor ``__COUNTER__``.
**passthru-includes**
Don't expand those ``#include`` whose arguments match the supplied regular expression
into the output, however still execute those includes. This lets you generate output
with macros from nested includes expanded, however those ``#include`` matching
the regular expression are passed through into the output.
Standards (non-)compliance
--------------------------
``pcpp`` passes a very slightly modified edition of the `mcpp <http://mcpp.sourceforge.net/>`_
unit test suite. The only modifications done were to disable the digraph and trigraphs tests.
It also passes the list of "preprocessor torture" expansion fragments
in the C11 standard, correctly expanding some very complex recursive macro expansions
where expansions cause new macro expansions to be formed. In this, it handily beats
the MSVC preprocessor and ought to handle most C99 preprocessor metaprogramming.
If you compare its output side-by-side to that of GCC or clang's preprocessor, results
are extremely close indeed with blank line collapsing being the only difference.
As of v1.30 (Oct 2020), a proper yacc based expression evaluator for :c:`#if`
expressions is used which is standards conforming, and fixes a large number of
problems found in the previous Python :c:`eval()` based expression evaluator.
A full, detailed list of known non-conformance with the C99 standard is below.
Pull requests with bug fixes and new unit tests for the fix are welcome.
On Python 3, input and output files can have your choice of encoding, and you can
hook file open to inspect the encoding using ``chardet``.
Note that most of this preprocessor was written originally by David Beazley to show
off his excellent Python Lex-Yacc library PLY (http://www.dabeaz.com/ply/) and is
hidden in there without being at all obvious given the number of Stack Overflow
questions which have asked for a pure Python C preprocessor implementation. This
implementation fixes a lot of conformance bugs (the original was never intended to
rigidly adhere to the C standard) and adds in a test suite based on the C11 preprocessor
torture samples plus the mcpp preprocessor test suite. Still, this project would
not be possible without David's work, so please take off your hat and give a bow towards him.
Command line tool ``pcpp``:
---------------------------
The help from the command line tool ``pcpp``::
usage: pcpp [-h] [-o [path]] [-D macro[=val]] [-U macro] [-N macro] [-I path]
[--passthru-defines] [--passthru-unfound-includes]
[--passthru-unknown-exprs] [--passthru-comments]
[--passthru-magic-macros] [--passthru-includes <regex>]
[--disable-auto-pragma-once] [--line-directive [form]] [--debug]
[--time] [--filetimes [path]] [--compress]
[--assume-input-encoding <encoding>]
[--output-encoding <encoding>] [--write-bom] [--version]
[input [input ...]]
A pure universal Python C (pre-)preprocessor implementation very useful for
pre-preprocessing header only C++ libraries into single file includes and
other such build or packaging stage malarky.
positional arguments:
input Files to preprocess (use '-' for stdin)
optional arguments:
-h, --help show this help message and exit
-o [path] Output to a file instead of stdout
-D macro[=val] Predefine name as a macro [with value]
-U macro Pre-undefine name as a macro
-N macro Never define name as a macro, even if defined during
the preprocessing.
-I path Path to search for unfound #include's
--passthru-defines Pass through but still execute #defines and #undefs if
not always removed by preprocessor logic
--passthru-unfound-includes
Pass through #includes not found without execution
--passthru-unknown-exprs
Unknown macros in expressions cause preprocessor logic
to be passed through instead of executed by treating
unknown macros as 0L
--passthru-comments Pass through comments unmodified
--passthru-magic-macros
Pass through double underscore magic macros unmodified
--passthru-includes <regex>
Regular expression for which #includes to not expand.
#includes, if found, are always executed
--disable-auto-pragma-once
Disable the heuristics which auto apply #pragma once
to #include files wholly wrapped in an obvious include
guard macro
--line-directive [form]
Form of line directive to use, defaults to #line,
specify nothing to disable output of line directives
--debug Generate a pcpp_debug.log file logging execution
--time Print the time it took to #include each file
--filetimes [path] Write CSV file with time spent inside each included
file, inclusive and exclusive
--compress Make output as small as possible
--assume-input-encoding <encoding>
The text encoding to assume inputs are in
--output-encoding <encoding>
The text encoding to use when writing files
--write-bom Prefix any output with a Unicode BOM
--version show program's version number and exit
Note that so pcpp can stand in for other preprocessor tooling, it ignores any
arguments it does not understand.
Quick demo of pass through mode
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Let us look at an example for pass through mode. Here is the original:
.. code-block:: c
#if !defined(__cpp_constexpr)
#if __cplusplus >= 201402L
#define __cpp_constexpr 201304 // relaxed constexpr
#else
#define __cpp_constexpr 190000
#endif
#endif
#ifndef BOOSTLITE_CONSTEXPR
#if __cpp_constexpr >= 201304
#define BOOSTLITE_CONSTEXPR constexpr
#endif
#endif
#ifndef BOOSTLITE_CONSTEXPR
#define BOOSTLITE_CONSTEXPR
#endif
``pcpp test.h --passthru-defines --passthru-unknown-exprs`` will output:
.. code-block:: c
#if !defined(__cpp_constexpr)
#if __cplusplus >= 201402
#define __cpp_constexpr 201304
#else
#define __cpp_constexpr 190000
#endif
#endif
#ifndef BOOSTLITE_CONSTEXPR
#if __cpp_constexpr >= 201304
#define BOOSTLITE_CONSTEXPR constexpr
#endif
#endif
#ifndef BOOSTLITE_CONSTEXPR
#define BOOSTLITE_CONSTEXPR
#endif
This is because ``__cpp_constexpr`` was not defined, so because of the ``--passthru-unknown-exprs`` flag
we pass through everything inside that if block **unexecuted** i.e. defines and undefs are NOT executed by
``pcpp``. Let's define ``__cpp_constexpr``:
``pcpp test.h --passthru-defines --passthru-unknown-exprs -D __cpp_constexpr``
.. code-block:: c
#line 8 "test.h"
#ifndef BOOSTLITE_CONSTEXPR
#endif
#ifndef BOOSTLITE_CONSTEXPR
#define BOOSTLITE_CONSTEXPR
#endif
So, big difference now. We execute the entire first if block as ``__cpp_constexpr`` is now defined, thus
leaving whitespace. Let's try setting ``__cpp_constexpr`` a bit higher:
``pcpp test.h --passthru-defines --passthru-unknown-exprs -D __cpp_constexpr=201304``
.. code-block:: c
#line 8 "test.h"
#ifndef BOOSTLITE_CONSTEXPR
#define BOOSTLITE_CONSTEXPR constexpr
#endif
As you can see, the lines related to the known ``__cpp_constexpr`` are executed and removed, passing through
any if blocks with unknown macros in the expression.
What if you want a macro to be known but undefined? The -U (to undefine) flag has an obvious meaning in pass
through mode in that it makes a macro no longer unknown, but known to be undefined.
``pcpp test.h --passthru-defines --passthru-unknown-exprs -U __cpp_constexpr``
.. code-block:: c
#if __cplusplus >= 201402
#define __cpp_constexpr 201304
#else
#define __cpp_constexpr 190000
#endif
#ifndef BOOSTLITE_CONSTEXPR
#endif
#ifndef BOOSTLITE_CONSTEXPR
#define BOOSTLITE_CONSTEXPR
#endif
Here ``__cpp_constexpr`` is known to be undefined so the first clause executes, but ``__cplusplus`` is
unknown so that entire block is passed through unexecuted. In the next test comparing ``__cpp_constexpr``
to 201304 it is still known to be undefined, and so 0 >= 201304 is the expressions tested which is false,
hence the following stanza is removed entirely.
Helping ``pcpp`` using source code annotation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can achieve a great deal using -D (define), -U (undefine) and -N (never define) on the command line,
but for more complex preprocessing it gets hard to pass through the correct logic without some source code
annotation.
``pcpp`` lets you annotate which part of an if block being passed through due to use of unknown macros
to also be executed in addition to the pass through. For this use ``__PCPP_ALWAYS_FALSE__`` or
``__PCPP_ALWAYS_TRUE__`` which tells ``pcpp`` to temporarily start executing the passed through
preprocessor commands e.g.
.. code-block:: c
#if !defined(__cpp_constexpr)
#if __cplusplus >= 201402L
#define __cpp_constexpr 201304
#elif !__PCPP_ALWAYS_FALSE__ // pcpp please execute this next block
#define __cpp_constexpr 190000
#endif
#endif
#ifndef BOOSTLITE_CONSTEXPR
#if __cpp_constexpr >= 201304
#define BOOSTLITE_CONSTEXPR constexpr
#endif
#endif
#ifndef BOOSTLITE_CONSTEXPR
#define BOOSTLITE_CONSTEXPR
#endif
Note that ``__PCPP_ALWAYS_FALSE__`` will always be false in any other preprocessor, and it is also
false in ``pcpp``. However, it causes ``pcpp`` to execute the define of ``__cpp_constexpr`` to 190000:
``pcpp test.h --passthru-defines --passthru-unknown-exprs``
.. code-block:: c
#if !defined(__cpp_constexpr)
#if __cplusplus >= 201402
#define __cpp_constexpr 201304
#elif 1
#define __cpp_constexpr 190000
#endif
#endif
#ifndef BOOSTLITE_CONSTEXPR
#endif
#ifndef BOOSTLITE_CONSTEXPR
#define BOOSTLITE_CONSTEXPR
#endif
This is one way of marking up ``#else`` clauses so they always execute in a normal preprocessor
and also pass through with execution with ``pcpp``. You can, of course, also place ``|| __PCPP_ALWAYS_FALSE__``
in any ``#if`` stanza to cause it to be passed through with execution, but not affect the
preprocessing logic otherwise.
What's implemented by the ``Preprocessor`` class:
=================================================
- Digraphs and Trigraphs
- line continuation operator '``\``'
- C99 correct elimination of comments and maintenance of whitespace in output.
- :c:`__DATE__`, :c:`__TIME__`, :c:`__FILE__`, :c:`__LINE__`. Note that :c:`__STDC__` et al are NOT defined by
default, you need to define those manually before starting preprocessing.
- :c:`__COUNTER__`, a very common extension
- Object :c:`#define`
- Function :c:`#define macro(...)`
- Retokenisation and reexpansion after expansion is C99 compliant.
- :c:`#undef`
- :c:`#include "path"`, :c:`<path>` and :c:`PATH`
- :c:`defined` operator
- C operators:
- :c:`+, -, !, ~`
- :c:`*, /, %`
- :c:`+, -`
- :c:`<<, >>`
- :c:`<, <=, >, >=`
- :c:`==, !=`
- :c:`&`
- :c:`^`
- :c:`|`
- :c:`&&`
- :c:`||`
- :c:`x ? y : z` (partial support, see known bugs)
- :c:`#if`, :c:`#ifdef`, :c:`#ifndef`, :c:`#elif`, :c:`#else`, :c:`#endif`
- Stringizing operator #
- Token pasting operator ##
- :c:`#pragma once`, a very common extension
Additionally implemented by ``pcpp`` command line tool:
-------------------------------------------------------
- :c:`#error` (default implementation prints to stderr and increments the exit code)
- :c:`#warning` (default implementation prints to stderr)
Not implemented yet (donations of code welcome):
------------------------------------------------
- :c:`#pragma` anything other than :c:`once`.
- :c:`_Pragma` used to emit preprocessor calculated #pragma.
- :c:`#line num`, :c:`num "file"` and :c:`NUMBER FILE`.
Known bugs (ordered from worst to least worst):
-----------------------------------------------
None presently known.
Customising your own preprocessor:
==================================
See the API reference docs at https://ned14.github.io/pcpp/
You can find an example of overriding the ``on_*()`` processing hooks at https://github.com/ned14/pcpp/blob/master/pcpp/pcmd.py
Running Tests
=============
To run the test suite for ``pcpp``, you can use either of these methods:
1. Using pytest directly (recommended):
::
python -m pytest tests/ -v
2. Using the setup.py test command (deprecated but still functional):
::
python setup.py test
The test suite includes various test cases covering C99 preprocessor functionality,
edge cases, and compatibility with the C11 standard preprocessor torture samples.
History:
========
v1.31 (?):
----------
- Remove Python 2 support completely; pcpp is now Python 3 only
(issue #87).
- Replace setuptools test suite with pytest as the test runner.
- Add ``uv`` support for faster dependency installation.
- Rearrange ``main()`` function logic to avoid code duplication and make the
entry point cleaner (PR #73). Thanks to assarbad for this improvement.
- Fix issue #79 by replacing ``CPP_INTEGER`` and ``CPP_FLOAT`` tokens with a
``PP_NUMBER`` token for better preprocessing compliance. Update ``PP_NUMBER``
regex definition to properly handle digit separators in numeric literals.
Add new test file for issue0079. Thanks to willwray for the PR implementing
these features.
- Add support for ``#include_next``, though note it is gated behind the
``--enable-include-next`` command line option. Thanks to Dudeldu for the original
PR #98.
- Multi line and unicode character literals were not working by pure oversight.
Fixed and thanks to geky for showing the issue in PR #103.
- Add support for ``__has_include``, a long requested and oft requested
feature (#53, #77, #97).
- Disable the processing of trigraphs by default to match other C preprocessors.
Now pass ``--trigraphs`` to enable them. Thanks to pmp-p for suggesting this #100.
- Believe it or not, until now this caused an infinite loop:
```
#define FOO(x) x
#define BAR FOO(BAR)
BAR
```
This is fixed, which closes #72, #101 and possibly quite a few more open issues.
Thanks to MatthewShao for originally reporting this.
v1.30 (29th October 2021):
--------------------------
- Thanks to a 5km limit covid lockdown in my country, a public holiday where we were
supposed to be away meant I was stuck at home instead. I took the full day to finish
the https://github.com/ned14/pcpp/tree/yacc_expression_evaluator branch which is a
proper C preprocessor expression evaluator based on http://www.dabeaz.com/ply/ 's
yacc module. This was a very long outstanding piece of work which had been in
progress for nearly two years. It just needed a full day of my time to get it done,
and now it is indeed done at long last.
- BREAKING CHANGE: Thanks to the new expression evaluator, fix a long standing bug
where unknown function macros in expressions were parsed as ``0(0)`` which obviously
enough does not work. Fixing this changes how the ``on_unknown_macro_in_expr()``
hook works, and there is now an added ``on_unknown_macro_function_in_expr()`` hook.
- Add a new passthru option ``--passthru-includes`` which enables selected ``#include``
to be passed through, in addition to being executed. Thanks to schra for suggesting
this, including a PR. The original implementation had some subtle corner case bugs,
thanks to trelau for reporting those.
- Fix a token expansion ordering bug whereby if a function macro used the same
macro in more than one argument, expansion in one argument evaluation caused overly
eager expansion in later argument evaluations. This fix ought to fix pcpp's ability
to parse Boost (untested). Thanks to joaquintides for reporting this.
- Now that pcpp no longer ever calls ``eval()``, pcpp is PyPy compatible and is
probably also compatible with Pyston (untested). Typical speedup is about 2.2x-2.3x,
though it can also be slower occasionally for some inputs. PyPy compatibility is now
being tested by CI to ensure it remains working going forth.
- Fix internal preprocessor error and failure to insert newlines before ``#include``
caused by certain sequence of line continuations in a macro. Thanks to dslijepcevic
for reporting this.
v1.22 (19th October 2020):
--------------------------
- Fix bug where outputting to stdout did not combine with anything which
printed to stdout. Thanks to Fondesa for reporting this.
- Fix extra newlines being inserted after a multiline comment. Thanks to virtuald
for sending a PR fixing this.
- Fix not being able to actually specify an empty line directive. Thanks to kuri65536
for sending a PR fixing this.
- Update ply submodule to latest from trunk.
- Emit line continuations as tokens, rather than collapsing lines during parsing.
Thanks to MathieuDuponchelle for the pull request implementing this.
- Enable parsing and emission of files in arbitrary text encodings. This is supported
in Python 3 or later only. Thanks to MathieuDuponchelle for the suggestion.
- Fix bad regex for parsing floats, so now floats are correctly tokenised. Thanks
to LynnKirby for reporting this.
- BREAKING CHANGE: Passthrough for ``#include MACRO`` was not supported. This was not
intentional, and to fix it required modifying the ``on_include_not_found()``
customisation point which is a source breaking change. Thanks to schra for reporting this.
v1.21 (30th September 2019):
----------------------------
- Fix bug where token pasting two numeric tokens did not yield a numeric token. Thanks
to Sei-Lisa for reporting this.
- BREAKING CHANGE: Paths emitted by pcpp into ``#line`` directives now are relative to the
working directory of the process when ``Preprocessor`` is initialised. This includes
added search paths - files included from those locations will be emitted with a sequence
of ``../`` to relativise the path emitted. If no path exists between the working
directory and the path of the file being emitted, an absolute path is emitted instead.
If you wish to disable this new behaviour, or use different behaviour, you can
customise the new `rewrite_paths` member variable of ``Preprocessor``.
- Fix bug where ``__LINE__`` was expanding into the line number of its definition instead
of its use. Thanks to Sei-Lisa for reporting this.
- Add ``--passthru-magic-macros`` command line option.
- BREAKING CHANGE: The ``PreprocessorHooks`` and ``OutputDirective`` interface has
changed. One now must specify the kind of ``OutputDirective`` abort one wants, and one
can now both ignore AND remove directives. ``on_directive_handle()`` and
``on_directive_unknown()`` now take an extra parameter ``precedingtoks``, these are the
tokens from the ``#`` up to the directive.
- Fix a corner case where ``FUNC(void)foo()`` expanded to ``voidfoo()`` and not
``void foo()`` which is a very common non-conforming extension of the C preprocessor.
Thanks to OmegaDoom for reporting this.
- Add tokens for all the C operators, to help implementation of an expression evaluator.
- Updated embedded ply to HEAD (2019-04-25)
- Fix ``#include`` not working if no ``-I`` parameters were supplied. Thanks to csm10495
for reporting this.
v1.20 (7th January 2019):
-------------------------
- Now supports character literals in expressions. Thanks to untaugh for the pull request
adding this.
- Stopped the default collapsing of whitespace in output, and made it optional via a
new command line option ``--compress``.
- Fixed extraneous whitespace in ``--passthru-comments`` caused by multiline comments.
Thanks to p2k for reporting this.
- Fixed bug where defining a macro via string did not set the source attribute in the
token. Thanks to ZedThree for reporting this.
- Stop triggering an exception when no arguments are supplied to pcpp. Thanks to
virtuald for reporting this.
- Rebase onto PLY latest from Dec 28th 2018 (https://github.com/dabeaz/ply/commit/a37e0839583d683d95e70ce1445c0063c7d4bd21). Latest
PLY no longer works using pypi packaging, David wants people to include the source of
PLY directly. pcpp does this via a git submodule, and has setuptools bundle the submodule.
- Add a formal LICENSE.txt file, as requested by Sei-Lisa.
- Fix failure to issue ``#line`` directive for first include file in a file. Thanks to
Sei-Lisa for reporting this.
v1.1 (19th June 2018):
----------------------
- Added the ``--times`` and ``--filetimes`` features.
- Fix bug where macros containing operator `defined` were not being expanded properly.
- Added the ability to accept multiple inputs, they are concatenated into the output.
- Fix bug where lines beginning with `#` and no contents caused an internal preprocessor error.
- Fix bug where the macro expansion ``par par##ext`` was expanding into ``parext parext``.
v1.01 (21st Feb 2018):
----------------------
- Fix bug where in pass through mode, an #elif in an #if block inside an #if block in ifpassthru was failing to be passed through.
- Downgraded failure to evaluate an expression to a warning.
- Fix missing Readme.rst in pypi package.
v1.00 (13th Mar 2017):
----------------------
First release
================================================
FILE: doc/evaluator.html
================================================
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.5.3" />
<title>pcpp.evaluator API documentation</title>
<meta name="description" content="" />
<link href='https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.0/normalize.min.css' rel='stylesheet'>
<link href='https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/8.0.0/sanitize.min.css' rel='stylesheet'>
<link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github.min.css" rel="stylesheet">
<style>
.flex {
display: flex !important
}
body {
line-height: 1.5em
}
#content {
padding: 20px
}
#sidebar {
padding: 30px;
overflow: hidden
}
.http-server-breadcrumbs {
font-size: 130%;
margin: 0 0 15px 0
}
#footer {
font-size: .75em;
padding: 5px 30px;
border-top: 1px solid #ddd;
text-align: right
}
#footer p {
margin: 0 0 0 1em;
display: inline-block
}
#footer p:last-child {
margin-right: 30px
}
h1,
h2,
h3,
h4,
h5 {
font-weight: 300
}
h1 {
font-size: 2.5em;
line-height: 1.1em
}
h2 {
font-size: 1.75em;
margin: 1em 0 .50em 0
}
h3 {
font-size: 1.4em;
margin: 25px 0 10px 0
}
h4 {
margin: 0;
font-size: 105%
}
a {
color: #058;
text-decoration: none;
transition: color .3s ease-in-out
}
a:hover {
color: #e82
}
.title code {
font-weight: bold
}
h2[id^="header-"] {
margin-top: 2em
}
.ident {
color: #900
}
pre code {
background: #f8f8f8;
font-size: .8em;
line-height: 1.4em
}
code {
background: #f2f2f1;
padding: 1px 4px;
overflow-wrap: break-word
}
h1 code {
background: transparent
}
pre {
background: #f8f8f8;
border: 0;
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
margin: 1em 0;
padding: 1ex
}
#http-server-module-list {
display: flex;
flex-flow: column
}
#http-server-module-list div {
display: flex
}
#http-server-module-list dt {
min-width: 10%
}
#http-server-module-list p {
margin-top: 0
}
.toc ul,
#index {
list-style-type: none;
margin: 0;
padding: 0
}
#index code {
background: transparent
}
#index h3 {
border-bottom: 1px solid #ddd
}
#index ul {
padding: 0
}
#index h4 {
font-weight: bold
}
#index h4+ul {
margin-bottom: .6em
}
@media (min-width:200ex) {
#index .two-column {
column-count: 2
}
}
@media (min-width:300ex) {
#index .two-column {
column-count: 3
}
}
dl {
margin-bottom: 2em
}
dl dl:last-child {
margin-bottom: 4em
}
dd {
margin: 0 0 1em 3em
}
#header-classes+dl>dd {
margin-bottom: 3em
}
dd dd {
margin-left: 2em
}
dd p {
margin: 10px 0
}
.name {
background: #eee;
font-weight: bold;
font-size: .85em;
padding: 5px 10px;
display: inline-block;
min-width: 40%
}
.name:hover {
background: #e0e0e0
}
.name>span:first-child {
white-space: nowrap
}
.name.class>span:nth-child(2) {
margin-left: .4em
}
.name small {
font-weight: normal
}
.inherited {
color: #999;
border-left: 5px solid #eee;
padding-left: 1em
}
.inheritance em {
font-style: normal;
font-weight: bold
}
.desc h2 {
font-weight: 400;
font-size: 1.25em
}
.desc h3 {
font-size: 1em
}
.desc dt code {
background: inherit
}
.source summary {
color: #666;
text-align: right;
font-weight: 400;
font-size: .8em;
text-transform: uppercase;
cursor: pointer
}
.source pre {
max-height: 500px;
overflow: auto;
margin: 0
}
.source pre code {
font-size: 12px;
overflow: visible
}
.hlist {
list-style: none
}
.hlist li {
display: inline
}
.hlist li:after {
content: ',\2002'
}
.hlist li:last-child:after {
content: none
}
.hlist .hlist {
display: inline;
padding-left: 1em
}
img {
max-width: 100%
}
.admonition {
padding: .1em .5em
}
.admonition-title {
font-weight: bold
}
.admonition.note,
.admonition.info,
.admonition.important {
background: #aef
}
.admonition.todo,
.admonition.versionadded,
.admonition.tip,
.admonition.hint {
background: #dfd
}
.admonition.warning,
.admonition.versionchanged,
.admonition.deprecated {
background: #fd4
}
.admonition.error,
.admonition.danger,
.admonition.caution {
background: lightpink
}
</style>
<style media="screen and (min-width: 700px)">
@media screen and (min-width:700px) {
#sidebar {
width: 30%
}
#content {
width: 70%;
max-width: 100ch;
padding: 3em 4em;
border-left: 1px solid #ddd
}
pre code {
font-size: 1em
}
.item .name {
font-size: 1em
}
main {
display: flex;
flex-direction: row-reverse;
justify-content: flex-end
}
.toc ul ul,
#index ul {
padding-left: 1.5em
}
.toc>ul>li {
margin-top: .5em
}
}
</style>
<style media="print">
@media print {
#sidebar h1 {
page-break-before: always
}
.source {
display: none
}
}
@media print {
* {
background: transparent !important;
color: #000 !important;
box-shadow: none !important;
text-shadow: none !important
}
a[href]:after {
content: " (" attr(href) ")";
font-size: 90%
}
a[href][title]:after {
content: none
}
abbr[title]:after {
content: " (" attr(title) ")"
}
.ir a:after,
a[href^="javascript:"]:after,
a[href^="#"]:after {
content: ""
}
pre,
blockquote {
border: 1px solid #999;
page-break-inside: avoid
}
thead {
display: table-header-group
}
tr,
img {
page-break-inside: avoid
}
img {
max-width: 100% !important
}
@page {
margin: 0.5cm
}
p,
h2,
h3 {
orphans: 3;
widows: 3
}
h1,
h2,
h3,
h4,
h5,
h6 {
page-break-after: avoid
}
}
</style>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title"><code>pcpp.evaluator</code> module</h1>
</header>
<section id="section-intro">
<details class="source">
<summary>Source code</summary>
<pre><code class="python">#!/usr/bin/python
# Python C99 conforming preprocessor expression evaluator
# (C) 2019-2026 Niall Douglas http://www.nedproductions.biz/
# Started: Apr 2019
from __future__ import generators, print_function, absolute_import, division
import sys, os, re, codecs, copy
if __name__ == '__main__' and __package__ is None:
sys.path.append( os.path.dirname( os.path.dirname( os.path.abspath(__file__) ) ) )
from pcpp.parser import STRING_TYPES, yacc, default_lexer, in_production
# The width of signed integer which this evaluator will use
INTMAXBITS = 64
# Some Python 3 compatibility shims
if sys.version_info.major < 3:
INTBASETYPE = long
else:
INTBASETYPE = int
# Precompile the regular expression for correctly expanding unicode escape
# sequences in Python 2 and 3. See https://stackoverflow.com/questions/4020539/process-escape-sequences-in-a-string-in-python
# for more information.
_expand_escape_sequences_pat = re.compile(r'''
( \\U........ # 8-digit hex escapes
| \\u.... # 4-digit hex escapes
| \\x.. # 2-digit hex escapes
| \\[0-7]{1,3} # Octal escapes
| \\N\{[^}]+\} # Unicode characters by name
| \\[\\'"abfnrtv] # Single-character escapes
)''', re.UNICODE | re.VERBOSE)
class Value(INTBASETYPE):
"""A signed or unsigned integer within a preprocessor expression, bounded
to within INT_MIN and INT_MAX, or 0 and UINT_MAX. Signed overflow is handled
like a two's complement CPU, despite being UB, as that's what GCC and clang do.
>>> Value(5)
Value(5)
>>> Value('5L')
Value(5)
>>> Value('5U')
Value(5U)
>>> Value('0')
Value(0)
>>> Value('0U')
Value(0U)
>>> Value('-1U')
Value(18446744073709551615U)
>>> Value(5) * Value(2)
Value(10)
>>> Value(5) + Value('2u')
Value(7U)
>>> Value(5) * 2
Value(10)
>>> Value(5) / 2 # Must return integer
Value(2)
>>> Value(50) % 8
Value(2)
>>> -Value(5)
Value(-5)
>>> +Value(-5)
Value(-5)
>>> ~Value(5)
Value(-6)
>>> Value(6) & 2
Value(2)
>>> Value(4) | 2
Value(6)
>>> Value(6) ^ 2
Value(4)
>>> Value(2) << 2
Value(8)
>>> Value(8) >> 2
Value(2)
>>> Value(9223372036854775808)
Value(-9223372036854775808)
>>> Value(-9223372036854775809)
Value(9223372036854775807)
>>> Value(18446744073709551615)
Value(-1)
>>> Value(False)
Value(0)
>>> Value(True)
Value(1)
>>> Value(5) == Value(6)
Value(0)
>>> Value(5) == Value(5)
Value(1)
>>> not Value(2)
Traceback (most recent call last):
...
AssertionError
>>> Value(4) and Value(2)
Traceback (most recent call last):
...
AssertionError
>>> Value(5) and not Value(6)
Traceback (most recent call last):
...
AssertionError
>>> Value('0x3f')
Value(63)
>>> Value('077')
Value(63)
>>> Value("'N'")
Value(78)
>>> Value("L'N'")
Value(78)
>>> Value("'\\n'")
Value(10)
>>> Value("'\\\\n'")
Value(10)
>>> Value("'\\\\'")
Value(92)
>>> Value("'\\'")
Traceback (most recent call last):
...
SyntaxError: Empty character escape sequence
"""
INT_MIN = -(1 << (INTMAXBITS - 1))
INT_MAX = (1 << (INTMAXBITS - 1)) - 1
INT_MASK = (1 << INTMAXBITS) - 1
UINT_MIN = 0
UINT_MAX = (1 << INTMAXBITS) - 1
@classmethod
def __sclamp(cls, value):
value = INTBASETYPE(value)
return ((value - cls.INT_MIN) & cls.INT_MASK) + cls.INT_MIN
@classmethod
def __uclamp(cls, value):
value = INTBASETYPE(value)
return value & cls.UINT_MAX
def __new__(cls, value, unsigned = False, exception = None):
if isinstance(value, Value):
unsigned = value.unsigned
exception = value.exception
elif isinstance(value, INTBASETYPE) or isinstance(value, int) or isinstance(value, float):
value = cls.__uclamp(value) if unsigned else cls.__sclamp(value)
elif isinstance(value, STRING_TYPES):
if (value.startswith("L'") or value[0] == "'") and value[-1] == "'":
startidx = 2 if value.startswith("L'") else 1
#print("1. ***", value, file = sys.stderr)
value = value[startidx:-1]
if len(value) == 0:
raise SyntaxError('Empty character escape sequence')
#print("2. ***", value, file = sys.stderr)
value = _expand_escape_sequences_pat.sub(lambda x: codecs.decode(x.group(0), 'unicode-escape'), value)
#print("3. ***", value, file = sys.stderr)
x = INTBASETYPE(ord(value))
#print("4. ***", x, file = sys.stderr)
elif value.startswith('0x') or value.startswith('0X'):
# Strip any terminators
while not ((value[-1] >= '0' and value[-1] <= '9') or (value[-1] >= 'a' and value[-1] <= 'f') or (value[-1] >= 'A' and value[-1] <= 'F')):
if value[-1] == 'u' or value[-1] == 'U':
unsigned = True
value = value[:-1]
x = INTBASETYPE(value, base = 16)
elif value.startswith('0'):
# Strip any terminators
while not (value[-1] >= '0' and value[-1] <= '7'):
if value[-1] == 'u' or value[-1] == 'U':
unsigned = True
value = value[:-1]
x = INTBASETYPE(value, base = 8)
else:
# Strip any terminators
while not (value[-1] >= '0' and value[-1] <= '9'):
if value[-1] == 'u' or value[-1] == 'U':
unsigned = True
value = value[:-1]
x = INTBASETYPE(value)
value = cls.__uclamp(x) if unsigned else cls.__sclamp(x)
#assert x == value
else:
print('Unknown value type: %s' % repr(type(value)), file = sys.stderr)
assert False # Input is an unrecognised type
inst = super(Value, cls).__new__(cls, value)
inst.unsigned = unsigned
inst.exception = exception
return inst
def value(self):
if self.exception is not None:
raise self.exception
return INTBASETYPE(self)
def __add__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) + self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(super(Value, self).__add__(other))
def __sub__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) - self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(super(Value, self).__sub__(other))
def __mul__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) * self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(super(Value, self).__mul__(other))
def __div__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) / self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(super(Value, self).__div__(other))
def __truediv__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) / self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(super(Value, self).__truediv__(other))
def __mod__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) % self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(super(Value, self).__mod__(other))
def __neg__(self):
if self.exception is not None:
return self
return Value(super(Value, self).__neg__(), self.unsigned)
def __invert__(self):
if self.exception is not None:
return self
return Value(super(Value, self).__invert__(), self.unsigned)
def __and__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) & self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(super(Value, self).__and__(other))
def __or__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) | self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(super(Value, self).__or__(other))
def __pos__(self):
if self.exception is not None:
return self
return Value(super(Value, self).__pos__())
def __pow__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) ** self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(super(Value, self).__pow__(other))
def __lshift__(self, other):
if self.exception is not None:
return self
# Ignore other signedness
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) << self.__uclamp(other), True) if (self.unsigned) else Value(super(Value, self).__lshift__(other))
def __rshift__(self, other):
if self.exception is not None:
return self
# Ignore other signedness
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) >> self.__uclamp(other), True) if (self.unsigned) else Value(super(Value, self).__rshift__(other))
def __xor__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) ^ self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(super(Value, self).__xor__(other))
def __repr__(self):
if self.exception is not None:
return "Exception(%s)" % repr(self.exception)
elif self.unsigned:
return "Value(%dU)" % INTBASETYPE(self)
else:
return "Value(%d)" % INTBASETYPE(self)
def __bool__(self):
assert False # Do not use Python logical operations
def __nonzero__(self):
assert False # Do not use Python logical operations
def __cmp__(self, other):
assert False
def __lt__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) < self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(self.__sclamp(self) < self.__sclamp(other), False)
def __le__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) <= self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(self.__sclamp(self) <= self.__sclamp(other), False)
def __eq__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) == self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(self.__sclamp(self) == self.__sclamp(other), False)
def __ne__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) != self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(self.__sclamp(self) != self.__sclamp(other), False)
def __ge__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) >= self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(self.__sclamp(self) >= self.__sclamp(other), False)
def __gt__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) > self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(self.__sclamp(self) > self.__sclamp(other), False)
# PLY yacc specification
# Valid C preprocessor expression items:
# - Integer constants
# - Character constants
# - Addition, subtraction, multiplication, division, bitwise and-or-xor, shifts,
# comparisons, logical and-or-not
# - defined()
#
# The C preprocessor does not support:
# - assignment
# - increment and decrement
# - array indexing, indirection
# - casting
# - sizeof, alignof
# The subset of tokens from Preprocessor used in preprocessor expressions
tokens = (
'CPP_ID', 'CPP_INTEGER', 'CPP_CHAR', 'CPP_STRING',
'CPP_PLUS', 'CPP_MINUS', 'CPP_STAR', 'CPP_FSLASH', 'CPP_PERCENT', 'CPP_BAR',
'CPP_AMPERSAND', 'CPP_TILDE', 'CPP_HAT', 'CPP_LESS', 'CPP_GREATER', 'CPP_EXCLAMATION',
'CPP_QUESTION', 'CPP_LPAREN', 'CPP_RPAREN',
'CPP_COMMA', 'CPP_COLON',
'CPP_LSHIFT', 'CPP_LESSEQUAL', 'CPP_RSHIFT',
'CPP_GREATEREQUAL', 'CPP_LOGICALOR', 'CPP_LOGICALAND', 'CPP_EQUALITY',
'CPP_INEQUALITY'
)
# 'CPP_WS', 'CPP_EQUAL', 'CPP_BSLASH', 'CPP_SQUOTE',
precedence = (
('left', 'CPP_COMMA'), # 15
# 14 (assignments, unused)
('left', 'CPP_QUESTION', 'CPP_COLON'), # 13
('left', 'CPP_LOGICALOR'), # 12
('left', 'CPP_LOGICALAND'), # 11
('left', 'CPP_BAR'), # 10
('left', 'CPP_HAT'), # 9
('left', 'CPP_AMPERSAND'), # 8
('left', 'CPP_EQUALITY', 'CPP_INEQUALITY'), # 7
('left', 'CPP_LESS', 'CPP_LESSEQUAL', 'CPP_GREATER', 'CPP_GREATEREQUAL'), # 6
('left', 'CPP_LSHIFT', 'CPP_RSHIFT'), # 5
('left', 'CPP_PLUS', 'CPP_MINUS'), # 4
('left', 'CPP_STAR', 'CPP_FSLASH', 'CPP_PERCENT'), # 3
('right', 'UPLUS', 'UMINUS', 'CPP_EXCLAMATION', 'CPP_TILDE'), # 2
# 1 (unused in the C preprocessor)
)
def p_error(p):
if p:
raise SyntaxError("around token '%s' type %s" % (p.value, p.type))
else:
raise SyntaxError("at EOF")
def p_expression_number(p):
'expression : CPP_INTEGER'
p[0] = Value(p[1])
def p_expression_character(p):
'expression : CPP_CHAR'
p[0] = Value(p[1])
def p_expression_string(p):
"""
expression : CPP_STRING
| CPP_LESS expression CPP_GREATER
"""
p[0] = p[1]
def p_expression_group(t):
'expression : CPP_LPAREN expression CPP_RPAREN'
t[0] = t[2]
def p_expression_uplus(p):
'expression : CPP_PLUS expression %prec UPLUS'
p[0] = +Value(p[2])
def p_expression_uminus(p):
'expression : CPP_MINUS expression %prec UMINUS'
p[0] = -Value(p[2])
def p_expression_unop(p):
"""
expression : CPP_EXCLAMATION expression
| CPP_TILDE expression
"""
try:
if p[1] == '!':
p[0] = Value(0) if (Value(p[2]).value()!=0) else Value(1)
elif p[1] == '~':
p[0] = ~Value(p[2])
except Exception as e:
p[0] = Value(0, exception = e)
def p_expression_binop(p):
"""
expression : expression CPP_STAR expression
| expression CPP_FSLASH expression
| expression CPP_PERCENT expression
| expression CPP_PLUS expression
| expression CPP_MINUS expression
| expression CPP_LSHIFT expression
| expression CPP_RSHIFT expression
| expression CPP_LESS expression
| expression CPP_LESSEQUAL expression
| expression CPP_GREATER expression
| expression CPP_GREATEREQUAL expression
| expression CPP_EQUALITY expression
| expression CPP_INEQUALITY expression
| expression CPP_AMPERSAND expression
| expression CPP_HAT expression
| expression CPP_BAR expression
| expression CPP_LOGICALAND expression
| expression CPP_LOGICALOR expression
| expression CPP_COMMA expression
"""
# print [repr(p[i]) for i in range(0,4)]
try:
if p[2] == '*':
p[0] = Value(p[1]) * Value(p[3])
elif p[2] == '/':
p[0] = Value(p[1]) / Value(p[3])
elif p[2] == '%':
p[0] = Value(p[1]) % Value(p[3])
elif p[2] == '+':
p[0] = Value(p[1]) + Value(p[3])
elif p[2] == '-':
p[0] = Value(p[1]) - Value(p[3])
elif p[2] == '<<':
p[0] = Value(p[1]) << Value(p[3])
elif p[2] == '>>':
p[0] = Value(p[1]) >> Value(p[3])
elif p[2] == '<':
p[0] = Value(p[1]) < Value(p[3])
elif p[2] == '<=':
p[0] = Value(p[1]) <= Value(p[3])
elif p[2] == '>':
p[0] = Value(p[1]) > Value(p[3])
elif p[2] == '>=':
p[0] = Value(p[1]) >= Value(p[3])
elif p[2] == '==':
p[0] = Value(p[1]) == Value(p[3])
elif p[2] == '!=':
p[0] = Value(p[1]) != Value(p[3])
elif p[2] == '&':
p[0] = Value(p[1]) & Value(p[3])
elif p[2] == '^':
p[0] = Value(p[1]) ^ Value(p[3])
elif p[2] == '|':
p[0] = Value(p[1]) | Value(p[3])
elif p[2] == '&&':
p[0] = Value(1) if (Value(p[1]).value()!=0 and Value(p[3]).value()!=0) else Value(0)
elif p[2] == '||':
p[0] = Value(1) if (Value(p[1]).value()!=0 or Value(p[3]).value()!=0) else Value(0)
elif p[2] == ',':
p[0] = Value(p[3])
except Exception as e:
p[0] = Value(0, exception = e)
def p_expression_conditional(p):
'expression : expression CPP_QUESTION expression CPP_COLON expression'
try:
# Output type must cast up to unsigned if either input is unsigned
p[0] = Value(p[3]) if (Value(p[1]).value()!=0) else Value(p[5])
try:
p[0] = Value(p[0].value(), unsigned = Value(p[3]).unsigned or Value(p[5]).unsigned)
except:
pass
except Exception as e:
p[0] = Value(0, exception = e)
def p_expression_function_call(p):
"expression : CPP_ID CPP_LPAREN expression CPP_RPAREN"
try:
p.lexer.on_function_call(p)
except Exception as e:
p[0] = Value(0, exception = e)
def p_expression_identifier(p):
"expression : CPP_ID"
try:
p.lexer.on_identifier(p)
except Exception as e:
p[0] = Value(0, exception = e)
class Evaluator(object):
"""Evaluator of #if C preprocessor expressions.
>>> e = Evaluator()
>>> e('5')
Value(5)
>>> e('5+6')
Value(11)
>>> e('5+6*2')
Value(17)
>>> e('5/2+6*2')
Value(14)
>>> e('5 < 6 <= 7')
Value(1)
>>> e('5 < 6 && 8 > 7')
Value(1)
>>> e('18446744073709551615 == -1')
Value(1)
>>> e('-9223372036854775809 == 9223372036854775807')
Value(1)
>>> e('-1 < 0U')
Value(0U)
>>> e('(( 0L && 0) || (!0L && !0 ))')
Value(1)
>>> e('(1)?2:3')
Value(2)
>>> e('(1 ? -1 : 0) <= 0')
Value(1)
>>> e('(1 ? -1 : 0U)') # Output type of ? must be common between both choices
Value(18446744073709551615U)
>>> e('(1 ? -1 : 0U) <= 0')
Value(0U)
>>> e('1 && 10 / 0') # doctest: +ELLIPSIS
Exception(ZeroDivisionError('division by zero'...
>>> e('0 && 10 / 0') # && must shortcut
Value(0)
>>> e('1 ? 10 / 0 : 0') # doctest: +ELLIPSIS
Exception(ZeroDivisionError('division by zero'...
>>> e('0 ? 10 / 0 : 0') # ? must shortcut
Value(0)
>>> e('(3 ^ 5) != 6 || (3 | 5) != 7 || (3 & 5) != 1')
Value(0)
>>> e('1 << 2 != 4 || 8 >> 1 != 4')
Value(0)
>>> e('(2 || 3) != 1 || (2 && 3) != 1 || (0 || 4) != 1 || (0 && 5) != 0')
Value(0)
>>> e('-1 << 3U > 0')
Value(0)
>>> e("'N' == 78")
Value(1)
>>> e('0x3f == 63')
Value(1)
>>> e("'\\\\n'")
Value(10)
>>> e("'\\\\\\\\'")
Value(92)
>>> e("'\\\\n' == 0xA")
Value(1)
>>> e("'\\\\\\\\' == 0x5c")
Value(1)
>>> e("L'\\\\0' == 0")
Value(1)
>>> e('12 == 12')
Value(1)
>>> e('12L == 12')
Value(1)
>>> e('-1 >= 0U')
Value(1U)
>>> e('(1<<2) == 4')
Value(1)
>>> e('(-!+!9) == -1')
Value(1)
>>> e('(2 || 3) == 1')
Value(1)
>>> e('1L * 3 != 3')
Value(0)
>>> e('(!1L != 0) || (-1L != -1)')
Value(0)
>>> e('0177777 == 65535')
Value(1)
>>> e('0Xffff != 65535 || 0XFfFf == 65535')
Value(1)
>>> e('0L != 0 || 0l != 0')
Value(0)
>>> e('1U != 1 || 1u == 1')
Value(1)
>>> e('0 <= -1')
Value(0)
>>> e('1 << 2 != 4 || 8 >> 1 == 4')
Value(1)
>>> e('(3 ^ 5) == 6')
Value(1)
>>> e('(3 | 5) == 7')
Value(1)
>>> e('(3 & 5) == 1')
Value(1)
>>> e('(3 ^ 5) != 6 || (3 | 5) != 7 || (3 & 5) != 1')
Value(0)
>>> e('(0 ? 1 : 2) != 2')
Value(0)
>>> e('-1 << 3U > 0')
Value(0)
>>> e('0 && 10 / 0')
Value(0)
>>> e('not_defined && 10 / not_defined') # doctest: +ELLIPSIS
Exception(SyntaxError('Unknown identifier not_defined'...
>>> e('0 && 10 / 0 > 1')
Value(0)
>>> e('(0) ? 10 / 0 : 0')
Value(0)
>>> e('0 == 0 || 10 / 0 > 1')
Value(1)
>>> e('(15 >> 2 >> 1 != 1) || (3 << 2 << 1 != 24)')
Value(0)
>>> e('(1 | 2) == 3 && 4 != 5 || 0')
Value(1)
>>> e('1 > 0')
Value(1)
>>> e("'\123' != 83")
Value(0)
>>> e("'\x1b' != '\033'")
Value(0)
>>> e('0 + (1 - (2 + (3 - (4 + (5 - (6 + (7 - (8 + (9 - (10 + (11 - (12 + (13 - (14 + (15 - (16 + (17 - (18 + (19 - (20 + (21 - (22 + (23 - (24 + (25 - (26 + (27 - (28 + (29 - (30 + (31 - (32 + 0)))))))))) )))))))))))))))))))))) == 0')
Value(1)
>>> e('test_function(X)', functions={'test_function':lambda x: 55})
Value(55)
>>> e('test_identifier', identifiers={'test_identifier':11})
Value(11)
>>> e('defined(X)', functions={'defined':lambda x: 55})
Value(55)
>>> e('defined(X)') # doctest: +ELLIPSIS
Exception(SyntaxError('Unknown function defined'...
>>> e('__has_include("variant")') # doctest: +ELLIPSIS
Exception(SyntaxError('Unknown function __has_include'...
>>> e('__has_include(<variant>)') # doctest: +ELLIPSIS
Exception(SyntaxError('Unknown function __has_include'...
>>> e('5 // comment')
Value(5)
>>> e('5 /* comment */')
Value(5)
>>> e('5 /* comment // more */')
Value(5)
>>> e('5 // /* comment */')
Value(5)
"""
# >>> e('defined X', functions={'defined':lambda x: 55})
# Value(55)
def __init__(self, lexer = None):
self.lexer = lexer if lexer is not None else default_lexer()
self.parser = yacc.yacc(optimize=in_production,debug=not in_production,write_tables=not in_production)
class __lexer(object):
def __init__(self, functions, identifiers):
self.__toks = []
self.__functions = functions
self.__identifiers = identifiers
def input(self, toks):
self.__toks = [tok for tok in toks if tok.type != 'CPP_WS' and tok.type != 'CPP_LINECONT' and tok.type != 'CPP_COMMENT1' and tok.type != 'CPP_COMMENT2']
self.__idx = 0
def token(self):
if self.__idx >= len(self.__toks):
return None
self.__idx = self.__idx + 1
return self.__toks[self.__idx - 1]
def on_function_call(self, p):
if p[1] not in self.__functions:
raise SyntaxError('Unknown function %s' % p[1])
p[0] = Value(self.__functions[p[1]](p[3]))
def on_identifier(self, p):
if p[1] not in self.__identifiers:
raise SyntaxError('Unknown identifier %s' % p[1])
p[0] = Value(self.__identifiers[p[1]])
def __call__(self, input, functions = {}, identifiers = {}):
"""Execute a fully macro expanded set of tokens representing an expression,
returning the result of the evaluation.
"""
if not isinstance(input,list):
self.lexer.input(input)
input = []
while True:
tok = self.lexer.token()
if not tok:
break
input.append(tok)
return self.parser.parse(input, lexer = self.__lexer(functions, identifiers))
if __name__ == "__main__":
import doctest
doctest.testmod()</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="pcpp.evaluator.p_error"><code class="name flex">
<span>def <span class="ident">p_error</span></span>(<span>p)</span>
</code></dt>
<dd>
<section class="desc"></section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def p_error(p):
if p:
raise SyntaxError("around token '%s' type %s" % (p.value, p.type))
else:
raise SyntaxError("at EOF")</code></pre>
</details>
</dd>
<dt id="pcpp.evaluator.p_expression_binop"><code class="name flex">
<span>def <span class="ident">p_expression_binop</span></span>(<span>p)</span>
</code></dt>
<dd>
<section class="desc">
<dl>
<dt><strong><code>expression</code></strong> : <code>expression</code>
<code>CPP_STAR</code> <code>expression</code></dt>
<dd>| expression CPP_FSLASH expression
| expression CPP_PERCENT expression
| expression CPP_PLUS expression
| expression CPP_MINUS expression
| expression CPP_LSHIFT expression
| expression CPP_RSHIFT expression
| expression CPP_LESS expression
| expression CPP_LESSEQUAL expression
| expression CPP_GREATER expression
| expression CPP_GREATEREQUAL expression
| expression CPP_EQUALITY expression
| expression CPP_INEQUALITY expression
| expression CPP_AMPERSAND expression
| expression CPP_HAT expression
| expression CPP_BAR expression
| expression CPP_LOGICALAND expression
| expression CPP_LOGICALOR expression
| expression CPP_COMMA expression</dd>
</dl>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def p_expression_binop(p):
"""
expression : expression CPP_STAR expression
| expression CPP_FSLASH expression
| expression CPP_PERCENT expression
| expression CPP_PLUS expression
| expression CPP_MINUS expression
| expression CPP_LSHIFT expression
| expression CPP_RSHIFT expression
| expression CPP_LESS expression
| expression CPP_LESSEQUAL expression
| expression CPP_GREATER expression
| expression CPP_GREATEREQUAL expression
| expression CPP_EQUALITY expression
| expression CPP_INEQUALITY expression
| expression CPP_AMPERSAND expression
| expression CPP_HAT expression
| expression CPP_BAR expression
| expression CPP_LOGICALAND expression
| expression CPP_LOGICALOR expression
| expression CPP_COMMA expression
"""
# print [repr(p[i]) for i in range(0,4)]
try:
if p[2] == '*':
p[0] = Value(p[1]) * Value(p[3])
elif p[2] == '/':
p[0] = Value(p[1]) / Value(p[3])
elif p[2] == '%':
p[0] = Value(p[1]) % Value(p[3])
elif p[2] == '+':
p[0] = Value(p[1]) + Value(p[3])
elif p[2] == '-':
p[0] = Value(p[1]) - Value(p[3])
elif p[2] == '<<':
p[0] = Value(p[1]) << Value(p[3])
elif p[2] == '>>':
p[0] = Value(p[1]) >> Value(p[3])
elif p[2] == '<':
p[0] = Value(p[1]) < Value(p[3])
elif p[2] == '<=':
p[0] = Value(p[1]) <= Value(p[3])
elif p[2] == '>':
p[0] = Value(p[1]) > Value(p[3])
elif p[2] == '>=':
p[0] = Value(p[1]) >= Value(p[3])
elif p[2] == '==':
p[0] = Value(p[1]) == Value(p[3])
elif p[2] == '!=':
p[0] = Value(p[1]) != Value(p[3])
elif p[2] == '&':
p[0] = Value(p[1]) & Value(p[3])
elif p[2] == '^':
p[0] = Value(p[1]) ^ Value(p[3])
elif p[2] == '|':
p[0] = Value(p[1]) | Value(p[3])
elif p[2] == '&&':
p[0] = Value(1) if (Value(p[1]).value()!=0 and Value(p[3]).value()!=0) else Value(0)
elif p[2] == '||':
p[0] = Value(1) if (Value(p[1]).value()!=0 or Value(p[3]).value()!=0) else Value(0)
elif p[2] == ',':
p[0] = Value(p[3])
except Exception as e:
p[0] = Value(0, exception = e)</code></pre>
</details>
</dd>
<dt id="pcpp.evaluator.p_expression_character"><code class="name flex">
<span>def <span class="ident">p_expression_character</span></span>(<span>p)</span>
</code></dt>
<dd>
<section class="desc">
<dl>
<dt><strong><code>expression</code></strong> : <code>CPP_CHAR</code></dt>
<dd> </dd>
</dl>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def p_expression_character(p):
'expression : CPP_CHAR'
p[0] = Value(p[1])</code></pre>
</details>
</dd>
<dt id="pcpp.evaluator.p_expression_conditional"><code class="name flex">
<span>def <span class="ident">p_expression_conditional</span></span>(<span>p)</span>
</code></dt>
<dd>
<section class="desc">
<dl>
<dt><strong><code>expression</code></strong> : <code>expression</code>
<code>CPP_QUESTION</code> <code>expression</code> <code>CPP_COLON</code>
<code>expression</code></dt>
<dd> </dd>
</dl>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def p_expression_conditional(p):
'expression : expression CPP_QUESTION expression CPP_COLON expression'
try:
# Output type must cast up to unsigned if either input is unsigned
p[0] = Value(p[3]) if (Value(p[1]).value()!=0) else Value(p[5])
try:
p[0] = Value(p[0].value(), unsigned = Value(p[3]).unsigned or Value(p[5]).unsigned)
except:
pass
except Exception as e:
p[0] = Value(0, exception = e)</code></pre>
</details>
</dd>
<dt id="pcpp.evaluator.p_expression_function_call"><code class="name flex">
<span>def <span class="ident">p_expression_function_call</span></span>(<span>p)</span>
</code></dt>
<dd>
<section class="desc">
<dl>
<dt><strong><code>expression</code></strong> : <code>CPP_ID</code>
<code>CPP_LPAREN</code> <code>expression</code> <code>CPP_RPAREN</code></dt>
<dd> </dd>
</dl>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def p_expression_function_call(p):
"expression : CPP_ID CPP_LPAREN expression CPP_RPAREN"
try:
p.lexer.on_function_call(p)
except Exception as e:
p[0] = Value(0, exception = e)</code></pre>
</details>
</dd>
<dt id="pcpp.evaluator.p_expression_group"><code class="name flex">
<span>def <span class="ident">p_expression_group</span></span>(<span>t)</span>
</code></dt>
<dd>
<section class="desc">
<dl>
<dt><strong><code>expression</code></strong> : <code>CPP_LPAREN</code>
<code>expression</code> <code>CPP_RPAREN</code></dt>
<dd> </dd>
</dl>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def p_expression_group(t):
'expression : CPP_LPAREN expression CPP_RPAREN'
t[0] = t[2]</code></pre>
</details>
</dd>
<dt id="pcpp.evaluator.p_expression_identifier"><code class="name flex">
<span>def <span class="ident">p_expression_identifier</span></span>(<span>p)</span>
</code></dt>
<dd>
<section class="desc">
<dl>
<dt><strong><code>expression</code></strong> : <code>CPP_ID</code></dt>
<dd> </dd>
</dl>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def p_expression_identifier(p):
"expression : CPP_ID"
try:
p.lexer.on_identifier(p)
except Exception as e:
p[0] = Value(0, exception = e)</code></pre>
</details>
</dd>
<dt id="pcpp.evaluator.p_expression_number"><code class="name flex">
<span>def <span class="ident">p_expression_number</span></span>(<span>p)</span>
</code></dt>
<dd>
<section class="desc">
<dl>
<dt><strong><code>expression</code></strong> : <code>CPP_INTEGER</code></dt>
<dd> </dd>
</dl>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def p_expression_number(p):
'expression : CPP_INTEGER'
p[0] = Value(p[1])</code></pre>
</details>
</dd>
<dt id="pcpp.evaluator.p_expression_string"><code class="name flex">
<span>def <span class="ident">p_expression_string</span></span>(<span>p)</span>
</code></dt>
<dd>
<section class="desc">
<dl>
<dt><strong><code>expression</code></strong> : <code>CPP_STRING</code></dt>
<dd>| CPP_LESS expression CPP_GREATER</dd>
</dl>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def p_expression_string(p):
"""
expression : CPP_STRING
| CPP_LESS expression CPP_GREATER
"""
p[0] = p[1]</code></pre>
</details>
</dd>
<dt id="pcpp.evaluator.p_expression_uminus"><code class="name flex">
<span>def <span class="ident">p_expression_uminus</span></span>(<span>p)</span>
</code></dt>
<dd>
<section class="desc">
<dl>
<dt><strong><code>expression</code></strong> : <code>CPP_MINUS</code>
<code>expression</code> %<code>prec</code> <code>UMINUS</code></dt>
<dd> </dd>
</dl>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def p_expression_uminus(p):
'expression : CPP_MINUS expression %prec UMINUS'
p[0] = -Value(p[2])</code></pre>
</details>
</dd>
<dt id="pcpp.evaluator.p_expression_unop"><code class="name flex">
<span>def <span class="ident">p_expression_unop</span></span>(<span>p)</span>
</code></dt>
<dd>
<section class="desc">
<dl>
<dt><strong><code>expression</code></strong> : <code>CPP_EXCLAMATION</code>
<code>expression</code></dt>
<dd>| CPP_TILDE expression</dd>
</dl>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def p_expression_unop(p):
"""
expression : CPP_EXCLAMATION expression
| CPP_TILDE expression
"""
try:
if p[1] == '!':
p[0] = Value(0) if (Value(p[2]).value()!=0) else Value(1)
elif p[1] == '~':
p[0] = ~Value(p[2])
except Exception as e:
p[0] = Value(0, exception = e)</code></pre>
</details>
</dd>
<dt id="pcpp.evaluator.p_expression_uplus"><code class="name flex">
<span>def <span class="ident">p_expression_uplus</span></span>(<span>p)</span>
</code></dt>
<dd>
<section class="desc">
<dl>
<dt><strong><code>expression</code></strong> : <code>CPP_PLUS</code>
<code>expression</code> %<code>prec</code> <code>UPLUS</code></dt>
<dd> </dd>
</dl>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def p_expression_uplus(p):
'expression : CPP_PLUS expression %prec UPLUS'
p[0] = +Value(p[2])</code></pre>
</details>
</dd>
</dl>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="pcpp.evaluator.Evaluator"><code class="flex name class">
<span>class <span class="ident">Evaluator</span></span>
</code></dt>
<dd>
<section class="desc">
<p>Evaluator of #if C preprocessor expressions.</p>
<pre><code>>>> e = Evaluator()
>>> e('5')
Value(5)
>>> e('5+6')
Value(11)
>>> e('5+6*2')
Value(17)
>>> e('5/2+6*2')
Value(14)
>>> e('5 < 6 <= 7')
Value(1)
>>> e('5 < 6 && 8 > 7')
Value(1)
>>> e('18446744073709551615 == -1')
Value(1)
>>> e('-9223372036854775809 == 9223372036854775807')
Value(1)
>>> e('-1 < 0U')
Value(0U)
>>> e('(( 0L && 0) || (!0L && !0 ))')
Value(1)
>>> e('(1)?2:3')
Value(2)
>>> e('(1 ? -1 : 0) <= 0')
Value(1)
>>> e('(1 ? -1 : 0U)') # Output type of ? must be common between both choices
Value(18446744073709551615U)
>>> e('(1 ? -1 : 0U) <= 0')
Value(0U)
>>> e('1 && 10 / 0') # doctest: +ELLIPSIS
Exception(ZeroDivisionError('division by zero'...
>>> e('0 && 10 / 0') # && must shortcut
Value(0)
>>> e('1 ? 10 / 0 : 0') # doctest: +ELLIPSIS
Exception(ZeroDivisionError('division by zero'...
>>> e('0 ? 10 / 0 : 0') # ? must shortcut
Value(0)
>>> e('(3 ^ 5) != 6 || (3 | 5) != 7 || (3 & 5) != 1')
Value(0)
>>> e('1 << 2 != 4 || 8 >> 1 != 4')
Value(0)
>>> e('(2 || 3) != 1 || (2 && 3) != 1 || (0 || 4) != 1 || (0 && 5) != 0')
Value(0)
>>> e('-1 << 3U > 0')
Value(0)
>>> e("'N' == 78")
Value(1)
>>> e('0x3f == 63')
Value(1)
>>> e("'\\n'")
Value(10)
>>> e("'\\\\'")
Value(92)
>>> e("'\\n' == 0xA")
Value(1)
>>> e("'\\\\' == 0x5c")
Value(1)
>>> e("L'\\0' == 0")
Value(1)
>>> e('12 == 12')
Value(1)
>>> e('12L == 12')
Value(1)
>>> e('-1 >= 0U')
Value(1U)
>>> e('(1<<2) == 4')
Value(1)
>>> e('(-!+!9) == -1')
Value(1)
>>> e('(2 || 3) == 1')
Value(1)
>>> e('1L * 3 != 3')
Value(0)
>>> e('(!1L != 0) || (-1L != -1)')
Value(0)
>>> e('0177777 == 65535')
Value(1)
>>> e('0Xffff != 65535 || 0XFfFf == 65535')
Value(1)
>>> e('0L != 0 || 0l != 0')
Value(0)
>>> e('1U != 1 || 1u == 1')
Value(1)
>>> e('0 <= -1')
Value(0)
>>> e('1 << 2 != 4 || 8 >> 1 == 4')
Value(1)
>>> e('(3 ^ 5) == 6')
Value(1)
>>> e('(3 | 5) == 7')
Value(1)
>>> e('(3 & 5) == 1')
Value(1)
>>> e('(3 ^ 5) != 6 || (3 | 5) != 7 || (3 & 5) != 1')
Value(0)
>>> e('(0 ? 1 : 2) != 2')
Value(0)
>>> e('-1 << 3U > 0')
Value(0)
>>> e('0 && 10 / 0')
Value(0)
>>> e('not_defined && 10 / not_defined') # doctest: +ELLIPSIS
Exception(SyntaxError('Unknown identifier not_defined'...
>>> e('0 && 10 / 0 > 1')
Value(0)
>>> e('(0) ? 10 / 0 : 0')
Value(0)
>>> e('0 == 0 || 10 / 0 > 1')
Value(1)
>>> e('(15 >> 2 >> 1 != 1) || (3 << 2 << 1 != 24)')
Value(0)
>>> e('(1 | 2) == 3 && 4 != 5 || 0')
Value(1)
>>> e('1 > 0')
Value(1)
>>> e("'S' != 83")
Value(0)
>>> e("'' != ''")
Value(0)
>>> e('0 + (1 - (2 + (3 - (4 + (5 - (6 + (7 - (8 + (9 - (10 + (11 - (12 + (13 - (14 + (15 - (16 + (17 - (18 + (19 - (20 + (21 - (22 + (23 - (24 + (25 - (26 + (27 - (28 + (29 - (30 + (31 - (32 + 0)))))))))) )))))))))))))))))))))) == 0')
Value(1)
>>> e('test_function(X)', functions={'test_function':lambda x: 55})
Value(55)
>>> e('test_identifier', identifiers={'test_identifier':11})
Value(11)
>>> e('defined(X)', functions={'defined':lambda x: 55})
Value(55)
>>> e('defined(X)') # doctest: +ELLIPSIS
Exception(SyntaxError('Unknown function defined'...
>>> e('__has_include("variant")') # doctest: +ELLIPSIS
Exception(SyntaxError('Unknown function __has_include'...
>>> e('__has_include(<variant>)') # doctest: +ELLIPSIS
Exception(SyntaxError('Unknown function __has_include'...
>>> e('5 // comment')
Value(5)
>>> e('5 /* comment */')
Value(5)
>>> e('5 /* comment // more */')
Value(5)
>>> e('5 // /* comment */')
</code></pre>
<p>Value(5)</p>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">class Evaluator(object):
"""Evaluator of #if C preprocessor expressions.
>>> e = Evaluator()
>>> e('5')
Value(5)
>>> e('5+6')
Value(11)
>>> e('5+6*2')
Value(17)
>>> e('5/2+6*2')
Value(14)
>>> e('5 < 6 <= 7')
Value(1)
>>> e('5 < 6 && 8 > 7')
Value(1)
>>> e('18446744073709551615 == -1')
Value(1)
>>> e('-9223372036854775809 == 9223372036854775807')
Value(1)
>>> e('-1 < 0U')
Value(0U)
>>> e('(( 0L && 0) || (!0L && !0 ))')
Value(1)
>>> e('(1)?2:3')
Value(2)
>>> e('(1 ? -1 : 0) <= 0')
Value(1)
>>> e('(1 ? -1 : 0U)') # Output type of ? must be common between both choices
Value(18446744073709551615U)
>>> e('(1 ? -1 : 0U) <= 0')
Value(0U)
>>> e('1 && 10 / 0') # doctest: +ELLIPSIS
Exception(ZeroDivisionError('division by zero'...
>>> e('0 && 10 / 0') # && must shortcut
Value(0)
>>> e('1 ? 10 / 0 : 0') # doctest: +ELLIPSIS
Exception(ZeroDivisionError('division by zero'...
>>> e('0 ? 10 / 0 : 0') # ? must shortcut
Value(0)
>>> e('(3 ^ 5) != 6 || (3 | 5) != 7 || (3 & 5) != 1')
Value(0)
>>> e('1 << 2 != 4 || 8 >> 1 != 4')
Value(0)
>>> e('(2 || 3) != 1 || (2 && 3) != 1 || (0 || 4) != 1 || (0 && 5) != 0')
Value(0)
>>> e('-1 << 3U > 0')
Value(0)
>>> e("'N' == 78")
Value(1)
>>> e('0x3f == 63')
Value(1)
>>> e("'\\\\n'")
Value(10)
>>> e("'\\\\\\\\'")
Value(92)
>>> e("'\\\\n' == 0xA")
Value(1)
>>> e("'\\\\\\\\' == 0x5c")
Value(1)
>>> e("L'\\\\0' == 0")
Value(1)
>>> e('12 == 12')
Value(1)
>>> e('12L == 12')
Value(1)
>>> e('-1 >= 0U')
Value(1U)
>>> e('(1<<2) == 4')
Value(1)
>>> e('(-!+!9) == -1')
Value(1)
>>> e('(2 || 3) == 1')
Value(1)
>>> e('1L * 3 != 3')
Value(0)
>>> e('(!1L != 0) || (-1L != -1)')
Value(0)
>>> e('0177777 == 65535')
Value(1)
>>> e('0Xffff != 65535 || 0XFfFf == 65535')
Value(1)
>>> e('0L != 0 || 0l != 0')
Value(0)
>>> e('1U != 1 || 1u == 1')
Value(1)
>>> e('0 <= -1')
Value(0)
>>> e('1 << 2 != 4 || 8 >> 1 == 4')
Value(1)
>>> e('(3 ^ 5) == 6')
Value(1)
>>> e('(3 | 5) == 7')
Value(1)
>>> e('(3 & 5) == 1')
Value(1)
>>> e('(3 ^ 5) != 6 || (3 | 5) != 7 || (3 & 5) != 1')
Value(0)
>>> e('(0 ? 1 : 2) != 2')
Value(0)
>>> e('-1 << 3U > 0')
Value(0)
>>> e('0 && 10 / 0')
Value(0)
>>> e('not_defined && 10 / not_defined') # doctest: +ELLIPSIS
Exception(SyntaxError('Unknown identifier not_defined'...
>>> e('0 && 10 / 0 > 1')
Value(0)
>>> e('(0) ? 10 / 0 : 0')
Value(0)
>>> e('0 == 0 || 10 / 0 > 1')
Value(1)
>>> e('(15 >> 2 >> 1 != 1) || (3 << 2 << 1 != 24)')
Value(0)
>>> e('(1 | 2) == 3 && 4 != 5 || 0')
Value(1)
>>> e('1 > 0')
Value(1)
>>> e("'\123' != 83")
Value(0)
>>> e("'\x1b' != '\033'")
Value(0)
>>> e('0 + (1 - (2 + (3 - (4 + (5 - (6 + (7 - (8 + (9 - (10 + (11 - (12 + (13 - (14 + (15 - (16 + (17 - (18 + (19 - (20 + (21 - (22 + (23 - (24 + (25 - (26 + (27 - (28 + (29 - (30 + (31 - (32 + 0)))))))))) )))))))))))))))))))))) == 0')
Value(1)
>>> e('test_function(X)', functions={'test_function':lambda x: 55})
Value(55)
>>> e('test_identifier', identifiers={'test_identifier':11})
Value(11)
>>> e('defined(X)', functions={'defined':lambda x: 55})
Value(55)
>>> e('defined(X)') # doctest: +ELLIPSIS
Exception(SyntaxError('Unknown function defined'...
>>> e('__has_include("variant")') # doctest: +ELLIPSIS
Exception(SyntaxError('Unknown function __has_include'...
>>> e('__has_include(<variant>)') # doctest: +ELLIPSIS
Exception(SyntaxError('Unknown function __has_include'...
>>> e('5 // comment')
Value(5)
>>> e('5 /* comment */')
Value(5)
>>> e('5 /* comment // more */')
Value(5)
>>> e('5 // /* comment */')
Value(5)
"""
# >>> e('defined X', functions={'defined':lambda x: 55})
# Value(55)
def __init__(self, lexer = None):
self.lexer = lexer if lexer is not None else default_lexer()
self.parser = yacc.yacc(optimize=in_production,debug=not in_production,write_tables=not in_production)
class __lexer(object):
def __init__(self, functions, identifiers):
self.__toks = []
self.__functions = functions
self.__identifiers = identifiers
def input(self, toks):
self.__toks = [tok for tok in toks if tok.type != 'CPP_WS' and tok.type != 'CPP_LINECONT' and tok.type != 'CPP_COMMENT1' and tok.type != 'CPP_COMMENT2']
self.__idx = 0
def token(self):
if self.__idx >= len(self.__toks):
return None
self.__idx = self.__idx + 1
return self.__toks[self.__idx - 1]
def on_function_call(self, p):
if p[1] not in self.__functions:
raise SyntaxError('Unknown function %s' % p[1])
p[0] = Value(self.__functions[p[1]](p[3]))
def on_identifier(self, p):
if p[1] not in self.__identifiers:
raise SyntaxError('Unknown identifier %s' % p[1])
p[0] = Value(self.__identifiers[p[1]])
def __call__(self, input, functions = {}, identifiers = {}):
"""Execute a fully macro expanded set of tokens representing an expression,
returning the result of the evaluation.
"""
if not isinstance(input,list):
self.lexer.input(input)
input = []
while True:
tok = self.lexer.token()
if not tok:
break
input.append(tok)
return self.parser.parse(input, lexer = self.__lexer(functions, identifiers))</code></pre>
</details>
<h3>Methods</h3>
<dl>
<dt id="pcpp.evaluator.Evaluator.__init__"><code class="name flex">
<span>def <span class="ident">__init__</span></span>(<span>self, lexer=None)</span>
</code></dt>
<dd>
<section class="desc">
<p>Initialize self.
See help(type(self)) for accurate signature.</p>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def __init__(self, lexer = None):
self.lexer = lexer if lexer is not None else default_lexer()
self.parser = yacc.yacc(optimize=in_production,debug=not in_production,write_tables=not in_production)</code></pre>
</details>
</dd>
</dl>
</dd>
<dt id="pcpp.evaluator.Value"><code class="flex name class">
<span>class <span class="ident">Value</span></span>
<span>(</span><span><small>ancestors:</small> builtins.int)</span>
</code></dt>
<dd>
<section class="desc">
<p>A signed or unsigned integer within a preprocessor expression, bounded
to within INT_MIN and INT_MAX, or 0 and UINT_MAX. Signed overflow is handled
like a two's complement CPU, despite being UB, as that's what GCC and clang do.</p>
<pre><code>>>> Value(5)
Value(5)
>>> Value('5L')
Value(5)
>>> Value('5U')
Value(5U)
>>> Value('0')
Value(0)
>>> Value('0U')
Value(0U)
>>> Value('-1U')
Value(18446744073709551615U)
>>> Value(5) * Value(2)
Value(10)
>>> Value(5) + Value('2u')
Value(7U)
>>> Value(5) * 2
Value(10)
>>> Value(5) / 2 # Must return integer
Value(2)
>>> Value(50) % 8
Value(2)
>>> -Value(5)
Value(-5)
>>> +Value(-5)
Value(-5)
>>> ~Value(5)
Value(-6)
>>> Value(6) & 2
Value(2)
>>> Value(4) | 2
Value(6)
>>> Value(6) ^ 2
Value(4)
>>> Value(2) << 2
Value(8)
>>> Value(8) >> 2
Value(2)
>>> Value(9223372036854775808)
Value(-9223372036854775808)
>>> Value(-9223372036854775809)
Value(9223372036854775807)
>>> Value(18446744073709551615)
Value(-1)
>>> Value(False)
Value(0)
>>> Value(True)
Value(1)
>>> Value(5) == Value(6)
Value(0)
>>> Value(5) == Value(5)
Value(1)
>>> not Value(2)
Traceback (most recent call last):
</code></pre>
<p>…
AssertionError</p>
<pre><code>>>> Value(4) and Value(2)
Traceback (most recent call last):
</code></pre>
<p>…
AssertionError</p>
<pre><code>>>> Value(5) and not Value(6)
Traceback (most recent call last):
</code></pre>
<p>…
AssertionError</p>
<pre><code>>>> Value('0x3f')
Value(63)
>>> Value('077')
Value(63)
>>> Value("'N'")
Value(78)
>>> Value("L'N'")
Value(78)
>>> Value("'\n'")
Value(10)
>>> Value("'\\n'")
Value(10)
>>> Value("'\\'")
Value(92)
>>> Value("'\'")
Traceback (most recent call last):
</code></pre>
<dl>
<dt>…</dt>
<dt><strong><code>SyntaxError</code></strong> : <code>Empty</code>
<code>character</code> <code>escape</code> <code>sequence</code></dt>
<dd> </dd>
</dl>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">class Value(INTBASETYPE):
"""A signed or unsigned integer within a preprocessor expression, bounded
to within INT_MIN and INT_MAX, or 0 and UINT_MAX. Signed overflow is handled
like a two's complement CPU, despite being UB, as that's what GCC and clang do.
>>> Value(5)
Value(5)
>>> Value('5L')
Value(5)
>>> Value('5U')
Value(5U)
>>> Value('0')
Value(0)
>>> Value('0U')
Value(0U)
>>> Value('-1U')
Value(18446744073709551615U)
>>> Value(5) * Value(2)
Value(10)
>>> Value(5) + Value('2u')
Value(7U)
>>> Value(5) * 2
Value(10)
>>> Value(5) / 2 # Must return integer
Value(2)
>>> Value(50) % 8
Value(2)
>>> -Value(5)
Value(-5)
>>> +Value(-5)
Value(-5)
>>> ~Value(5)
Value(-6)
>>> Value(6) & 2
Value(2)
>>> Value(4) | 2
Value(6)
>>> Value(6) ^ 2
Value(4)
>>> Value(2) << 2
Value(8)
>>> Value(8) >> 2
Value(2)
>>> Value(9223372036854775808)
Value(-9223372036854775808)
>>> Value(-9223372036854775809)
Value(9223372036854775807)
>>> Value(18446744073709551615)
Value(-1)
>>> Value(False)
Value(0)
>>> Value(True)
Value(1)
>>> Value(5) == Value(6)
Value(0)
>>> Value(5) == Value(5)
Value(1)
>>> not Value(2)
Traceback (most recent call last):
...
AssertionError
>>> Value(4) and Value(2)
Traceback (most recent call last):
...
AssertionError
>>> Value(5) and not Value(6)
Traceback (most recent call last):
...
AssertionError
>>> Value('0x3f')
Value(63)
>>> Value('077')
Value(63)
>>> Value("'N'")
Value(78)
>>> Value("L'N'")
Value(78)
>>> Value("'\\n'")
Value(10)
>>> Value("'\\\\n'")
Value(10)
>>> Value("'\\\\'")
Value(92)
>>> Value("'\\'")
Traceback (most recent call last):
...
SyntaxError: Empty character escape sequence
"""
INT_MIN = -(1 << (INTMAXBITS - 1))
INT_MAX = (1 << (INTMAXBITS - 1)) - 1
INT_MASK = (1 << INTMAXBITS) - 1
UINT_MIN = 0
UINT_MAX = (1 << INTMAXBITS) - 1
@classmethod
def __sclamp(cls, value):
value = INTBASETYPE(value)
return ((value - cls.INT_MIN) & cls.INT_MASK) + cls.INT_MIN
@classmethod
def __uclamp(cls, value):
value = INTBASETYPE(value)
return value & cls.UINT_MAX
def __new__(cls, value, unsigned = False, exception = None):
if isinstance(value, Value):
unsigned = value.unsigned
exception = value.exception
elif isinstance(value, INTBASETYPE) or isinstance(value, int) or isinstance(value, float):
value = cls.__uclamp(value) if unsigned else cls.__sclamp(value)
elif isinstance(value, STRING_TYPES):
if (value.startswith("L'") or value[0] == "'") and value[-1] == "'":
startidx = 2 if value.startswith("L'") else 1
#print("1. ***", value, file = sys.stderr)
value = value[startidx:-1]
if len(value) == 0:
raise SyntaxError('Empty character escape sequence')
#print("2. ***", value, file = sys.stderr)
value = _expand_escape_sequences_pat.sub(lambda x: codecs.decode(x.group(0), 'unicode-escape'), value)
#print("3. ***", value, file = sys.stderr)
x = INTBASETYPE(ord(value))
#print("4. ***", x, file = sys.stderr)
elif value.startswith('0x') or value.startswith('0X'):
# Strip any terminators
while not ((value[-1] >= '0' and value[-1] <= '9') or (value[-1] >= 'a' and value[-1] <= 'f') or (value[-1] >= 'A' and value[-1] <= 'F')):
if value[-1] == 'u' or value[-1] == 'U':
unsigned = True
value = value[:-1]
x = INTBASETYPE(value, base = 16)
elif value.startswith('0'):
# Strip any terminators
while not (value[-1] >= '0' and value[-1] <= '7'):
if value[-1] == 'u' or value[-1] == 'U':
unsigned = True
value = value[:-1]
x = INTBASETYPE(value, base = 8)
else:
# Strip any terminators
while not (value[-1] >= '0' and value[-1] <= '9'):
if value[-1] == 'u' or value[-1] == 'U':
unsigned = True
value = value[:-1]
x = INTBASETYPE(value)
value = cls.__uclamp(x) if unsigned else cls.__sclamp(x)
#assert x == value
else:
print('Unknown value type: %s' % repr(type(value)), file = sys.stderr)
assert False # Input is an unrecognised type
inst = super(Value, cls).__new__(cls, value)
inst.unsigned = unsigned
inst.exception = exception
return inst
def value(self):
if self.exception is not None:
raise self.exception
return INTBASETYPE(self)
def __add__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) + self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(super(Value, self).__add__(other))
def __sub__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) - self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(super(Value, self).__sub__(other))
def __mul__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) * self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(super(Value, self).__mul__(other))
def __div__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) / self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(super(Value, self).__div__(other))
def __truediv__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) / self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(super(Value, self).__truediv__(other))
def __mod__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) % self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(super(Value, self).__mod__(other))
def __neg__(self):
if self.exception is not None:
return self
return Value(super(Value, self).__neg__(), self.unsigned)
def __invert__(self):
if self.exception is not None:
return self
return Value(super(Value, self).__invert__(), self.unsigned)
def __and__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) & self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(super(Value, self).__and__(other))
def __or__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) | self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(super(Value, self).__or__(other))
def __pos__(self):
if self.exception is not None:
return self
return Value(super(Value, self).__pos__())
def __pow__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) ** self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(super(Value, self).__pow__(other))
def __lshift__(self, other):
if self.exception is not None:
return self
# Ignore other signedness
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) << self.__uclamp(other), True) if (self.unsigned) else Value(super(Value, self).__lshift__(other))
def __rshift__(self, other):
if self.exception is not None:
return self
# Ignore other signedness
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) >> self.__uclamp(other), True) if (self.unsigned) else Value(super(Value, self).__rshift__(other))
def __xor__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) ^ self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(super(Value, self).__xor__(other))
def __repr__(self):
if self.exception is not None:
return "Exception(%s)" % repr(self.exception)
elif self.unsigned:
return "Value(%dU)" % INTBASETYPE(self)
else:
return "Value(%d)" % INTBASETYPE(self)
def __bool__(self):
assert False # Do not use Python logical operations
def __nonzero__(self):
assert False # Do not use Python logical operations
def __cmp__(self, other):
assert False
def __lt__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) < self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(self.__sclamp(self) < self.__sclamp(other), False)
def __le__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) <= self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(self.__sclamp(self) <= self.__sclamp(other), False)
def __eq__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) == self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(self.__sclamp(self) == self.__sclamp(other), False)
def __ne__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) != self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(self.__sclamp(self) != self.__sclamp(other), False)
def __ge__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) >= self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(self.__sclamp(self) >= self.__sclamp(other), False)
def __gt__(self, other):
if self.exception is not None:
return self
other = Value(other)
if other.exception is not None:
return other
return Value(self.__uclamp(self) > self.__uclamp(other), True) if (self.unsigned or other.unsigned) else Value(self.__sclamp(self) > self.__sclamp(other), False)</code></pre>
</details>
<h3>Class variables</h3>
<dl>
<dt id="pcpp.evaluator.Value.INT_MASK"><code
class="name">var <span class="ident">INT_MASK</span></code></dt>
<dd>
<section class="desc"></section>
</dd>
<dt id="pcpp.evaluator.Value.INT_MAX"><code
class="name">var <span class="ident">INT_MAX</span></code></dt>
<dd>
<section class="desc"></section>
</dd>
<dt id="pcpp.evaluator.Value.INT_MIN"><code
class="name">var <span class="ident">INT_MIN</span></code></dt>
<dd>
<section class="desc"></section>
</dd>
<dt id="pcpp.evaluator.Value.UINT_MAX"><code
class="name">var <span class="ident">UINT_MAX</span></code></dt>
<dd>
<section class="desc"></section>
</dd>
<dt id="pcpp.evaluator.Value.UINT_MIN"><code
class="name">var <span class="ident">UINT_MIN</span></code></dt>
<dd>
<section class="desc"></section>
</dd>
</dl>
<h3>Methods</h3>
<dl>
<dt id="pcpp.evaluator.Value.value"><code class="name flex">
<span>def <span class="ident">value</span></span>(<span>self)</span>
</code></dt>
<dd>
<section class="desc"></section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def value(self):
if self.exception is not None:
raise self.exception
return INTBASETYPE(self)</code></pre>
</details>
</dd>
</dl>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li>
<h3>Super-module</h3>
<ul>
<li><code><a title="pcpp" href="index.html">pcpp</a></code></li>
</ul>
</li>
<li>
<h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="pcpp.evaluator.p_error" href="#pcpp.evaluator.p_error">p_error</a></code>
</li>
<li><code><a title="pcpp.evaluator.p_expression_binop" href="#pcpp.evaluator.p_expression_binop">p_expression_binop</a></code>
</li>
<li><code><a title="pcpp.evaluator.p_expression_character" href="#pcpp.evaluator.p_expression_character">p_expression_character</a></code>
</li>
<li><code><a title="pcpp.evaluator.p_expression_conditional" href="#pcpp.evaluator.p_expression_conditional">p_expression_conditional</a></code>
</li>
<li><code><a title="pcpp.evaluator.p_expression_function_call" href="#pcpp.evaluator.p_expression_function_call">p_expression_function_call</a></code>
</li>
<li><code><a title="pcpp.evaluator.p_expression_group" href="#pcpp.evaluator.p_expression_group">p_expression_group</a></code>
</li>
<li><code><a title="pcpp.evaluator.p_expression_identifier" href="#pcpp.evaluator.p_expression_identifier">p_expression_identifier</a></code>
</li>
<li><code><a title="pcpp.evaluator.p_expression_number" href="#pcpp.evaluator.p_expression_number">p_expression_number</a></code>
</li>
<li><code><a title="pcpp.evaluator.p_expression_string" href="#pcpp.evaluator.p_expression_string">p_expression_string</a></code>
</li>
<li><code><a title="pcpp.evaluator.p_expression_uminus" href="#pcpp.evaluator.p_expression_uminus">p_expression_uminus</a></code>
</li>
<li><code><a title="pcpp.evaluator.p_expression_unop" href="#pcpp.evaluator.p_expression_unop">p_expression_unop</a></code>
</li>
<li><code><a title="pcpp.evaluator.p_expression_uplus" href="#pcpp.evaluator.p_expression_uplus">p_expression_uplus</a></code>
</li>
</ul>
</li>
<li>
<h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="pcpp.evaluator.Evaluator" href="#pcpp.evaluator.Evaluator">Evaluator</a></code>
</h4>
<ul class="">
<li><code><a title="pcpp.evaluator.Evaluator.__init__" href="#pcpp.evaluator.Evaluator.__init__">__init__</a></code>
</li>
</ul>
</li>
<li>
<h4><code><a title="pcpp.evaluator.Value" href="#pcpp.evaluator.Value">Value</a></code></h4>
<ul class="two-column">
<li><code><a title="pcpp.evaluator.Value.INT_MASK" href="#pcpp.evaluator.Value.INT_MASK">INT_MASK</a></code>
</li>
<li><code><a title="pcpp.evaluator.Value.INT_MAX" href="#pcpp.evaluator.Value.INT_MAX">INT_MAX</a></code>
</li>
<li><code><a title="pcpp.evaluator.Value.INT_MIN" href="#pcpp.evaluator.Value.INT_MIN">INT_MIN</a></code>
</li>
<li><code><a title="pcpp.evaluator.Value.UINT_MAX" href="#pcpp.evaluator.Value.UINT_MAX">UINT_MAX</a></code>
</li>
<li><code><a title="pcpp.evaluator.Value.UINT_MIN" href="#pcpp.evaluator.Value.UINT_MIN">UINT_MIN</a></code>
</li>
<li><code><a title="pcpp.evaluator.Value.value" href="#pcpp.evaluator.Value.value">value</a></code>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.5.3</a>.</p>
</footer>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad()</script>
</body>
</html>
================================================
FILE: doc/index.html
================================================
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.5.3" />
<title>pcpp API documentation</title>
<meta name="description" content="" />
<link href='https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.0/normalize.min.css' rel='stylesheet'>
<link href='https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/8.0.0/sanitize.min.css' rel='stylesheet'>
<link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github.min.css" rel="stylesheet">
<style>.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{font-weight:bold}#index h4 + ul{margin-bottom:.6em}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.name small{font-weight:normal}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase;cursor:pointer}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}.admonition{padding:.1em .5em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title"><code>pcpp</code> module</h1>
</header>
<section id="section-intro">
<details class="source">
<summary>Source code</summary>
<pre><code class="python">from .evaluator import Evaluator
from .parser import Action, OutputDirective
from .pcmd import main, version, CmdPreprocessor
from .preprocessor import Preprocessor
__version__ = version</code></pre>
</details>
</section>
<section>
<h2 class="section-title" id="header-submodules">Sub-modules</h2>
<dl>
<dt><code class="name"><a title="pcpp.evaluator" href="evaluator.html">pcpp.evaluator</a></code></dt>
<dd>
<section class="desc"></section>
</dd>
<dt><code class="name"><a title="pcpp.lextab" href="lextab.html">pcpp.lextab</a></code></dt>
<dd>
<section class="desc"></section>
</dd>
<dt><code class="name"><a title="pcpp.parser" href="parser.html">pcpp.parser</a></code></dt>
<dd>
<section class="desc"></section>
</dd>
<dt><code class="name"><a title="pcpp.parsetab" href="parsetab.html">pcpp.parsetab</a></code></dt>
<dd>
<section class="desc"></section>
</dd>
<dt><code class="name"><a title="pcpp.pcmd" href="pcmd.html">pcpp.pcmd</a></code></dt>
<dd>
<section class="desc"></section>
</dd>
<dt><code class="name"><a title="pcpp.preprocessor" href="preprocessor.html">pcpp.preprocessor</a></code></dt>
<dd>
<section class="desc"></section>
</dd>
</dl>
</section>
<section>
</section>
<section>
</section>
<section>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3><a href="#header-submodules">Sub-modules</a></h3>
<ul>
<li><code><a title="pcpp.evaluator" href="evaluator.html">pcpp.evaluator</a></code></li>
<li><code><a title="pcpp.lextab" href="lextab.html">pcpp.lextab</a></code></li>
<li><code><a title="pcpp.parser" href="parser.html">pcpp.parser</a></code></li>
<li><code><a title="pcpp.parsetab" href="parsetab.html">pcpp.parsetab</a></code></li>
<li><code><a title="pcpp.pcmd" href="pcmd.html">pcpp.pcmd</a></code></li>
<li><code><a title="pcpp.preprocessor" href="preprocessor.html">pcpp.preprocessor</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.5.3</a>.</p>
</footer>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad()</script>
</body>
</html>
================================================
FILE: doc/lextab.html
================================================
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.5.3" />
<title>pcpp.lextab API documentation</title>
<meta name="description" content="" />
<link href='https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.0/normalize.min.css' rel='stylesheet'>
<link href='https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/8.0.0/sanitize.min.css' rel='stylesheet'>
<link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github.min.css" rel="stylesheet">
<style>.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{font-weight:bold}#index h4 + ul{margin-bottom:.6em}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.name small{font-weight:normal}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase;cursor:pointer}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}.admonition{padding:.1em .5em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title"><code>pcpp.lextab</code> module</h1>
</header>
<section id="section-intro">
<details class="source">
<summary>Source code</summary>
<pre><code class="python"># lextab.py. This file automatically created by PLY (version 3.11). Don't edit!
_tabversion = '3.10'
_lextokens = set(('CPP_AMPERSAND', 'CPP_ANDEQUAL', 'CPP_BAR', 'CPP_BSLASH', 'CPP_CHAR', 'CPP_COLON', 'CPP_COMMA', 'CPP_COMMENT1', 'CPP_COMMENT2', 'CPP_DEREFERENCE', 'CPP_DIVIDEEQUAL', 'CPP_DOT', 'CPP_DPOUND', 'CPP_DQUOTE', 'CPP_EQUAL', 'CPP_EQUALITY', 'CPP_EXCLAMATION', 'CPP_FLOAT', 'CPP_FSLASH', 'CPP_GREATER', 'CPP_GREATEREQUAL', 'CPP_HAT', 'CPP_ID', 'CPP_INEQUALITY', 'CPP_INTEGER', 'CPP_LBRACKET', 'CPP_LCURLY', 'CPP_LESS', 'CPP_LESSEQUAL', 'CPP_LINECONT', 'CPP_LOGICALAND', 'CPP_LOGICALOR', 'CPP_LPAREN', 'CPP_LSHIFT', 'CPP_LSHIFTEQUAL', 'CPP_MINUS', 'CPP_MINUSEQUAL', 'CPP_MINUSMINUS', 'CPP_MULTIPLYEQUAL', 'CPP_OREQUAL', 'CPP_PERCENT', 'CPP_PERCENTEQUAL', 'CPP_PLUS', 'CPP_PLUSEQUAL', 'CPP_PLUSPLUS', 'CPP_POUND', 'CPP_QUESTION', 'CPP_RBRACKET', 'CPP_RCURLY', 'CPP_RPAREN', 'CPP_RSHIFT', 'CPP_RSHIFTEQUAL', 'CPP_SEMICOLON', 'CPP_SQUOTE', 'CPP_STAR', 'CPP_STRING', 'CPP_TILDE', 'CPP_WS', 'CPP_XOREQUAL'))
_lexreflags = 64
_lexliterals = '+-*/%|&~^<>=!?()[]{}.,;:\\\'"'
_lexstateinfo = {'INITIAL': 'inclusive'}
_lexstatere = {'INITIAL': [('(?P<t_CPP_WS>([ \\t]+|\\n))|(?P<t_CPP_LINECONT>\\\\[ \\t]*\\n)|(?P<t_CPP_INTEGER>(((((0x)|(0X))[0-9a-fA-F]+)|(\\d+))([uU][lL]|[lL][uU]|[uU]|[lL])?))|(?P<t_CPP_STRING>\\"([^\\\\\\n]|(\\\\(.|\\n)))*?\\")|(?P<t_CPP_CHAR>(L)?\\\'([^\\\\\\n]|(\\\\(.|\\n)))*?\\\')|(?P<t_CPP_COMMENT1>(/\\*(.|\\n)*?\\*/))|(?P<t_CPP_COMMENT2>(//[^\\n]*))|(?P<t_CPP_FLOAT>((\\d+)(\\.\\d+)(e(\\+|-)?(\\d+))?|(\\d+)e(\\+|-)?(\\d+))([lL]|[fF])?)|(?P<t_CPP_ID>[A-Za-z_][\\w_]*)|(?P<t_CPP_LOGICALOR>\\|\\|)|(?P<t_CPP_PLUSPLUS>\\+\\+)|(?P<t_CPP_DPOUND>\\#\\#)|(?P<t_CPP_LSHIFTEQUAL><<=)|(?P<t_CPP_OREQUAL>\\|=)|(?P<t_CPP_PLUSEQUAL>\\+=)|(?P<t_CPP_RSHIFTEQUAL>>>=)|(?P<t_CPP_MULTIPLYEQUAL>\\*=)|(?P<t_CPP_BAR>\\|)|(?P<t_CPP_DIVIDEEQUAL>/=)|(?P<t_CPP_POUND>\\#)|(?P<t_CPP_PERCENTEQUAL>%=)|(?P<t_CPP_DEREFERENCE>->)|(?P<t_CPP_RPAREN>\\))|(?P<t_CPP_ANDEQUAL>&=)|(?P<t_CPP_RBRACKET>\\])|(?P<t_CPP_LPAREN>\\()|(?P<t_CPP_RSHIFT>>>)|(?P<t_CPP_LESSEQUAL><=)|(?P<t_CPP_HAT>\\^)|(?P<t_CPP_LOGICALAND>&&)|(?P<t_CPP_EQUALITY>==)|(?P<t_CPP_GREATEREQUAL>>=)|(?P<t_CPP_BSLASH>\\\\)|(?P<t_CPP_MINUSEQUAL>-=)|(?P<t_CPP_DOT>\\.)|(?P<t_CPP_MINUSMINUS>--)|(?P<t_CPP_LBRACKET>\\[)|(?P<t_CPP_PLUS>\\+)|(?P<t_CPP_XOREQUAL>^=)|(?P<t_CPP_STAR>\\*)|(?P<t_CPP_QUESTION>\\?)|(?P<t_CPP_LSHIFT><<)|(?P<t_CPP_INEQUALITY>!=)|(?P<t_CPP_DQUOTE>")|(?P<t_CPP_MINUS>-)|(?P<t_CPP_RCURLY>})|(?P<t_CPP_GREATER>>)|(?P<t_CPP_LESS><)|(?P<t_CPP_SQUOTE>\')|(?P<t_CPP_EXCLAMATION>!)|(?P<t_CPP_LCURLY>{)|(?P<t_CPP_EQUAL>=)|(?P<t_CPP_FSLASH>/)|(?P<t_CPP_COLON>:)|(?P<t_CPP_AMPERSAND>&)|(?P<t_CPP_COMMA>,)|(?P<t_CPP_TILDE>~)|(?P<t_CPP_SEMICOLON>;)|(?P<t_CPP_PERCENT>%)', [None, ('t_CPP_WS', 'CPP_WS'), None, ('t_CPP_LINECONT', 'CPP_LINECONT'), ('t_CPP_INTEGER', 'CPP_INTEGER'), None, None, None, None, None, None, None, None, ('t_CPP_STRING', 'CPP_STRING'), None, None, None, ('t_CPP_CHAR', 'CPP_CHAR'), None, None, None, None, ('t_CPP_COMMENT1', 'CPP_COMMENT1'), None, None, ('t_CPP_COMMENT2', 'CPP_COMMENT2'), None, (None, 'CPP_FLOAT'), None, None, None, None, None, None, None, None, None, None, (None, 'CPP_ID'), (None, 'CPP_LOGICALOR'), (None, 'CPP_PLUSPLUS'), (None, 'CPP_DPOUND'), (None, 'CPP_LSHIFTEQUAL'), (None, 'CPP_OREQUAL'), (None, 'CPP_PLUSEQUAL'), (None, 'CPP_RSHIFTEQUAL'), (None, 'CPP_MULTIPLYEQUAL'), (None, 'CPP_BAR'), (None, 'CPP_DIVIDEEQUAL'), (None, 'CPP_POUND'), (None, 'CPP_PERCENTEQUAL'), (None, 'CPP_DEREFERENCE'), (None, 'CPP_RPAREN'), (None, 'CPP_ANDEQUAL'), (None, 'CPP_RBRACKET'), (None, 'CPP_LPAREN'), (None, 'CPP_RSHIFT'), (None, 'CPP_LESSEQUAL'), (None, 'CPP_HAT'), (None, 'CPP_LOGICALAND'), (None, 'CPP_EQUALITY'), (None, 'CPP_GREATEREQUAL'), (None, 'CPP_BSLASH'), (None, 'CPP_MINUSEQUAL'), (None, 'CPP_DOT'), (None, 'CPP_MINUSMINUS'), (None, 'CPP_LBRACKET'), (None, 'CPP_PLUS'), (None, 'CPP_XOREQUAL'), (None, 'CPP_STAR'), (None, 'CPP_QUESTION'), (None, 'CPP_LSHIFT'), (None, 'CPP_INEQUALITY'), (None, 'CPP_DQUOTE'), (None, 'CPP_MINUS'), (None, 'CPP_RCURLY'), (None, 'CPP_GREATER'), (None, 'CPP_LESS'), (None, 'CPP_SQUOTE'), (None, 'CPP_EXCLAMATION'), (None, 'CPP_LCURLY'), (None, 'CPP_EQUAL'), (None, 'CPP_FSLASH'), (None, 'CPP_COLON'), (None, 'CPP_AMPERSAND'), (None, 'CPP_COMMA'), (None, 'CPP_TILDE'), (None, 'CPP_SEMICOLON'), (None, 'CPP_PERCENT')])]}
_lexstateignore = {'INITIAL': ''}
_lexstateerrorf = {'INITIAL': 't_error'}
_lexstateeoff = {}</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
</section>
<section>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="pcpp" href="index.html">pcpp</a></code></li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.5.3</a>.</p>
</footer>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad()</script>
</body>
</html>
================================================
FILE: doc/parser.html
================================================
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.5.3" />
<title>pcpp.parser API documentation</title>
<meta name="description" content="" />
<link href='https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.0/normalize.min.css' rel='stylesheet'>
<link href='https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/8.0.0/sanitize.min.css' rel='stylesheet'>
<link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github.min.css" rel="stylesheet">
<style>
.flex {
display: flex !important
}
body {
line-height: 1.5em
}
#content {
padding: 20px
}
#sidebar {
padding: 30px;
overflow: hidden
}
.http-server-breadcrumbs {
font-size: 130%;
margin: 0 0 15px 0
}
#footer {
font-size: .75em;
padding: 5px 30px;
border-top: 1px solid #ddd;
text-align: right
}
#footer p {
margin: 0 0 0 1em;
display: inline-block
}
#footer p:last-child {
margin-right: 30px
}
h1,
h2,
h3,
h4,
h5 {
font-weight: 300
}
h1 {
font-size: 2.5em;
line-height: 1.1em
}
h2 {
font-size: 1.75em;
margin: 1em 0 .50em 0
}
h3 {
font-size: 1.4em;
margin: 25px 0 10px 0
}
h4 {
margin: 0;
font-size: 105%
}
a {
color: #058;
text-decoration: none;
transition: color .3s ease-in-out
}
a:hover {
color: #e82
}
.title code {
font-weight: bold
}
h2[id^="header-"] {
margin-top: 2em
}
.ident {
color: #900
}
pre code {
background: #f8f8f8;
font-size: .8em;
line-height: 1.4em
}
code {
background: #f2f2f1;
padding: 1px 4px;
overflow-wrap: break-word
}
h1 code {
background: transparent
}
pre {
background: #f8f8f8;
border: 0;
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
margin: 1em 0;
padding: 1ex
}
#http-server-module-list {
display: flex;
flex-flow: column
}
#http-server-module-list div {
display: flex
}
#http-server-module-list dt {
min-width: 10%
}
#http-server-module-list p {
margin-top: 0
}
.toc ul,
#index {
list-style-type: none;
margin: 0;
padding: 0
}
#index code {
background: transparent
}
#index h3 {
border-bottom: 1px solid #ddd
}
#index ul {
padding: 0
}
#index h4 {
font-weight: bold
}
#index h4+ul {
margin-bottom: .6em
}
@media (min-width:200ex) {
#index .two-column {
column-count: 2
}
}
@media (min-width:300ex) {
#index .two-column {
column-count: 3
}
}
dl {
margin-bottom: 2em
}
dl dl:last-child {
margin-bottom: 4em
}
dd {
margin: 0 0 1em 3em
}
#header-classes+dl>dd {
margin-bottom: 3em
}
dd dd {
margin-left: 2em
}
dd p {
margin: 10px 0
}
.name {
background: #eee;
font-weight: bold;
font-size: .85em;
padding: 5px 10px;
display: inline-block;
min-width: 40%
}
.name:hover {
background: #e0e0e0
}
.name>span:first-child {
white-space: nowrap
}
.name.class>span:nth-child(2) {
margin-left: .4em
}
.name small {
font-weight: normal
}
.inherited {
color: #999;
border-left: 5px solid #eee;
padding-left: 1em
}
.inheritance em {
font-style: normal;
font-weight: bold
}
.desc h2 {
font-weight: 400;
font-size: 1.25em
}
.desc h3 {
font-size: 1em
}
.desc dt code {
background: inherit
}
.source summary {
color: #666;
text-align: right;
font-weight: 400;
font-size: .8em;
text-transform: uppercase;
cursor: pointer
}
.source pre {
max-height: 500px;
overflow: auto;
margin: 0
}
.source pre code {
font-size: 12px;
overflow: visible
}
.hlist {
list-style: none
}
.hlist li {
display: inline
}
.hlist li:after {
content: ',\2002'
}
.hlist li:last-child:after {
content: none
}
.hlist .hlist {
display: inline;
padding-left: 1em
}
img {
max-width: 100%
}
.admonition {
padding: .1em .5em
}
.admonition-title {
font-weight: bold
}
.admonition.note,
.admonition.info,
.admonition.important {
background: #aef
}
.admonition.todo,
.admonition.versionadded,
.admonition.tip,
.admonition.hint {
background: #dfd
}
.admonition.warning,
.admonition.versionchanged,
.admonition.deprecated {
background: #fd4
}
.admonition.error,
.admonition.danger,
.admonition.caution {
background: lightpink
}
</style>
<style media="screen and (min-width: 700px)">
@media screen and (min-width:700px) {
#sidebar {
width: 30%
}
#content {
width: 70%;
max-width: 100ch;
padding: 3em 4em;
border-left: 1px solid #ddd
}
pre code {
font-size: 1em
}
.item .name {
font-size: 1em
}
main {
display: flex;
flex-direction: row-reverse;
justify-content: flex-end
}
.toc ul ul,
#index ul {
padding-left: 1.5em
}
.toc>ul>li {
margin-top: .5em
}
}
</style>
<style media="print">
@media print {
#sidebar h1 {
page-break-before: always
}
.source {
display: none
}
}
@media print {
* {
background: transparent !important;
color: #000 !important;
box-shadow: none !important;
text-shadow: none !important
}
a[href]:after {
content: " (" attr(href) ")";
font-size: 90%
}
a[href][title]:after {
content: none
}
abbr[title]:after {
content: " (" attr(title) ")"
}
.ir a:after,
a[href^="javascript:"]:after,
a[href^="#"]:after {
content: ""
}
pre,
blockquote {
border: 1px solid #999;
page-break-inside: avoid
}
thead {
display: table-header-group
}
tr,
img {
page-break-inside: avoid
}
img {
max-width: 100% !important
}
@page {
margin: 0.5cm
}
p,
h2,
h3 {
orphans: 3;
widows: 3
}
h1,
h2,
h3,
h4,
h5,
h6 {
page-break-after: avoid
}
}
</style>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title"><code>pcpp.parser</code> module</h1>
</header>
<section id="section-intro">
<details class="source">
<summary>Source code</summary>
<pre><code class="python">#!/usr/bin/python
# Python C99 conforming preprocessor parser config
# (C) 2017-2026 Niall Douglas http://www.nedproductions.biz/
# and (C) 2007-2017 David Beazley http://www.dabeaz.com/
# Started: Feb 2017
#
# This C preprocessor was originally written by David Beazley and the
# original can be found at https://github.com/dabeaz/ply/blob/master/ply/cpp.py
# This edition substantially improves on standards conforming output,
# getting quite close to what clang or GCC outputs.
from __future__ import generators, print_function, absolute_import, division
import sys, re, os
in_production = 1 # Set to 0 if editing pcpp implementation!
# Some Python 3 compatibility shims
if sys.version_info.major < 3:
STRING_TYPES = (str, unicode)
else:
STRING_TYPES = str
# -----------------------------------------------------------------------------
# Default preprocessor lexer definitions. These tokens are enough to get
# a basic preprocessor working. Other modules may import these if they want
# -----------------------------------------------------------------------------
tokens = (
'CPP_ID','CPP_INTEGER', 'CPP_FLOAT', 'CPP_STRING', 'CPP_CHAR', 'CPP_WS', 'CPP_LINECONT', 'CPP_COMMENT1', 'CPP_COMMENT2',
'CPP_POUND','CPP_DPOUND', 'CPP_PLUS', 'CPP_MINUS', 'CPP_STAR', 'CPP_FSLASH', 'CPP_PERCENT', 'CPP_BAR',
'CPP_AMPERSAND', 'CPP_TILDE', 'CPP_HAT', 'CPP_LESS', 'CPP_GREATER', 'CPP_EQUAL', 'CPP_EXCLAMATION',
'CPP_QUESTION', 'CPP_LPAREN', 'CPP_RPAREN', 'CPP_LBRACKET', 'CPP_RBRACKET', 'CPP_LCURLY', 'CPP_RCURLY',
'CPP_DOT', 'CPP_COMMA', 'CPP_SEMICOLON', 'CPP_COLON', 'CPP_BSLASH', 'CPP_SQUOTE', 'CPP_DQUOTE',
'CPP_DEREFERENCE', 'CPP_MINUSEQUAL', 'CPP_MINUSMINUS', 'CPP_LSHIFT', 'CPP_LESSEQUAL', 'CPP_RSHIFT',
'CPP_GREATEREQUAL', 'CPP_LOGICALOR', 'CPP_OREQUAL', 'CPP_LOGICALAND', 'CPP_ANDEQUAL', 'CPP_EQUALITY',
'CPP_INEQUALITY', 'CPP_XOREQUAL', 'CPP_MULTIPLYEQUAL', 'CPP_DIVIDEEQUAL', 'CPP_PLUSEQUAL', 'CPP_PLUSPLUS',
'CPP_PERCENTEQUAL', 'CPP_LSHIFTEQUAL', 'CPP_RSHIFTEQUAL'
)
literals = "+-*/%|&~^<>=!?()[]{}.,;:\\\'\""
# Whitespace, but don't match past the end of a line
def t_CPP_WS(t):
r'([ \t]+|\n)'
t.lexer.lineno += t.value.count("\n")
return t
# Line continuation, accept whitespace between the backslash and new line
def t_CPP_LINECONT(t):
r'\\[ \t]*\n'
t.value = t.value[1:-1]
t.lexer.lineno += 1
return t
_string_literal_linecont_pat = re.compile(r'\\[ \t]*\n')
t_CPP_POUND = r'\#'
t_CPP_DPOUND = r'\#\#'
t_CPP_PLUS = r'\+'
t_CPP_MINUS = r'-'
t_CPP_STAR = r'\*'
t_CPP_FSLASH = r'/'
t_CPP_PERCENT = r'%'
t_CPP_BAR = r'\|'
t_CPP_AMPERSAND = r'&'
t_CPP_TILDE = r'~'
t_CPP_HAT = r'\^'
t_CPP_LESS = r'<'
t_CPP_GREATER = r'>'
t_CPP_EQUAL = r'='
t_CPP_EXCLAMATION = r'!'
t_CPP_QUESTION = r'\?'
t_CPP_LPAREN = r'\('
t_CPP_RPAREN = r'\)'
t_CPP_LBRACKET = r'\['
t_CPP_RBRACKET = r'\]'
t_CPP_LCURLY = r'{'
t_CPP_RCURLY = r'}'
t_CPP_DOT = r'\.'
t_CPP_COMMA = r','
t_CPP_SEMICOLON = r';'
t_CPP_COLON = r':'
t_CPP_BSLASH = r'\\'
t_CPP_SQUOTE = r"'"
t_CPP_DQUOTE = r'"'
t_CPP_DEREFERENCE = r'->'
t_CPP_MINUSEQUAL = r'-='
t_CPP_MINUSMINUS = r'--'
t_CPP_LSHIFT = r'<<'
t_CPP_LESSEQUAL = r'<='
t_CPP_RSHIFT = r'>>'
t_CPP_GREATEREQUAL = r'>='
t_CPP_LOGICALOR = r'\|\|'
t_CPP_OREQUAL = r'\|='
t_CPP_LOGICALAND = r'&&'
t_CPP_ANDEQUAL = r'&='
t_CPP_EQUALITY = r'=='
t_CPP_INEQUALITY = r'!='
t_CPP_XOREQUAL = r'^='
t_CPP_MULTIPLYEQUAL = r'\*='
t_CPP_DIVIDEEQUAL = r'/='
t_CPP_PLUSEQUAL = r'\+='
t_CPP_PLUSPLUS = r'\+\+'
t_CPP_PERCENTEQUAL = r'%='
t_CPP_LSHIFTEQUAL = r'<<='
t_CPP_RSHIFTEQUAL = r'>>='
# Identifier
t_CPP_ID = r'[A-Za-z_][\w_]*'
# Integer literal
def CPP_INTEGER(t):
r'(((((0x)|(0X))[0-9a-fA-F]+)|(\d+))([uU][lL]|[lL][uU]|[uU]|[lL])?)'
return t
t_CPP_INTEGER = CPP_INTEGER
# Floating literal
t_CPP_FLOAT = r'((\d+)(\.\d+)(e(\+|-)?(\d+))?|(\d+)e(\+|-)?(\d+))([lL]|[fF])?'
# String literal
def t_CPP_STRING(t):
r'\"([^\\\n]|(\\(.|\n)))*?\"'
t.value, subs_made = _string_literal_linecont_pat.subn('', t.value)
t.lexer.lineno += subs_made + t.value.count("\n")
return t
# Character constant 'c' or L'c'
def t_CPP_CHAR(t):
r'(L)?\'([^\\\n]|(\\(.|\n)))*?\''
t.lexer.lineno += t.value.count("\n")
return t
# Comment
def t_CPP_COMMENT1(t):
r'(/\*(.|\n)*?\*/)'
ncr = t.value.count("\n")
t.lexer.lineno += ncr
return t
# Line comment
def t_CPP_COMMENT2(t):
r'(//[^\n]*)'
return t
def t_error(t):
t.type = t.value[0]
t.value = t.value[0]
t.lexer.skip(1)
return t
# Python 2/3 compatible way of importing a subpackage
oldsyspath = sys.path
sys.path = [ os.path.join( os.path.dirname( os.path.abspath(__file__) ), "ply" ) ] + sys.path
from ply import lex, yacc
from ply.lex import LexToken
sys.path = oldsyspath
del oldsyspath
# -----------------------------------------------------------------------------
# trigraph()
#
# Given an input string, this function replaces all trigraph sequences.
# The following mapping is used:
#
# ??= #
# ??/ \
# ??' ^
# ??( [
# ??) ]
# ??! |
# ??< {
# ??> }
# ??- ~
# -----------------------------------------------------------------------------
_trigraph_pat = re.compile(r'''\?\?[=/\'\(\)\!<>\-]''')
_trigraph_rep = {
'=':'#',
'/':'\\',
"'":'^',
'(':'[',
')':']',
'!':'|',
'<':'{',
'>':'}',
'-':'~'
}
def trigraph(input):
return _trigraph_pat.sub(lambda g: _trigraph_rep[g.group()[-1]],input)
def default_lexer():
return lex.lex(optimize=in_production)
# ------------------------------------------------------------------
# Macro object
#
# This object holds information about preprocessor macros
#
# .name - Macro name (string)
# .value - Macro value (a list of tokens)
# .arglist - List of argument names
# .variadic - Boolean indicating whether or not variadic macro
# .vararg - Name of the variadic parameter
#
# When a macro is created, the macro replacement token sequence is
# pre-scanned and used to create patch lists that are later used
# during macro expansion
# ------------------------------------------------------------------
class Macro(object):
def __init__(self,name,value,arglist=None,variadic=False):
self.name = name
self.value = value
self.arglist = arglist
self.variadic = variadic
if variadic:
self.vararg = arglist[-1]
self.source = None
self.lineno = None
def __repr__(self):
return "%s(%s)=%s" % (self.name, self.arglist, self.value)
# ------------------------------------------------------------------
# Preprocessor event hooks
#
# Override these to customise preprocessing
# ------------------------------------------------------------------
class Action(object):
"""What kind of abort processing to do in OutputDirective"""
IgnoreAndPassThrough = 0
"""Abort processing (don't execute), but pass the directive through to output"""
IgnoreAndRemove = 1
"""Abort processing (don't execute), and remove from output"""
class OutputDirective(Exception):
"""Raise this exception to abort processing of a preprocessor directive and
to instead output it as is into the output"""
def __init__(self, action):
self.action = action
class PreprocessorHooks(object):
"""Override these in your subclass of Preprocessor to customise preprocessing"""
def __init__(self):
self.lastdirective = None
def on_error(self,file,line,msg):
"""Called when the preprocessor has encountered an error, e.g. malformed input.
The default simply prints to stderr and increments the return code.
"""
print("%s:%d error: %s" % (file,line,msg), file = sys.stderr)
self.return_code += 1
def on_file_open(self,is_system_include,includepath):
"""Called to open a file for reading.
This hook provides the ability to use ``chardet``, or any other mechanism,
to inspect a file for its text encoding, and open it appropriately. Be
aware that this function is used to probe for possible include file locations,
so ``includepath`` may not exist. If it does not, raise the appropriate
``IOError`` exception.
The default calls ``io.open(includepath, 'r', encoding = self.assume_encoding)``,
examines if it starts with a BOM (if so, it removes it), and returns the file
object opened. This raises the appropriate exception if the path was not found.
"""
if sys.version_info.major < 3:
assert self.assume_encoding is None
ret = open(includepath, 'r')
else:
ret = open(includepath, 'r', encoding = self.assume_encoding)
bom = ret.read(1)
#print(repr(bom))
if bom != '\ufeff':
ret.seek(0)
return ret
def on_include_not_found(self,is_malformed,is_system_include,curdir,includepath):
"""Called when a #include wasn't found.
Raise OutputDirective to pass through or remove, else return
a suitable path. Remember that Preprocessor.add_path() lets you add search paths.
The default calls ``self.on_error()`` with a suitable error message about the
include file not found if ``is_malformed`` is False, else a suitable error
message about a malformed #include, and in both cases raises OutputDirective
(pass through).
"""
if is_malformed:
self.on_error(self.lastdirective.source,self.lastdirective.lineno, "Malformed #include statement: %s" % includepath)
else:
self.on_error(self.lastdirective.source,self.lastdirective.lineno, "Include file '%s' not found" % includepath)
raise OutputDirective(Action.IgnoreAndPassThrough)
def on_unknown_macro_in_defined_expr(self,tok):
"""Called when an expression passed to an #if contained a defined operator
performed on something unknown.
Return True if to treat it as defined, False if to treat it as undefined,
raise OutputDirective to pass through without execution, or return None to
pass through the mostly expanded #if expression apart from the unknown defined.
The default returns False, as per the C standard.
"""
return False
def on_unknown_macro_in_expr(self,ident):
"""Called when an expression passed to an #if contained an unknown identifier.
Return what value the expression evaluator ought to use, or return None to
pass through the mostly expanded #if expression.
The default returns an integer 0, as per the C standard.
"""
return 0
def on_unknown_macro_function_in_expr(self,ident):
"""Called when an expression passed to an #if contained an unknown function.
Return a callable which will be invoked by the expression evaluator to
evaluate the input to the function, or return None to pass through the
mostly expanded #if expression.
The default returns a lambda which returns integer 0, as per the C standard.
"""
return lambda x : 0
def on_directive_handle(self,directive,toks,ifpassthru,precedingtoks):
"""Called when there is one of
define, include, undef, ifdef, ifndef, if, elif, else, endif
Return True to execute and remove from the output, raise OutputDirective
to pass through or remove without execution, or return None to execute
AND pass through to the output (this only works for #define, #undef).
The default returns True (execute and remove from the output).
directive is the directive, toks is the tokens after the directive,
ifpassthru is whether we are in passthru mode, precedingtoks is the
tokens preceding the directive from the # token until the directive.
"""
self.lastdirective = directive
return True
def on_directive_unknown(self,directive,toks,ifpassthru,precedingtoks):
"""Called when the preprocessor encounters a #directive it doesn't understand.
This is actually quite an extensive list as it currently only understands:
define, include, undef, ifdef, ifndef, if, elif, else, endif
Return True to remove from the output, raise OutputDirective
to pass through or remove, or return None to
pass through into the output.
The default handles #error and #warning by printing to stderr and returning True
(remove from output). For everything else it returns None (pass through into output).
directive is the directive, toks is the tokens after the directive,
ifpassthru is whether we are in passthru mode, precedingtoks is the
tokens preceding the directive from the # token until the directive.
"""
if directive.value == 'error':
print("%s:%d error: %s" % (directive.source,directive.lineno,''.join(tok.value for tok in toks)), file = sys.stderr)
self.return_code += 1
return True
elif directive.value == 'warning':
print("%s:%d warning: %s" % (directive.source,directive.lineno,''.join(tok.value for tok in toks)), file = sys.stderr)
return True
return None
def on_potential_include_guard(self,macro):
"""Called when the preprocessor encounters an #ifndef macro or an #if !defined(macro)
as the first non-whitespace thing in a file. Unlike the other hooks, macro is a string,
not a token.
"""
pass
def on_comment(self,tok):
"""Called when the preprocessor encounters a comment token. You can modify the token
in place. You must return True to let the comment pass through, else it will be removed.
Returning False or None modifies the token to become whitespace, becoming a single space
if the comment is a block comment, else a single new line if the comment is a line comment.
"""
return None</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="pcpp.parser.CPP_INTEGER"><code class="name flex">
<span>def <span class="ident">CPP_INTEGER</span></span>(<span>t)</span>
</code></dt>
<dd>
<section class="desc">
<p>(((((0x)|(0X))[0-9a-fA-F]+)|(\d+))([uU][lL]|[lL][uU]|[uU]|[lL])?)</p>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def CPP_INTEGER(t):
r'(((((0x)|(0X))[0-9a-fA-F]+)|(\d+))([uU][lL]|[lL][uU]|[uU]|[lL])?)'
return t</code></pre>
</details>
</dd>
<dt id="pcpp.parser.default_lexer"><code class="name flex">
<span>def <span class="ident">default_lexer</span></span>(<span>)</span>
</code></dt>
<dd>
<section class="desc"></section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def default_lexer():
return lex.lex(optimize=in_production)</code></pre>
</details>
</dd>
<dt id="pcpp.parser.t_CPP_CHAR"><code class="name flex">
<span>def <span class="ident">t_CPP_CHAR</span></span>(<span>t)</span>
</code></dt>
<dd>
<section class="desc">
<p>(L)?'([^\\n]|(\(.|\n)))*?'</p>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def t_CPP_CHAR(t):
r'(L)?\'([^\\\n]|(\\(.|\n)))*?\''
t.lexer.lineno += t.value.count("\n")
return t</code></pre>
</details>
</dd>
<dt id="pcpp.parser.t_CPP_COMMENT1"><code class="name flex">
<span>def <span class="ident">t_CPP_COMMENT1</span></span>(<span>t)</span>
</code></dt>
<dd>
<section class="desc">
<p>(/*(.|\n)*?*/)</p>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def t_CPP_COMMENT1(t):
r'(/\*(.|\n)*?\*/)'
ncr = t.value.count("\n")
t.lexer.lineno += ncr
return t</code></pre>
</details>
</dd>
<dt id="pcpp.parser.t_CPP_COMMENT2"><code class="name flex">
<span>def <span class="ident">t_CPP_COMMENT2</span></span>(<span>t)</span>
</code></dt>
<dd>
<section class="desc">
<p>(//[^\n]*)</p>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def t_CPP_COMMENT2(t):
r'(//[^\n]*)'
return t</code></pre>
</details>
</dd>
<dt id="pcpp.parser.t_CPP_INTEGER"><code class="name flex">
<span>def <span class="ident">t_CPP_INTEGER</span></span>(<span>t)</span>
</code></dt>
<dd>
<section class="desc">
<p>(((((0x)|(0X))[0-9a-fA-F]+)|(\d+))([uU][lL]|[lL][uU]|[uU]|[lL])?)</p>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def CPP_INTEGER(t):
r'(((((0x)|(0X))[0-9a-fA-F]+)|(\d+))([uU][lL]|[lL][uU]|[uU]|[lL])?)'
return t</code></pre>
</details>
</dd>
<dt id="pcpp.parser.t_CPP_LINECONT"><code class="name flex">
<span>def <span class="ident">t_CPP_LINECONT</span></span>(<span>t)</span>
</code></dt>
<dd>
<section class="desc">
<p>\[ \t]*\n</p>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def t_CPP_LINECONT(t):
r'\\[ \t]*\n'
t.value = t.value[1:-1]
t.lexer.lineno += 1
return t</code></pre>
</details>
</dd>
<dt id="pcpp.parser.t_CPP_STRING"><code class="name flex">
<span>def <span class="ident">t_CPP_STRING</span></span>(<span>t)</span>
</code></dt>
<dd>
<section class="desc">
<p>"([^\\n]|(\(.|\n)))*?"</p>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def t_CPP_STRING(t):
r'\"([^\\\n]|(\\(.|\n)))*?\"'
t.value, subs_made = _string_literal_linecont_pat.subn('', t.value)
t.lexer.lineno += subs_made + t.value.count("\n")
return t</code></pre>
</details>
</dd>
<dt id="pcpp.parser.t_CPP_WS"><code class="name flex">
<span>def <span class="ident">t_CPP_WS</span></span>(<span>t)</span>
</code></dt>
<dd>
<section class="desc">
<p>([ \t]+|\n)</p>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def t_CPP_WS(t):
r'([ \t]+|\n)'
t.lexer.lineno += t.value.count("\n")
return t</code></pre>
</details>
</dd>
<dt id="pcpp.parser.t_error"><code class="name flex">
<span>def <span class="ident">t_error</span></span>(<span>t)</span>
</code></dt>
<dd>
<section class="desc"></section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def t_error(t):
t.type = t.value[0]
t.value = t.value[0]
t.lexer.skip(1)
return t</code></pre>
</details>
</dd>
<dt id="pcpp.parser.trigraph"><code class="name flex">
<span>def <span class="ident">trigraph</span></span>(<span>input)</span>
</code></dt>
<dd>
<section class="desc"></section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def trigraph(input):
return _trigraph_pat.sub(lambda g: _trigraph_rep[g.group()[-1]],input)</code></pre>
</details>
</dd>
</dl>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="pcpp.parser.Action"><code class="flex name class">
<span>class <span class="ident">Action</span></span>
</code></dt>
<dd>
<section class="desc">
<p>What kind of abort processing to do in OutputDirective</p>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">class Action(object):
"""What kind of abort processing to do in OutputDirective"""
IgnoreAndPassThrough = 0
"""Abort processing (don't execute), but pass the directive through to output"""
IgnoreAndRemove = 1
"""Abort processing (don't execute), and remove from output"""</code></pre>
</details>
<h3>Class variables</h3>
<dl>
<dt id="pcpp.parser.Action.IgnoreAndPassThrough"><code
class="name">var <span class="ident">IgnoreAndPassThrough</span></code></dt>
<dd>
<section class="desc">
<p>Abort processing (don't execute), but pass the directive through to output</p>
</section>
</dd>
<dt id="pcpp.parser.Action.IgnoreAndRemove"><code
class="name">var <span class="ident">IgnoreAndRemove</span></code></dt>
<dd>
<section class="desc">
<p>Abort processing (don't execute), and remove from output</p>
</section>
</dd>
</dl>
</dd>
<dt id="pcpp.parser.Macro"><code class="flex name class">
<span>class <span class="ident">Macro</span></span>
</code></dt>
<dd>
<section class="desc"></section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">class Macro(object):
def __init__(self,name,value,arglist=None,variadic=False):
self.name = name
self.value = value
self.arglist = arglist
self.variadic = variadic
if variadic:
self.vararg = arglist[-1]
self.source = None
self.lineno = None
def __repr__(self):
return "%s(%s)=%s" % (self.name, self.arglist, self.value)</code></pre>
</details>
<h3>Methods</h3>
<dl>
<dt id="pcpp.parser.Macro.__init__"><code class="name flex">
<span>def <span class="ident">__init__</span></span>(<span>self, name, value, arglist=None, variadic=False)</span>
</code></dt>
<dd>
<section class="desc">
<p>Initialize self.
See help(type(self)) for accurate signature.</p>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def __init__(self,name,value,arglist=None,variadic=False):
self.name = name
self.value = value
self.arglist = arglist
self.variadic = variadic
if variadic:
self.vararg = arglist[-1]
self.source = None
self.lineno = None</code></pre>
</details>
</dd>
</dl>
</dd>
<dt id="pcpp.parser.OutputDirective"><code class="flex name class">
<span>class <span class="ident">OutputDirective</span></span>
<span>(</span><span><small>ancestors:</small> builtins.Exception, builtins.BaseException)</span>
</code></dt>
<dd>
<section class="desc">
<p>Raise this exception to abort processing of a preprocessor directive and
to instead output it as is into the output</p>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">class OutputDirective(Exception):
"""Raise this exception to abort processing of a preprocessor directive and
to instead output it as is into the output"""
def __init__(self, action):
self.action = action</code></pre>
</details>
<h3>Methods</h3>
<dl>
<dt id="pcpp.parser.OutputDirective.__init__"><code class="name flex">
<span>def <span class="ident">__init__</span></span>(<span>self, action)</span>
</code></dt>
<dd>
<section class="desc">
<p>Initialize self.
See help(type(self)) for accurate signature.</p>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def __init__(self, action):
self.action = action</code></pre>
</details>
</dd>
</dl>
</dd>
<dt id="pcpp.parser.PreprocessorHooks"><code class="flex name class">
<span>class <span class="ident">PreprocessorHooks</span></span>
</code></dt>
<dd>
<section class="desc">
<p>Override these in your subclass of Preprocessor to customise preprocessing</p>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">class PreprocessorHooks(object):
"""Override these in your subclass of Preprocessor to customise preprocessing"""
def __init__(self):
self.lastdirective = None
def on_error(self,file,line,msg):
"""Called when the preprocessor has encountered an error, e.g. malformed input.
The default simply prints to stderr and increments the return code.
"""
print("%s:%d error: %s" % (file,line,msg), file = sys.stderr)
self.return_code += 1
def on_file_open(self,is_system_include,includepath):
"""Called to open a file for reading.
This hook provides the ability to use ``chardet``, or any other mechanism,
to inspect a file for its text encoding, and open it appropriately. Be
aware that this function is used to probe for possible include file locations,
so ``includepath`` may not exist. If it does not, raise the appropriate
``IOError`` exception.
The default calls ``io.open(includepath, 'r', encoding = self.assume_encoding)``,
examines if it starts with a BOM (if so, it removes it), and returns the file
object opened. This raises the appropriate exception if the path was not found.
"""
if sys.version_info.major < 3:
assert self.assume_encoding is None
ret = open(includepath, 'r')
else:
ret = open(includepath, 'r', encoding = self.assume_encoding)
bom = ret.read(1)
#print(repr(bom))
if bom != '\ufeff':
ret.seek(0)
return ret
def on_include_not_found(self,is_malformed,is_system_include,curdir,includepath):
"""Called when a #include wasn't found.
Raise OutputDirective to pass through or remove, else return
a suitable path. Remember that Preprocessor.add_path() lets you add search paths.
The default calls ``self.on_error()`` with a suitable error message about the
include file not found if ``is_malformed`` is False, else a suitable error
message about a malformed #include, and in both cases raises OutputDirective
(pass through).
"""
if is_malformed:
self.on_error(self.lastdirective.source,self.lastdirective.lineno, "Malformed #include statement: %s" % includepath)
else:
self.on_error(self.lastdirective.source,self.lastdirective.lineno, "Include file '%s' not found" % includepath)
raise OutputDirective(Action.IgnoreAndPassThrough)
def on_unknown_macro_in_defined_expr(self,tok):
"""Called when an expression passed to an #if contained a defined operator
performed on something unknown.
Return True if to treat it as defined, False if to treat it as undefined,
raise OutputDirective to pass through without execution, or return None to
pass through the mostly expanded #if expression apart from the unknown defined.
The default returns False, as per the C standard.
"""
return False
def on_unknown_macro_in_expr(self,ident):
"""Called when an expression passed to an #if contained an unknown identifier.
Return what value the expression evaluator ought to use, or return None to
pass through the mostly expanded #if expression.
The default returns an integer 0, as per the C standard.
"""
return 0
def on_unknown_macro_function_in_expr(self,ident):
"""Called when an expression passed to an #if contained an unknown function.
Return a callable which will be invoked by the expression evaluator to
evaluate the input to the function, or return None to pass through the
mostly expanded #if expression.
The default returns a lambda which returns integer 0, as per the C standard.
"""
return lambda x : 0
def on_directive_handle(self,directive,toks,ifpassthru,precedingtoks):
"""Called when there is one of
define, include, undef, ifdef, ifndef, if, elif, else, endif
Return True to execute and remove from the output, raise OutputDirective
to pass through or remove without execution, or return None to execute
AND pass through to the output (this only works for #define, #undef).
The default returns True (execute and remove from the output).
directive is the directive, toks is the tokens after the directive,
ifpassthru is whether we are in passthru mode, precedingtoks is the
tokens preceding the directive from the # token until the directive.
"""
self.lastdirective = directive
return True
def on_directive_unknown(self,directive,toks,ifpassthru,precedingtoks):
"""Called when the preprocessor encounters a #directive it doesn't understand.
This is actually quite an extensive list as it currently only understands:
define, include, undef, ifdef, ifndef, if, elif, else, endif
Return True to remove from the output, raise OutputDirective
to pass through or remove, or return None to
pass through into the output.
The default handles #error and #warning by printing to stderr and returning True
(remove from output). For everything else it returns None (pass through into output).
directive is the directive, toks is the tokens after the directive,
ifpassthru is whether we are in passthru mode, precedingtoks is the
tokens preceding the directive from the # token until the directive.
"""
if directive.value == 'error':
print("%s:%d error: %s" % (directive.source,directive.lineno,''.join(tok.value for tok in toks)), file = sys.stderr)
self.return_code += 1
return True
elif directive.value == 'warning':
print("%s:%d warning: %s" % (directive.source,directive.lineno,''.join(tok.value for tok in toks)), file = sys.stderr)
return True
return None
def on_potential_include_guard(self,macro):
"""Called when the preprocessor encounters an #ifndef macro or an #if !defined(macro)
as the first non-whitespace thing in a file. Unlike the other hooks, macro is a string,
not a token.
"""
pass
def on_comment(self,tok):
"""Called when the preprocessor encounters a comment token. You can modify the token
in place. You must return True to let the comment pass through, else it will be removed.
Returning False or None modifies the token to become whitespace, becoming a single space
if the comment is a block comment, else a single new line if the comment is a line comment.
"""
return None</code></pre>
</details>
<h3>Subclasses</h3>
<ul class="hlist">
<li><a title="pcpp.preprocessor.Preprocessor"
href="preprocessor.html#pcpp.preprocessor.Preprocessor">Preprocessor</a></li>
</ul>
<h3>Methods</h3>
<dl>
<dt id="pcpp.parser.PreprocessorHooks.__init__"><code class="name flex">
<span>def <span class="ident">__init__</span></span>(<span>self)</span>
</code></dt>
<dd>
<section class="desc">
<p>Initialize self.
See help(type(self)) for accurate signature.</p>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def __init__(self):
self.lastdirective = None</code></pre>
</details>
</dd>
<dt id="pcpp.parser.PreprocessorHooks.on_comment"><code class="name flex">
<span>def <span class="ident">on_comment</span></span>(<span>self, tok)</span>
</code></dt>
<dd>
<section class="desc">
<p>Called when the preprocessor encounters a comment token. You can modify the token
in place. You must return True to let the comment pass through, else it will be
removed.</p>
<p>Returning False or None modifies the token to become whitespace, becoming a
single space
if the comment is a block comment, else a single new line if the comment is a
line comment.</p>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def on_comment(self,tok):
"""Called when the preprocessor encounters a comment token. You can modify the token
in place. You must return True to let the comment pass through, else it will be removed.
Returning False or None modifies the token to become whitespace, becoming a single space
if the comment is a block comment, else a single new line if the comment is a line comment.
"""
return None</code></pre>
</details>
</dd>
<dt id="pcpp.parser.PreprocessorHooks.on_directive_handle"><code class="name flex">
<span>def <span class="ident">on_directive_handle</span></span>(<span>self, directive, toks, ifpassthru, precedingtoks)</span>
</code></dt>
<dd>
<section class="desc">
<p>Called when there is one of</p>
<p>define, include, undef, ifdef, ifndef, if, elif, else, endif</p>
<p>Return True to execute and remove from the output, raise OutputDirective
to pass through or remove without execution, or return None to execute
AND pass through to the output (this only works for #define, #undef).</p>
<p>The default returns True (execute and remove from the output).</p>
<p>directive is the directive, toks is the tokens after the directive,
ifpassthru is whether we are in passthru mode, precedingtoks is the
tokens preceding the directive from the # token until the directive.</p>
</section>
<details class="source">
<summary>Source code</summary>
<pre><code class="python">def on_directive_handle(self,directive,toks,ifpassthru,precedingtoks):
"""Called when there is one of
define, include, undef, ifdef, ifndef, if, elif, else, endif
Return True to execute and remove from the output, raise OutputDirective
to pass through or remove without execution, or return None to execute
AND pass through to the output (this only works for #define, #undef).
The default returns True (execute and remove from the output).
directive is the directive, toks is the tokens after the directive,
ifpassthru is whether we are in passthru mode, precedingtoks is the
tokens preceding the directive from the # token until the directive.
"""
self.lastdirective = directive
return True</code></pre>
</details>
</dd>
<dt id="pcpp.parser.PreprocessorHooks.on_directive_unknown"><code class="name flex">
<span>def <span class="ident">on_directive_
gitextract_sih0q66g/
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ └── workflows/
│ └── ci.yml
├── .gitignore
├── .gitmodules
├── AGENTS.md
├── LICENSE.txt
├── README.rst
├── doc/
│ ├── evaluator.html
│ ├── index.html
│ ├── lextab.html
│ ├── parser.html
│ ├── parsetab.html
│ ├── pcmd.html
│ └── preprocessor.html
├── pcpp/
│ ├── __init__.py
│ ├── evaluator.py
│ ├── lextab.py
│ ├── parser.py
│ ├── parsetab.py
│ ├── pcmd.py
│ └── preprocessor.py
├── pyproject.toml
├── requirements.txt
├── setup.py
└── tests/
├── Readme.md
├── __init__.py
├── alternate_input_encodings.py
├── alternate_input_encodings1_ucs16le.c
├── alternate_input_encodings2_ucs16le.c
├── cstd.py
├── doctests.py
├── embedded.py
├── eval.py
├── issue0017/
│ ├── inc.h
│ └── issue0017.c
├── issue0017-ref.i
├── issue0017.py
├── issue0025/
│ ├── inc.h
│ └── main.c
├── issue0025-ref.i
├── issue0025.py
├── issue0027.py
├── issue0030/
│ ├── source1.c
│ ├── source2.c
│ └── source3.c
├── issue0030.py
├── issue0032.py
├── issue0037/
│ └── inc.h
├── issue0037.py
├── issue0044.h
├── issue0044.py
├── issue0051.c
├── issue0051.h
├── issue0051.py
├── issue0057.h
├── issue0057.py
├── issue0059.py
├── issue0059a.h
├── issue0059b.h
├── issue0063.c
├── issue0063.h
├── issue0063.py
├── issue0079.py
├── issue0098/
│ ├── dir1/
│ │ └── header.h
│ ├── dir2/
│ │ └── header.h
│ ├── dir3/
│ │ └── header.h
│ └── dir4/
│ └── header.h
├── issue0098.py
├── issue0103.py
├── n_std-clang.i
├── n_std-gcc.i
├── n_std-pcpp.i
├── n_std.i
├── n_std.py
├── passthru.py
└── test-c/
├── LICENSE
├── defs.h
├── e_12_8.c
├── e_14.c
├── e_14_10.c
├── e_14_7.c
├── e_14_9.c
├── e_15_3.c
├── e_16.c
├── e_17.c
├── e_18_4.c
├── e_19_3.c
├── e_23_3.c
├── e_24_6.c
├── e_25_6.c
├── e_27_7.c
├── e_29_3.c
├── e_31.c
├── e_31_3.c
├── e_32_5.c
├── e_33_2.c
├── e_35_2.c
├── e_4_3.c
├── e_7_4.c
├── e_std.c
├── header.h
├── i_32_3.c
├── i_35.c
├── i_35_3.c
├── ifdef15.h
├── line.h
├── m1024.h
├── m_33_big5.c
├── m_33_eucjp.c
├── m_33_gb.c
├── m_33_jis.c
├── m_33_ksc.c
├── m_33_sjis.c
├── m_33_utf8.c
├── m_34_big5.c
├── m_34_eucjp.c
├── m_34_gb.c
├── m_34_jis.c
├── m_34_ksc.c
├── m_34_sjis.c
├── m_34_utf8.c
├── m_36_big5.c
├── m_36_jis.c
├── m_36_sjis.c
├── n_1.c
├── n_10.c
├── n_11.c
├── n_12.c
├── n_13.c
├── n_13_13.c
├── n_13_5.c
├── n_13_7.c
├── n_13_8.c
├── n_15.c
├── n_18.c
├── n_19.c
├── n_2.c
├── n_20.c
├── n_21.c
├── n_22.c
├── n_23.c
├── n_24.c
├── n_25.c
├── n_26.c
├── n_27.c
├── n_28.c
├── n_29.c
├── n_3.c
├── n_30.c
├── n_32.c
├── n_37.c
├── n_3_4.c
├── n_4.c
├── n_5.c
├── n_6.c
├── n_7.c
├── n_8.c
├── n_8_2.c
├── n_9.c
├── n_i_.lst
├── n_std.c
├── nest1.h
├── nest10.h
├── nest11.h
├── nest12.h
├── nest13.h
├── nest14.h
├── nest15.h
├── nest2.h
├── nest3.h
├── nest4.h
├── nest5.h
├── nest6.h
├── nest7.h
├── nest8.h
├── nest9.h
├── side_cpp
├── u_1_1.c
├── u_1_11.c
├── u_1_12.c
├── u_1_13.c
├── u_1_14.c
├── u_1_17.c
├── u_1_19.c
├── u_1_22.c
├── u_1_23.c
├── u_1_24.c
├── u_1_25.c
├── u_1_27.c
├── u_1_28.c
├── u_1_5.c
├── u_1_7_big5.c
├── u_1_7_eucjp.c
├── u_1_7_gb.c
├── u_1_7_jis.c
├── u_1_7_ksc.c
├── u_1_7_sjis.c
├── u_1_7_utf8.c
├── u_1_8.c
├── u_2.c
├── unbal1.h
├── unbal2.h
├── unbal3.h
├── unbal4.h
├── unbal5.h
├── unbal6.h
├── undefs.c
├── unspcs.c
└── warns.c
SYMBOL INDEX (371 symbols across 125 files)
FILE: pcpp/evaluator.py
class Value (line 28) | class Value(INTBASETYPE):
method __sclamp (line 134) | def __sclamp(cls, value):
method __uclamp (line 138) | def __uclamp(cls, value):
method __new__ (line 141) | def __new__(cls, value, unsigned = False, exception = None):
method value (line 193) | def value(self):
method __add__ (line 197) | def __add__(self, other):
method __sub__ (line 204) | def __sub__(self, other):
method __mul__ (line 211) | def __mul__(self, other):
method __div__ (line 218) | def __div__(self, other):
method __truediv__ (line 225) | def __truediv__(self, other):
method __mod__ (line 232) | def __mod__(self, other):
method __neg__ (line 239) | def __neg__(self):
method __invert__ (line 243) | def __invert__(self):
method __and__ (line 247) | def __and__(self, other):
method __or__ (line 254) | def __or__(self, other):
method __pos__ (line 261) | def __pos__(self):
method __pow__ (line 265) | def __pow__(self, other):
method __lshift__ (line 272) | def __lshift__(self, other):
method __rshift__ (line 280) | def __rshift__(self, other):
method __xor__ (line 288) | def __xor__(self, other):
method __repr__ (line 295) | def __repr__(self):
method __bool__ (line 302) | def __bool__(self):
method __cmp__ (line 304) | def __cmp__(self, other):
method __lt__ (line 306) | def __lt__(self, other):
method __le__ (line 313) | def __le__(self, other):
method __eq__ (line 320) | def __eq__(self, other):
method __ne__ (line 327) | def __ne__(self, other):
method __ge__ (line 334) | def __ge__(self, other):
method __gt__ (line 341) | def __gt__(self, other):
function p_error (line 397) | def p_error(p):
function p_expression_number (line 403) | def p_expression_number(p):
function p_expression_character (line 411) | def p_expression_character(p):
function p_expression_string (line 415) | def p_expression_string(p):
function p_expression_group (line 422) | def p_expression_group(t):
function p_expression_uplus (line 426) | def p_expression_uplus(p):
function p_expression_uminus (line 430) | def p_expression_uminus(p):
function p_expression_unop (line 434) | def p_expression_unop(p):
function p_expression_binop (line 447) | def p_expression_binop(p):
function p_expression_conditional (line 512) | def p_expression_conditional(p):
function p_expression_function_call (line 524) | def p_expression_function_call(p):
function p_expression_identifier (line 531) | def p_expression_identifier(p):
class Evaluator (line 539) | class Evaluator(object):
method __init__ (line 687) | def __init__(self, lexer = None):
class __lexer (line 691) | class __lexer(object):
method __init__ (line 693) | def __init__(self, functions, identifiers):
method input (line 698) | def input(self, toks):
method token (line 702) | def token(self):
method on_function_call (line 708) | def on_function_call(self, p):
method on_identifier (line 713) | def on_identifier(self, p):
method __call__ (line 718) | def __call__(self, input, functions = {}, identifiers = {}):
FILE: pcpp/parser.py
function t_CPP_WS (line 39) | def t_CPP_WS(t):
function t_CPP_LINECONT (line 45) | def t_CPP_LINECONT(t):
function PP_NUMBER (line 109) | def PP_NUMBER(t):
function t_CPP_STRING (line 116) | def t_CPP_STRING(t):
function t_CPP_CHAR (line 123) | def t_CPP_CHAR(t):
function t_CPP_COMMENT1 (line 129) | def t_CPP_COMMENT1(t):
function t_CPP_COMMENT2 (line 136) | def t_CPP_COMMENT2(t):
function t_error (line 140) | def t_error(t):
function trigraph (line 185) | def trigraph(input):
function default_lexer (line 188) | def default_lexer():
class Macro (line 207) | class Macro(object):
method __init__ (line 208) | def __init__(self,name,value,arglist=None,variadic=False):
method __repr__ (line 217) | def __repr__(self):
class Action (line 226) | class Action(object):
class OutputDirective (line 233) | class OutputDirective(Exception):
method __init__ (line 236) | def __init__(self, action):
class PreprocessorHooks (line 239) | class PreprocessorHooks(object):
method __init__ (line 241) | def __init__(self):
method on_error (line 244) | def on_error(self,file,line,msg):
method on_file_open (line 252) | def on_file_open(self,is_system_include,includepath):
method on_include_not_found (line 272) | def on_include_not_found(self,is_malformed,is_system_include,curdir,in...
method on_unknown_macro_in_defined_expr (line 289) | def on_unknown_macro_in_defined_expr(self,tok):
method on_unknown_macro_in_expr (line 301) | def on_unknown_macro_in_expr(self,ident):
method on_unknown_macro_function_in_expr (line 311) | def on_unknown_macro_function_in_expr(self,ident):
method on_directive_handle (line 322) | def on_directive_handle(self,directive,toks,ifpassthru,precedingtoks):
method on_directive_unknown (line 340) | def on_directive_unknown(self,directive,toks,ifpassthru,precedingtoks):
method on_potential_include_guard (line 366) | def on_potential_include_guard(self,macro):
method on_comment (line 373) | def on_comment(self,tok):
FILE: pcpp/pcmd.py
class FileAction (line 15) | class FileAction(argparse.Action):
method __init__ (line 16) | def __init__(self, option_strings, dest, **kwargs):
method __call__ (line 19) | def __call__(self, parser, namespace, values, option_string=None):
class CmdPreprocessor (line 27) | class CmdPreprocessor(Preprocessor):
method __init__ (line 28) | def __init__(self, argv):
method on_include_not_found (line 196) | def on_include_not_found(self,is_malformed,is_system_include,curdir,in...
method on_unknown_macro_in_defined_expr (line 201) | def on_unknown_macro_in_defined_expr(self,tok):
method on_unknown_macro_in_expr (line 209) | def on_unknown_macro_in_expr(self,ident):
method on_unknown_macro_function_in_expr (line 217) | def on_unknown_macro_function_in_expr(self,ident):
method on_directive_handle (line 225) | def on_directive_handle(self,directive,toks,ifpassthru,precedingtoks):
method on_directive_unknown (line 240) | def on_directive_unknown(self,directive,toks,ifpassthru,precedingtoks):
method on_potential_include_guard (line 245) | def on_potential_include_guard(self,macro):
method on_comment (line 249) | def on_comment(self,tok):
function main (line 254) | def main(argv=None):
FILE: pcpp/preprocessor.py
class FileInclusionTime (line 30) | class FileInclusionTime(object):
method __init__ (line 32) | def __init__(self,including_path,included_path,included_abspath,depth):
class Preprocessor (line 46) | class Preprocessor(PreprocessorHooks):
method __init__ (line 47) | def __init__(self,lexer=None):
method __file_unique_id (line 88) | def __file_unique_id(fh):
method tokenize (line 98) | def tokenize(self,text):
method __lexprobe (line 118) | def __lexprobe(self):
method add_path (line 232) | def add_path(self,path):
method group_lines (line 254) | def group_lines(self,input,abssource):
method tokenstrip (line 290) | def tokenstrip(self,tokens):
method collect_args (line 319) | def collect_args(self,tokenlist,ignore_errors=False):
method macro_prescan (line 384) | def macro_prescan(self,macro):
method macro_expand_args (line 440) | def macro_expand_args(self,macro,args,expanding_from):
method expand_macros (line 556) | def expand_macros(self,tokens,expanding_from=[]):
method evalexpr (line 670) | def evalexpr(self,tokens):
method parsegen (line 826) | def parsegen(self,input,source=None,abssource=None):
method include (line 1161) | def include(self,tokens,original_line,include_next_is_active=False,inc...
method define (line 1255) | def define(self,tokens):
method undef (line 1337) | def undef(self,tokens):
method parse (line 1352) | def parse(self,input,source=None,ignore={}):
method token (line 1369) | def token(self):
method write (line 1380) | def write(self, oh=sys.stdout):
FILE: setup.py
class PyTest (line 10) | class PyTest(TestCommand):
method initialize_options (line 14) | def initialize_options(self):
method run_tests (line 18) | def run_tests(self):
FILE: tests/alternate_input_encodings.py
class runner (line 13) | class runner(object):
method runTest (line 14) | def runTest(self):
class single_input_file (line 36) | class single_input_file(unittest.TestCase, runner):
class multiple_input_files (line 40) | class multiple_input_files(unittest.TestCase, runner):
FILE: tests/cstd.py
class runner (line 6) | class runner(object):
method runTest (line 7) | def runTest(self):
class std1 (line 27) | class std1(unittest.TestCase, runner):
class std2 (line 55) | class std2(unittest.TestCase, runner):
class std3 (line 65) | class std3(unittest.TestCase, runner):
class std4 (line 75) | class std4(unittest.TestCase, runner):
class std5 (line 95) | class std5(unittest.TestCase, runner):
class std6 (line 122) | class std6(unittest.TestCase, runner):
class std7 (line 135) | class std7(unittest.TestCase, runner):
class std8 (line 152) | class std8(unittest.TestCase, runner):
class std9 (line 170) | class std9(unittest.TestCase, runner):
class std10 (line 180) | class std10(unittest.TestCase, runner):
class std11 (line 192) | class std11(unittest.TestCase, runner):
class test12 (line 212) | class test12(unittest.TestCase, runner):
class test13 (line 287) | class test13(unittest.TestCase, runner):
class test14 (line 302) | class test14(unittest.TestCase, runner):
class test15 (line 331) | class test15(unittest.TestCase, runner):
class test16 (line 339) | class test16(unittest.TestCase, runner):
class test17 (line 349) | class test17(unittest.TestCase, runner):
class test18 (line 358) | class test18(unittest.TestCase, runner):
class test19 (line 377) | class test19(unittest.TestCase, runner):
class test20 (line 393) | class test20(unittest.TestCase, runner):
class test21 (line 408) | class test21(unittest.TestCase, runner):
class test22 (line 423) | class test22(unittest.TestCase, runner):
class test23 (line 443) | class test23(unittest.TestCase, runner):
class test24 (line 484) | class test24(unittest.TestCase, runner):
class test25 (line 493) | class test25(unittest.TestCase, runner):
class test26 (line 502) | class test26(unittest.TestCase, runner):
class test27 (line 517) | class test27(unittest.TestCase, runner):
class test28 (line 532) | class test28(unittest.TestCase, runner):
class test29 (line 546) | class test29(unittest.TestCase, runner):
class test30 (line 562) | class test30(unittest.TestCase, runner):
class test31 (line 574) | class test31(unittest.TestCase, runner):
FILE: tests/doctests.py
class pcpp_doctests (line 3) | class pcpp_doctests(unittest.TestCase):
method runTest (line 4) | def runTest(self):
FILE: tests/embedded.py
class embedded1 (line 5) | class embedded1(unittest.TestCase):
method runTest (line 6) | def runTest(self):
FILE: tests/eval.py
class runner (line 5) | class runner(object):
method runTest (line 6) | def runTest(self):
class eval1 (line 28) | class eval1(unittest.TestCase, runner):
class eval2 (line 36) | class eval2(unittest.TestCase, runner):
class eval3 (line 44) | class eval3(unittest.TestCase, runner):
class eval4 (line 52) | class eval4(unittest.TestCase, runner):
FILE: tests/issue0017.py
class issue0017 (line 4) | class issue0017(unittest.TestCase):
method runTest (line 5) | def runTest(self):
FILE: tests/issue0025.py
class issue0025 (line 4) | class issue0025(unittest.TestCase):
method runTest (line 5) | def runTest(self):
FILE: tests/issue0027.py
class runner (line 6) | class runner(object):
method runTest (line 7) | def runTest(self):
class space_after_hash (line 32) | class space_after_hash(unittest.TestCase, runner):
FILE: tests/issue0030.py
class runner (line 8) | class runner(object):
method runTest (line 9) | def runTest(self):
class multiple_input_files (line 24) | class multiple_input_files(unittest.TestCase, runner):
FILE: tests/issue0032.py
class runner (line 8) | class runner(object):
method runTest (line 9) | def runTest(self):
class no_output_file (line 15) | class no_output_file(unittest.TestCase, runner):
FILE: tests/issue0037.py
class runner (line 10) | class runner(object):
method runTest (line 11) | def runTest(self):
class multiline_comments (line 25) | class multiline_comments(unittest.TestCase, runner):
FILE: tests/issue0044.py
class runner (line 13) | class runner(object):
method runTest (line 14) | def runTest(self):
class empty_line_directive (line 32) | class empty_line_directive(unittest.TestCase, runner):
FILE: tests/issue0051.py
class runner (line 5) | class runner(object):
method runTest (line 6) | def runTest(self):
class normal_inclusion (line 21) | class normal_inclusion(unittest.TestCase, runner):
class exclude_inclusion (line 31) | class exclude_inclusion(unittest.TestCase, runner):
FILE: tests/issue0057.py
class runner (line 6) | class runner(object):
method runTest (line 7) | def runTest(self):
class newline_after_passthru_include1 (line 32) | class newline_after_passthru_include1(unittest.TestCase, runner):
class newline_after_passthru_include2 (line 44) | class newline_after_passthru_include2(unittest.TestCase, runner):
class newline_after_passthru_include3 (line 56) | class newline_after_passthru_include3(unittest.TestCase, runner):
FILE: tests/issue0059.py
class runner (line 6) | class runner(object):
method runTest (line 7) | def runTest(self):
class multiple_inclusion (line 32) | class multiple_inclusion(unittest.TestCase, runner):
FILE: tests/issue0063.py
class runner (line 5) | class runner(object):
method runTest (line 6) | def runTest(self):
class include_after_continued_macro1 (line 21) | class include_after_continued_macro1(unittest.TestCase, runner):
class include_after_continued_macro2 (line 28) | class include_after_continued_macro2(unittest.TestCase, runner):
class include_after_continued_macro3 (line 41) | class include_after_continued_macro3(unittest.TestCase, runner):
FILE: tests/issue0079.py
class runner (line 4) | class runner(object):
method runTest (line 5) | def runTest(self):
class pp_number_pasting (line 19) | class pp_number_pasting(unittest.TestCase, runner):
FILE: tests/issue0098.py
class runner (line 5) | class runner(object):
method runTest (line 6) | def runTest(self):
class include_next_works (line 27) | class include_next_works(unittest.TestCase, runner):
class has_include_works (line 40) | class has_include_works(unittest.TestCase, runner):
FILE: tests/issue0103.py
class runner (line 5) | class runner(object):
method runTest (line 6) | def runTest(self):
class multiline_char_literals1 (line 19) | class multiline_char_literals1(unittest.TestCase, runner):
class multiline_char_literals2 (line 36) | class multiline_char_literals2(unittest.TestCase, runner):
FILE: tests/n_std.py
class n_std (line 5) | class n_std(unittest.TestCase):
method runTest (line 6) | def runTest(self):
FILE: tests/passthru.py
class runner (line 6) | class runner(object):
method runTest (line 7) | def runTest(self):
class test1 (line 53) | class test1(unittest.TestCase, runner):
class test2 (line 63) | class test2(unittest.TestCase, runner):
class test3 (line 76) | class test3(unittest.TestCase, runner):
class test4 (line 93) | class test4(unittest.TestCase, runner):
class test5 (line 112) | class test5(unittest.TestCase, runner):
class test6 (line 131) | class test6(unittest.TestCase, runner):
class test7 (line 145) | class test7(unittest.TestCase, runner):
class test8 (line 164) | class test8(unittest.TestCase, runner):
class test9 (line 207) | class test9(unittest.TestCase, runner):
class test10 (line 219) | class test10(unittest.TestCase, runner):
class test11 (line 237) | class test11(unittest.TestCase, runner):
class test12 (line 264) | class test12(unittest.TestCase, runner):
class test18 (line 294) | class test18(unittest.TestCase, runner):
class test19 (line 312) | class test19(unittest.TestCase, runner):
class test20 (line 337) | class test20(unittest.TestCase, runner):
class test21 (line 345) | class test21(unittest.TestCase, runner):
class test22 (line 357) | class test22(unittest.TestCase, runner):
class test23 (line 369) | class test23(unittest.TestCase, runner):
FILE: tests/test-c/e_12_8.c
function main (line 7) | main( void)
FILE: tests/test-c/e_14.c
function main (line 39) | main( void)
FILE: tests/test-c/e_14_10.c
function main (line 15) | int main( void)
FILE: tests/test-c/e_14_7.c
function main (line 15) | main( void)
FILE: tests/test-c/e_14_9.c
function main (line 7) | int main( void)
FILE: tests/test-c/e_16.c
function MACRO_0 (line 9) | MACRO_0
FILE: tests/test-c/e_18_4.c
function main (line 32) | main( void)
FILE: tests/test-c/e_19_3.c
function main (line 33) | main( void)
FILE: tests/test-c/e_23_3.c
function main (line 12) | main( void)
FILE: tests/test-c/e_24_6.c
function main (line 7) | main( void)
FILE: tests/test-c/e_25_6.c
function main (line 14) | main( void)
FILE: tests/test-c/e_27_7.c
function main (line 12) | main( void)
FILE: tests/test-c/e_29_3.c
function main (line 13) | main( void)
FILE: tests/test-c/e_31.c
function main (line 11) | main( void)
FILE: tests/test-c/e_31_3.c
function main (line 11) | main( void)
FILE: tests/test-c/e_32_5.c
function main (line 8) | main( void)
FILE: tests/test-c/e_33_2.c
function main (line 8) | main( void)
FILE: tests/test-c/e_35_2.c
function main (line 9) | main( void)
FILE: tests/test-c/e_7_4.c
function main (line 8) | main( void)
FILE: tests/test-c/e_std.c
function main (line 18) | main( void)
function e_19_3 (line 237) | void e_19_3( void)
function e_25_6 (line 290) | void e_25_6( void)
function e_27_7 (line 305) | void e_27_7( void)
function e_31 (line 328) | void e_31( void)
FILE: tests/test-c/i_32_3.c
function main (line 5) | main( void)
FILE: tests/test-c/i_35.c
function main (line 5) | main( void)
FILE: tests/test-c/i_35_3.c
function main (line 5) | main( void)
FILE: tests/test-c/m_33_big5.c
function main (line 7) | main( void)
FILE: tests/test-c/m_33_eucjp.c
function main (line 7) | main( void)
FILE: tests/test-c/m_33_gb.c
function main (line 7) | main( void)
FILE: tests/test-c/m_33_jis.c
function main (line 7) | main( void)
FILE: tests/test-c/m_33_ksc.c
function main (line 7) | main( void)
FILE: tests/test-c/m_33_sjis.c
function main (line 7) | main( void)
FILE: tests/test-c/m_33_utf8.c
function main (line 7) | main( void)
FILE: tests/test-c/m_34_big5.c
function main (line 5) | main( void)
FILE: tests/test-c/m_34_eucjp.c
function main (line 5) | main( void)
FILE: tests/test-c/m_34_gb.c
function main (line 5) | main( void)
FILE: tests/test-c/m_34_jis.c
function main (line 5) | main( void)
FILE: tests/test-c/m_34_ksc.c
function main (line 5) | main( void)
FILE: tests/test-c/m_34_sjis.c
function main (line 5) | main( void)
FILE: tests/test-c/m_34_utf8.c
function main (line 5) | main( void)
FILE: tests/test-c/m_36_big5.c
function main (line 7) | main( void)
FILE: tests/test-c/m_36_jis.c
function main (line 7) | main( void)
FILE: tests/test-c/m_36_sjis.c
function main (line 7) | main( void)
FILE: tests/test-c/n_1.c
function main (line 8) | main( void)
FILE: tests/test-c/n_10.c
function main (line 8) | main( void)
FILE: tests/test-c/n_11.c
function main (line 9) | main( void)
FILE: tests/test-c/n_12.c
function main (line 6) | main( void)
FILE: tests/test-c/n_13.c
function main (line 20) | main( void)
FILE: tests/test-c/n_13_13.c
function main (line 12) | main( void)
FILE: tests/test-c/n_13_5.c
function main (line 5) | main( void)
FILE: tests/test-c/n_13_7.c
function main (line 6) | main( void)
FILE: tests/test-c/n_13_8.c
function main (line 5) | main( void)
FILE: tests/test-c/n_15.c
function main (line 8) | main( void)
FILE: tests/test-c/n_18.c
function main (line 5) | main( void)
FILE: tests/test-c/n_19.c
function main (line 5) | main( void)
FILE: tests/test-c/n_2.c
function main (line 5) | main( void)
FILE: tests/test-c/n_20.c
function main (line 5) | main( void)
FILE: tests/test-c/n_21.c
function main (line 5) | main( void)
FILE: tests/test-c/n_22.c
function main (line 9) | main( void)
FILE: tests/test-c/n_23.c
function main (line 10) | main( void)
FILE: tests/test-c/n_24.c
function main (line 5) | main( void)
FILE: tests/test-c/n_25.c
function main (line 16) | main( void)
FILE: tests/test-c/n_26.c
function f (line 5) | int f( a)
function g (line 11) | int g( a)
function main (line 17) | main( void)
FILE: tests/test-c/n_27.c
function main (line 8) | main( void)
FILE: tests/test-c/n_28.c
function main (line 6) | main( void)
FILE: tests/test-c/n_29.c
function main (line 5) | main( void)
FILE: tests/test-c/n_3.c
function main (line 7) | main( void)
FILE: tests/test-c/n_30.c
function main (line 12) | main( void)
FILE: tests/test-c/n_32.c
function main (line 5) | main( void)
FILE: tests/test-c/n_37.c
function main (line 9) | main( void)
FILE: tests/test-c/n_4.c
function main (line 5) | main( void)
FILE: tests/test-c/n_5.c
function main (line 7) | main( void)
FILE: tests/test-c/n_6.c
function main (line 10) | main( void)
FILE: tests/test-c/n_7.c
function main (line 5) | main( void)
FILE: tests/test-c/n_9.c
function main (line 10) | main( void)
FILE: tests/test-c/n_std.c
function main (line 63) | int main( void)
function n_2 (line 104) | void n_2( void)
function n_3 (line 134) | void n_3( void)
function n_5 (line 159) | void n_5( void)
function n_6 (line 178) | void n_6( void)
function n_7 (line 196) | void n_7( void)
function n_9 (line 219) | void n_9( void)
function n_10 (line 228) | void n_10( void)
function n_11 (line 253) | void n_11( void)
function n_12 (line 285) | void n_12( void)
function n_13 (line 327) | void n_13( void)
function n_13_5 (line 365) | void n_13_5( void)
function n_13_7 (line 389) | void n_13_7( void)
function n_13_8 (line 408) | void n_13_8( void)
function n_13_13 (line 441) | void n_13_13( void)
function n_15 (line 468) | void n_15( void)
function n_19 (line 509) | void n_19( void)
function n_20 (line 524) | void n_20( void)
function n_21 (line 533) | void n_21( void)
function n_22 (line 550) | void n_22( void)
function n_23 (line 566) | void n_23( void)
function n_24 (line 580) | void n_24( void)
function n_25 (line 606) | void n_25( void)
function f (line 636) | int f( a)
function g (line 642) | int g( a)
function f (line 648) | int f( int a)
function g (line 653) | int g( int a)
function n_26 (line 659) | void n_26( void)
function n_27 (line 694) | void n_27( void)
function n_28 (line 741) | void n_28( void)
function n_29 (line 770) | void n_29( void)
function n_30 (line 784) | void n_30( void)
function n_32 (line 810) | void n_32( void)
function n_37 (line 824) | void n_37( void)
FILE: tests/test-c/u_1_1.c
function main (line 3) | main( void)
FILE: tests/test-c/u_1_11.c
function main (line 8) | main( void)
FILE: tests/test-c/u_1_12.c
function main (line 7) | main( void)
FILE: tests/test-c/u_1_13.c
function Junk (line 5) | Junk
FILE: tests/test-c/u_1_14.c
function main (line 3) | main( void)
FILE: tests/test-c/u_1_17.c
function main (line 5) | main( void)
FILE: tests/test-c/u_1_19.c
function main (line 5) | main( void)
FILE: tests/test-c/u_1_22.c
function main (line 7) | main( void)
FILE: tests/test-c/u_1_23.c
function main (line 7) | main( void)
FILE: tests/test-c/u_1_24.c
function main (line 21) | main( void)
FILE: tests/test-c/u_1_25.c
function main (line 8) | main( void)
FILE: tests/test-c/u_1_27.c
function main (line 7) | main( void)
FILE: tests/test-c/u_1_28.c
function main (line 13) | main( void)
FILE: tests/test-c/u_1_5.c
function main (line 14) | main( void)
FILE: tests/test-c/u_1_7_big5.c
function main (line 8) | main( void)
FILE: tests/test-c/u_1_7_eucjp.c
function main (line 7) | main( void)
FILE: tests/test-c/u_1_7_gb.c
function main (line 8) | main( void)
FILE: tests/test-c/u_1_7_jis.c
function main (line 7) | main( void)
FILE: tests/test-c/u_1_7_ksc.c
function main (line 8) | main( void)
FILE: tests/test-c/u_1_7_sjis.c
function main (line 8) | main( void)
FILE: tests/test-c/u_1_7_utf8.c
function main (line 7) | main( void)
FILE: tests/test-c/u_1_8.c
function main (line 8) | main( void)
FILE: tests/test-c/u_2.c
function main (line 13) | main( void)
FILE: tests/test-c/undefs.c
function main (line 16) | main( void)
FILE: tests/test-c/unspcs.c
function main (line 21) | main( void)
FILE: tests/test-c/warns.c
function main (line 15) | main( void)
Condensed preview — 210 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (925K chars).
[
{
"path": ".gitattributes",
"chars": 3966,
"preview": "* text=auto !eol svneol=native#text/plain\n*.gitattributes text svneol=native#text/plain\n\n# Scriptish formats\n*.bat "
},
{
"path": ".github/FUNDING.yml",
"chars": 14,
"preview": "github: ned14\n"
},
{
"path": ".github/workflows/ci.yml",
"chars": 2979,
"preview": "name: CI\n\non:\n push:\n branches:\n - master\n pull_request:\n\njobs:\n Build:\n runs-on: ubuntu-24.04\n strateg"
},
{
"path": ".gitignore",
"chars": 37,
"preview": "*.pyc\nbuild/*\ndist/*\npcpp.egg-info/*\n"
},
{
"path": ".gitmodules",
"chars": 117,
"preview": "[submodule \"pcpp/ply\"]\n\tpath = pcpp/ply\n\turl = https://github.com/ned14/ply.git\n\tbranch = master\n\tignore = untracked\n"
},
{
"path": "AGENTS.md",
"chars": 343,
"preview": "# Agent Overview for pcpp (Pure Python C Preprocessor)\n\n## How to build\n- `python setup.py build`\n\n## How to test\n- `pyt"
},
{
"path": "LICENSE.txt",
"chars": 1552,
"preview": "(C) 2018-2026 Niall Douglas http://www.nedproductions.biz/\nand (C) 2007-2019 David Beazley http://www.dabeaz.com/\n\nAll r"
},
{
"path": "README.rst",
"chars": 25372,
"preview": "A C99 preprocessor written in pure Python\n=========================================\n.. role:: c(code)\n :language: c\n\n."
},
{
"path": "doc/evaluator.html",
"chars": 93376,
"preview": "<!doctype html>\n<html lang=\"en\">\n\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-widt"
},
{
"path": "doc/index.html",
"chars": 7006,
"preview": "<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initia"
},
{
"path": "doc/lextab.html",
"chars": 11429,
"preview": "<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initia"
},
{
"path": "doc/parser.html",
"chars": 75467,
"preview": "<!doctype html>\n<html lang=\"en\">\n\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-widt"
},
{
"path": "doc/parsetab.html",
"chars": 20311,
"preview": "<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initia"
},
{
"path": "doc/pcmd.html",
"chars": 27203,
"preview": "<!doctype html>\n<html lang=\"en\">\n\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-widt"
},
{
"path": "doc/preprocessor.html",
"chars": 265106,
"preview": "<!doctype html>\n<html lang=\"en\">\n\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-widt"
},
{
"path": "pcpp/__init__.py",
"chars": 187,
"preview": "from .evaluator import Evaluator\nfrom .parser import Action, OutputDirective\nfrom .pcmd import main, version, CmdPreproc"
},
{
"path": "pcpp/evaluator.py",
"chars": 26642,
"preview": "#!/usr/bin/python\n# Python C99 conforming preprocessor expression evaluator\n# (C) 2019-2026 Niall Douglas http://www.ned"
},
{
"path": "pcpp/lextab.py",
"chars": 4207,
"preview": "# lextab.py. This file automatically created by PLY (version 3.11). Don't edit!\n_tabversion = '3.10'\n_lextokens = s"
},
{
"path": "pcpp/parser.py",
"chars": 13812,
"preview": "#!/usr/bin/python\n# Python C99 conforming preprocessor parser config\n# (C) 2017-2026 Niall Douglas http://www.nedproduct"
},
{
"path": "pcpp/parsetab.py",
"chars": 13515,
"preview": "\n# parsetab.py\n# This file is automatically generated. Do not edit.\n# pylint: disable=W,C,R\n_tabversion = '3.10'\n\n_lr_me"
},
{
"path": "pcpp/pcmd.py",
"chars": 16148,
"preview": "#!/usr/bin/python\n# Python C99 conforming preprocessor command line\n# (C) 2017-2026 Niall Douglas http://www.nedproducti"
},
{
"path": "pcpp/preprocessor.py",
"chars": 69296,
"preview": "#!/usr/bin/python\n# Python C99 conforming preprocessor useful for generating single include files\n# (C) 2017-2026 Niall "
},
{
"path": "pyproject.toml",
"chars": 1167,
"preview": "[build-system]\nrequires = [\"setuptools\"]\nbuild-backend = \"setuptools.build_meta\"\n\n[project]\nname = \"pcpp\"\nversion = \"1.3"
},
{
"path": "requirements.txt",
"chars": 24,
"preview": "setuptools\nwheel\npytest\n"
},
{
"path": "setup.py",
"chars": 2558,
"preview": "#!/usr/bin/env python\n\nfrom setuptools import setup\nfrom setuptools.command.test import test as TestCommand\nimport os\nim"
},
{
"path": "tests/Readme.md",
"chars": 96,
"preview": "test-c was borrowed from the test suite for the mcpp preprocessor\n\nhttp://mcpp.sourceforge.net/\n"
},
{
"path": "tests/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "tests/alternate_input_encodings.py",
"chars": 1721,
"preview": "import unittest, sys, io, os\n\nshouldbe1 = r'''#line 1 \"tests/alternate_input_encodings1_ucs16le.c\"\n语言处理\n'''\n\nshouldbe2 "
},
{
"path": "tests/cstd.py",
"chars": 16036,
"preview": "\nimport unittest, time\nfrom io import StringIO\nclock = time.process_time\n\nclass runner(object):\n def runTest(self):\n "
},
{
"path": "tests/doctests.py",
"chars": 441,
"preview": "import unittest\n\nclass pcpp_doctests(unittest.TestCase):\n def runTest(self):\n import doctest, pcpp.preprocesso"
},
{
"path": "tests/embedded.py",
"chars": 601,
"preview": "\nimport unittest, sys\nfrom io import StringIO\n\nclass embedded1(unittest.TestCase):\n def runTest(self):\n from p"
},
{
"path": "tests/eval.py",
"chars": 1262,
"preview": "import unittest, time\nfrom io import StringIO\nclock = time.process_time\n\nclass runner(object):\n def runTest(self):\n "
},
{
"path": "tests/issue0017/inc.h",
"chars": 75,
"preview": "inc1\n#ifndef __inc_h__\ninc2\n#define __inc_h__\ninc3\n#endif //__inc_h__\ninc4\n"
},
{
"path": "tests/issue0017/issue0017.c",
"chars": 46,
"preview": "#include \"inc.h\"\ntest1\n#include \"inc.h\"\ntest2\n"
},
{
"path": "tests/issue0017-ref.i",
"chars": 190,
"preview": "#line 1 \"tests/issue0017/inc.h\"\ninc1\n\ninc2\n\ninc3\n\ninc4\n#line 2 \"tests/issue0017/issue0017.c\"\ntest1\n#line 1 \"tests/issue0"
},
{
"path": "tests/issue0017.py",
"chars": 802,
"preview": "\nimport unittest, os\n\nclass issue0017(unittest.TestCase):\n def runTest(self):\n from pcpp import Preprocessor\n "
},
{
"path": "tests/issue0025/inc.h",
"chars": 67,
"preview": "OUTCOME_TRY_UNIQUE_NAME __LINE__\n\nOUTCOME_TRY_UNIQUE_NAME __LINE__\n"
},
{
"path": "tests/issue0025/main.c",
"chars": 388,
"preview": "#define OUTCOME_TRY_GLUE2(x, y) x##y\n#define OUTCOME_TRY_GLUE(x, y) OUTCOME_TRY_GLUE2(x, y)\n#define OUTCOME_TRY_UNIQUE_N"
},
{
"path": "tests/issue0025-ref.i",
"chars": 513,
"preview": "#line 5 \"tests/issue0025/main.c\"\n_outcome_try_unique_name_temporary5 5\n_outcome_try_unique_name_temporary6 6\n_outcome_tr"
},
{
"path": "tests/issue0025.py",
"chars": 797,
"preview": "\nimport unittest, os\n\nclass issue0025(unittest.TestCase):\n def runTest(self):\n from pcpp import Preprocessor\n "
},
{
"path": "tests/issue0027.py",
"chars": 1302,
"preview": "\nimport unittest, time\nfrom io import StringIO\nclock = time.process_time\n\nclass runner(object):\n def runTest(self):\n "
},
{
"path": "tests/issue0030/source1.c",
"chars": 25,
"preview": "#undef FOO\n#define FOO 1\n"
},
{
"path": "tests/issue0030/source2.c",
"chars": 25,
"preview": "#undef FOO\n#define FOO 2\n"
},
{
"path": "tests/issue0030/source3.c",
"chars": 4,
"preview": "FOO\n"
},
{
"path": "tests/issue0030.py",
"chars": 856,
"preview": "\nimport unittest, sys, os\n\nshouldbe = r'''#line 1 \"tests/issue0030/source3.c\"\n2\n'''\n\nclass runner(object):\n def runTe"
},
{
"path": "tests/issue0032.py",
"chars": 375,
"preview": "\nimport unittest, sys\n\nshouldbe = r'''#line 1 \"tests/issue0030/source3.c\"\n2\n'''\n\nclass runner(object):\n def runTest(s"
},
{
"path": "tests/issue0037/inc.h",
"chars": 75,
"preview": " /** this spans\n two lines */\n virtual std::string baseOnly();"
},
{
"path": "tests/issue0037.py",
"chars": 866,
"preview": "\nimport unittest, sys, os\n\nshouldbe = r'''#line 1 \"tests/issue0037/inc.h\"\n /** this spans\n two lines */\n vi"
},
{
"path": "tests/issue0044.h",
"chars": 31,
"preview": "a1\n#if 0\nsample text\n#endif\nb1\n"
},
{
"path": "tests/issue0044.py",
"chars": 974,
"preview": "\nimport unittest\nimport sys, os\n\nshouldbe = r'''a1\n\n\n\nb1\n'''\n\n\nclass runner(object):\n def runTest(self):\n from"
},
{
"path": "tests/issue0051.c",
"chars": 63,
"preview": "#include \"issue0051.h\"\n\n#ifdef FOO\n TRUE\n#else\n FALSE\n#endif\n"
},
{
"path": "tests/issue0051.h",
"chars": 66,
"preview": "#define FOO 1\n\nvoid my_func1();\nvoid my_func2();\nvoid my_func3();\n"
},
{
"path": "tests/issue0051.py",
"chars": 1072,
"preview": "\nimport unittest\nimport sys, os\n\nclass runner(object):\n def runTest(self):\n from pcpp import CmdPreprocessor\n "
},
{
"path": "tests/issue0057.h",
"chars": 12,
"preview": "headertoken\n"
},
{
"path": "tests/issue0057.py",
"chars": 1882,
"preview": "\nimport unittest, time\nfrom io import StringIO\nclock = time.process_time\n\nclass runner(object):\n def runTest(self):\n "
},
{
"path": "tests/issue0059.py",
"chars": 1612,
"preview": "\nimport unittest, time\nfrom io import StringIO\nclock = time.process_time\n\nclass runner(object):\n def runTest(self):\n "
},
{
"path": "tests/issue0059a.h",
"chars": 38,
"preview": "#pragma once\n#define FOO __COUNTER__\n\n"
},
{
"path": "tests/issue0059b.h",
"chars": 11,
"preview": "#undef FOO\n"
},
{
"path": "tests/issue0063.c",
"chars": 85,
"preview": "#define x\\\n\\\n\n#include \"issue0063.h\"\n\n#undef x\n#define x\\\n \\\n\n#include \"issue0063.h\"\n"
},
{
"path": "tests/issue0063.h",
"chars": 9,
"preview": "int f();\n"
},
{
"path": "tests/issue0063.py",
"chars": 1310,
"preview": "\nimport unittest\nimport sys, os\n\nclass runner(object):\n def runTest(self):\n from pcpp import CmdPreprocessor\n "
},
{
"path": "tests/issue0079.py",
"chars": 816,
"preview": "import unittest, time\nfrom io import StringIO\n\nclass runner(object):\n def runTest(self):\n from pcpp import Pre"
},
{
"path": "tests/issue0098/dir1/header.h",
"chars": 33,
"preview": "header1\n#include_next \"header.h\"\n"
},
{
"path": "tests/issue0098/dir2/header.h",
"chars": 33,
"preview": "header2\n#include_next \"header.h\"\n"
},
{
"path": "tests/issue0098/dir3/header.h",
"chars": 33,
"preview": "header3\n#include_next \"header.h\"\n"
},
{
"path": "tests/issue0098/dir4/header.h",
"chars": 8,
"preview": "header4\n"
},
{
"path": "tests/issue0098.py",
"chars": 1465,
"preview": "\nimport unittest, sys\nfrom io import StringIO\n\nclass runner(object):\n def runTest(self):\n from pcpp import Pre"
},
{
"path": "tests/issue0103.py",
"chars": 910,
"preview": "\nimport unittest, sys\nfrom io import StringIO\n\nclass runner(object):\n def runTest(self):\n from pcpp import Pre"
},
{
"path": "tests/n_std-clang.i",
"chars": 8049,
"preview": "# 1 \"tests/test-c/n_std.c\"\n# 1 \"<built-in>\" 1\n# 1 \"<built-in>\" 3\n# 312 \"<built-in>\" 3\n# 1 \"<command line>\" 1\n# 1 \"<built"
},
{
"path": "tests/n_std-gcc.i",
"chars": 8113,
"preview": "# 1 \"tests/test-c/n_std.c\"\n# 1 \"<built-in>\"\n# 1 \"<command-line>\"\n# 1 \"/usr/include/stdc-predef.h\" 1 3 4\n# 1 \"<command-li"
},
{
"path": "tests/n_std-pcpp.i",
"chars": 7808,
"preview": "# 30 \"tests/test-c/n_std.c\"\nvoid n_1( void);\nvoid n_2( void);\nvoid n_3( void);\nvoid n_4( void);\nvoid n_5( void);\nvoid n_"
},
{
"path": "tests/n_std.i",
"chars": 7808,
"preview": "# 30 \"tests/test-c/n_std.c\"\nvoid n_1( void);\nvoid n_2( void);\nvoid n_3( void);\nvoid n_4( void);\nvoid n_5( void);\nvoid n_"
},
{
"path": "tests/n_std.py",
"chars": 1262,
"preview": "\nimport unittest, time, difflib\nclock = time.process_time\n\nclass n_std(unittest.TestCase):\n def runTest(self):\n "
},
{
"path": "tests/passthru.py",
"chars": 6801,
"preview": "\nimport unittest, time\nfrom io import StringIO\nclock = time.process_time\n\nclass runner(object):\n def runTest(self):\n "
},
{
"path": "tests/test-c/LICENSE",
"chars": 1460,
"preview": "/*-\n * Copyright (c) 1998, 2002-2008 Kiyoshi Matsui <kmatsui@t3.rim.or.jp>\n * All rights reserved.\n *\n * This software i"
},
{
"path": "tests/test-c/defs.h",
"chars": 691,
"preview": "/* defs.h */\n\n#ifndef NO_SYSTEM_HEADERS\n#include <stdio.h>\n\n/* assert(): Enable one of these three. */\n/* Note: Thi"
},
{
"path": "tests/test-c/e_12_8.c",
"chars": 217,
"preview": "/* e_12_8.c: Out of range of integer pp-token in #if expression. */\n\n/* 12.8: Preprocessing number perhaps out of "
},
{
"path": "tests/test-c/e_14.c",
"chars": 731,
"preview": "/* e_14.c: Illegal #if expressions. */\n\n#define A 1\n#define B 1\n\n/* 14.1: String literal is not allowed in #i"
},
{
"path": "tests/test-c/e_14_10.c",
"chars": 267,
"preview": "/* e_14_10.c: Overflow of constant expression in #if directive. */\n\n/* 14.10: */\n#include <limits.h>\n\n#if L"
},
{
"path": "tests/test-c/e_14_7.c",
"chars": 381,
"preview": "/* e_14_7.c: There is no keyword in #if expression. */\n\n/* 14.7: sizeof operator is disallowed. */\n/* Evaluated"
},
{
"path": "tests/test-c/e_14_9.c",
"chars": 157,
"preview": "/* e_14_9.c: Out of range in #if expression (division by 0). */\n\n/* 14.9: Divided by 0. */\n#if 1 / 0\n#endif\n"
},
{
"path": "tests/test-c/e_15_3.c",
"chars": 282,
"preview": "/* e_15_3.c: #ifdef, #ifndef syntax errors. */\n\n/* 15.3: Not an identifier. */\n#ifdef \"string\"\n#endif\n#ifdef 1"
},
{
"path": "tests/test-c/e_16.c",
"chars": 234,
"preview": "/* e_16.c: Trailing junk of #else, #endif. */\n\n/* 16.1: Trailing junk of #else. */\n#define MACRO_0 0\n#if MAC"
},
{
"path": "tests/test-c/e_17.c",
"chars": 640,
"preview": "/* e_17.c: Ill-formed group in a source file. */\n\n#define MACRO_1 1\n\n/* 17.1: Error of #endif without #if. *"
},
{
"path": "tests/test-c/e_18_4.c",
"chars": 908,
"preview": "/* e_18_4.c: #define syntax errors. */\n\n/* 18.4: Not an identifier. */\n#define \"string\"\n#define 123\n\n/* 18.5: "
},
{
"path": "tests/test-c/e_19_3.c",
"chars": 826,
"preview": "/* e_19_3.c: Redefinitions of macros. */\n\n#include \"defs.h\"\n#define str( s) # s\n#define xstr( s) "
},
{
"path": "tests/test-c/e_23_3.c",
"chars": 364,
"preview": "/* e_23_3.c: ## operator shall not occur at the beginning or at the end of\n replacement list for either form o"
},
{
"path": "tests/test-c/e_24_6.c",
"chars": 179,
"preview": "/* e_24_6.c: Operand of # operator in function-like macro definition should\n be a parameter. */\n\n/* 24.6: *"
},
{
"path": "tests/test-c/e_25_6.c",
"chars": 500,
"preview": "/* e_25_6.c: Macro arguments are pre-expanded separately. */\n\n/* 25.6: */\n#define sub( x, y) (x - y)\n#defi"
},
{
"path": "tests/test-c/e_27_7.c",
"chars": 305,
"preview": "/* e_27_7.c: Error of rescanning. */\n\n#define sub( x, y) (x - y)\n\n/* 27.7: */\n#define TWO_TOKENS a,b\n"
},
{
"path": "tests/test-c/e_29_3.c",
"chars": 241,
"preview": "/* e_29_3.c: #undef errors. */\n\n/* 29.3: Not an identifier. */\n#undef \"string\"\n#undef 123\n\n/* 29.4: Excessi"
},
{
"path": "tests/test-c/e_31.c",
"chars": 225,
"preview": "/* e_31.c: Illegal macro calls. */\n\n#define sub( x, y) (x - y)\n\n/* 31.1: Too many arguments error. */\n "
},
{
"path": "tests/test-c/e_31_3.c",
"chars": 285,
"preview": "/* e_31_3.c: Macro call in control line should complete in the line. */\n\n#define glue( a, b) a ## b\n#define str( "
},
{
"path": "tests/test-c/e_32_5.c",
"chars": 268,
"preview": "/* e_32_5.c: Range error of character constant. */\n\n/* 32.5: Value of a numerical escape sequence in character co"
},
{
"path": "tests/test-c/e_33_2.c",
"chars": 314,
"preview": "/* e_33_2.c: Out of range of numerical escape sequence in wide-char. */\n\n/* 33.2: Value of a numerical escape sequ"
},
{
"path": "tests/test-c/e_35_2.c",
"chars": 243,
"preview": "/* e_35_2.c: Out of range of character constant. */\n\n/* In ASCII character set. */\n/* 35.2: */\n#if 'abcdefghi"
},
{
"path": "tests/test-c/e_4_3.c",
"chars": 254,
"preview": "/* e_4_3.c: Illegal pp-token. */\n\n/* 4.3: Empty character constant is an error. */\n#if '' == 0 /* Th"
},
{
"path": "tests/test-c/e_7_4.c",
"chars": 191,
"preview": "/* e_7_4.c: #line error. */\n\n/* 7.4: string literal in #line directive shall be a character string\n li"
},
{
"path": "tests/test-c/e_std.c",
"chars": 8048,
"preview": "/*\n * e_std.c\n *\n * 1998/08 made public kmatsui\n * 2002/08 revised no"
},
{
"path": "tests/test-c/header.h",
"chars": 40,
"preview": "/* header.h */\n\n#define MACRO_abc abc\n"
},
{
"path": "tests/test-c/i_32_3.c",
"chars": 525,
"preview": "/* i_32_3.c: Character constant in #if expression. */\n\n#include \"defs.h\"\n\nmain( void)\n{\n fputs( \"started\\n\", "
},
{
"path": "tests/test-c/i_35.c",
"chars": 370,
"preview": "/* i_35.c: Multi-character character constant. */\n\n#include \"defs.h\"\n\nmain( void)\n{\n fputs( \"started\\n\", stderr);"
},
{
"path": "tests/test-c/i_35_3.c",
"chars": 396,
"preview": "/* i_35_3.c: Multi-character wide character constant. */\n\n#include \"defs.h\"\n\nmain( void)\n{\n fputs( \"started\\"
},
{
"path": "tests/test-c/ifdef15.h",
"chars": 587,
"preview": "/* ifdef15.h */\n\n#ifdef X01\n#else\n#ifdef X02\n#else\n#ifdef X03\n#else\n#ifdef X04\n#else\n#ifdef X05\n#else\n#ifdef X0"
},
{
"path": "tests/test-c/line.h",
"chars": 140,
"preview": "/* line.h */\n\n{\n char * file = __FILE__;\n file += strlen( file) - 6;\n assert( __LINE__ == 6 && strcmp( file,"
},
{
"path": "tests/test-c/m1024.h",
"chars": 11282,
"preview": "/* m1024.h */\n\n#define AA\n#define AB\n#define AC\n#define AD\n#define AE\n#define AF\n#define AG\n#define AH\n#define AI\n#defi"
},
{
"path": "tests/test-c/m_33_big5.c",
"chars": 771,
"preview": "/* m_33_big5.c: Wide character constant encoded in Big-Five. */\n\n#include \"defs.h\"\n#include <limits.h>\n#define "
},
{
"path": "tests/test-c/m_33_eucjp.c",
"chars": 765,
"preview": "/* m_33_eucjp.c: Wide character constant encoded in EUC-JP. */\n\n#include \"defs.h\"\n#include <limits.h>\n#define "
},
{
"path": "tests/test-c/m_33_gb.c",
"chars": 761,
"preview": "/* m_33_gb.c: Wide character constant encoded in GB-2312. */\n\n#include \"defs.h\"\n#include <limits.h>\n#define "
},
{
"path": "tests/test-c/m_33_jis.c",
"chars": 935,
"preview": "/* m_33_jis.c: Wide character constant encoded in ISO-2022-JP. */\n\n#include \"defs.h\"\n#include <limits.h>\n#define "
},
{
"path": "tests/test-c/m_33_ksc.c",
"chars": 769,
"preview": "/* m_33_ksc.c: Wide character constant encoded in KSC-5601. */\n\n#include \"defs.h\"\n#include <limits.h>\n#define "
},
{
"path": "tests/test-c/m_33_sjis.c",
"chars": 773,
"preview": "/* m_33_sjis.c: Wide character constant encoded in shift-JIS. */\n\n#include \"defs.h\"\n#include <limits.h>\n#define "
},
{
"path": "tests/test-c/m_33_utf8.c",
"chars": 825,
"preview": "/* m_33_utf8.c: Wide character constant encoded in UTF-8. */\n\n#include \"defs.h\"\n#include <limits.h>\n#define "
},
{
"path": "tests/test-c/m_34_big5.c",
"chars": 560,
"preview": "/* m_34_big5.t: Multi-byte character constant encoded in Big-Five. */\n\n#include \"defs.h\"\n\nmain( void)\n{\n char * "
},
{
"path": "tests/test-c/m_34_eucjp.c",
"chars": 561,
"preview": "/* m_34_eucjp.c: Multi-byte character constant encoded in EUC-JP. */\n\n#include \"defs.h\"\n\nmain( void)\n{\n char"
},
{
"path": "tests/test-c/m_34_gb.c",
"chars": 556,
"preview": "/* m_34_gb.c: Multi-byte character constant encoded in GB-2312. */\n\n#include \"defs.h\"\n\nmain( void)\n{\n char * "
},
{
"path": "tests/test-c/m_34_jis.c",
"chars": 655,
"preview": "/* m_34_jis.c: Multi-byte character constant encoded in ISO-2022-JP. */\n\n#include \"defs.h\"\n\nmain( void)\n{\n char"
},
{
"path": "tests/test-c/m_34_ksc.c",
"chars": 559,
"preview": "/* m_34_ksc.c: Multi-byte character constant encoded in KSC-5601. */\n\n#include \"defs.h\"\n\nmain( void)\n{\n char * "
},
{
"path": "tests/test-c/m_34_sjis.c",
"chars": 562,
"preview": "/* m_34_sjis.c: Multi-byte character constant encoded in shift-JIS. */\n\n#include \"defs.h\"\n\nmain( void)\n{\n char * "
},
{
"path": "tests/test-c/m_34_utf8.c",
"chars": 554,
"preview": "/* m_34_utf8.c: Multi-byte character constant encoded in UTF-8. */\n\n#include \"defs.h\"\n\nmain( void)\n{\n char * ptr;"
},
{
"path": "tests/test-c/m_36_big5.c",
"chars": 741,
"preview": "/* m_36_big5.c: Handling of '\\\\' in BigFive multi-byte character. */\n\n#include \"defs.h\"\n\n#define str( a) #"
},
{
"path": "tests/test-c/m_36_jis.c",
"chars": 1042,
"preview": "/* m_36_jis.c: Handling of '\\\\' in ISO-2022-JP multi--byte character. */\n\n#include \"defs.h\"\n\n#define str( a) "
},
{
"path": "tests/test-c/m_36_sjis.c",
"chars": 735,
"preview": "/* m_36_sjis.c: Handling of '\\\\' in shift-JIS multi-byte character. */\n\n#include \"defs.h\"\n\n#define str( a) # "
},
{
"path": "tests/test-c/n_1.c",
"chars": 741,
"preview": "/* n_1.c: Conversion of trigraph sequences. */\n\n#include \"defs.h\"\n\nchar quasi_trigraph[] = { '?', '?', ' ', '?"
},
{
"path": "tests/test-c/n_10.c",
"chars": 789,
"preview": "/* n_10.c: #if, #elif, #else and #endif pp-directive. */\n\n#include \"defs.h\"\n\n#define MACRO_0 0\n#define MACRO_1 "
},
{
"path": "tests/test-c/n_11.c",
"chars": 794,
"preview": "/* n_11.c: Operator \"defined\" in #if or #elif directive. */\n\n#include \"defs.h\"\n\n#define MACRO_abc abc\n#define MA"
},
{
"path": "tests/test-c/n_12.c",
"chars": 1297,
"preview": "/* n_12.c: Integer preprocessing number token and type of #if expression. */\n\n#include \"defs.h\"\n#include <limits"
},
{
"path": "tests/test-c/n_13.c",
"chars": 1049,
"preview": "/* n_13.c: Valid operators in #if expression. */\n\n/* Valid operators are (precedence in this order) :\n defined, (un"
},
{
"path": "tests/test-c/n_13_13.c",
"chars": 922,
"preview": "/* n_13_13.c: #if expression with macros. */\n\n#include \"defs.h\"\n#define ZERO_TOKEN\n#define MACRO_0 0\n#defin"
},
{
"path": "tests/test-c/n_13_5.c",
"chars": 892,
"preview": "/* n_13_5.c: Arithmetic conversion in #if expressions. */\n\n#include \"defs.h\"\n\nmain( void)\n{\n fputs( \"started\\"
},
{
"path": "tests/test-c/n_13_7.c",
"chars": 618,
"preview": "/* n_13_7.c: Short-circuit evaluation of #if expression. */\n\n#include \"defs.h\"\n#define MACRO_0 0\n\nmain( void)\n"
},
{
"path": "tests/test-c/n_13_8.c",
"chars": 1257,
"preview": "/* n_13_8.c: Grouping of sub-expressions in #if expression. */\n\n#include \"defs.h\"\n\nmain( void)\n{\n fputs( \"star"
},
{
"path": "tests/test-c/n_15.c",
"chars": 484,
"preview": "/* n_15.c: #ifdef, #ifndef directives. */\n\n#include \"defs.h\"\n\n#define MACRO_0 0\n#define MACRO_1 1\n\nmain( voi"
},
{
"path": "tests/test-c/n_18.c",
"chars": 728,
"preview": "/* n_18.c: #define directive. */\n\n#include \"defs.h\"\n\nmain( void)\n{\n int c = 3;\n\n/* Excerpts from ISO C 6.8.3"
},
{
"path": "tests/test-c/n_19.c",
"chars": 563,
"preview": "/* n_19.c: Valid re-definitions of macros. */\n\n#include \"defs.h\"\n\nmain( void)\n{\n int c = 1;\n\n fputs( \"star"
},
{
"path": "tests/test-c/n_2.c",
"chars": 897,
"preview": "/* n_2.c: Line splicing by <backslash><newline> sequence. */\n\n#include \"defs.h\"\n\nmain( void)\n{\n int ab = 1, "
},
{
"path": "tests/test-c/n_20.c",
"chars": 275,
"preview": "/* n_20.c: Macro lexically identical to keyword. */\n\n#include \"defs.h\"\n\nmain( void)\n{\n\n/* 20.1: */\n#define float "
},
{
"path": "tests/test-c/n_21.c",
"chars": 471,
"preview": "/* n_21.c: Tokenization (No preprocessing tokens are merged implicitly). */\n\n#include \"defs.h\"\n\nmain( void)\n{\n "
},
{
"path": "tests/test-c/n_22.c",
"chars": 643,
"preview": "/* n_22.c: Tokenization of preprocessing number. */\n\n#include \"defs.h\"\n\n#define str( a) # a\n#define xstr( a) "
},
{
"path": "tests/test-c/n_23.c",
"chars": 464,
"preview": "/* n_23.c: ## operator in macro definition. */\n\n#include \"defs.h\"\n\n#define glue( a, b) a ## b\n#define xglue( "
},
{
"path": "tests/test-c/n_24.c",
"chars": 1011,
"preview": "/* n_24.c: # operator in macro definition. */\n\n#include \"defs.h\"\n\nmain( void)\n{\n fputs( \"started\\n\", stderr);\n\n/*"
},
{
"path": "tests/test-c/n_25.c",
"chars": 1191,
"preview": "/* n_25.c: Macro arguments are pre-expanded (unless the argument is an\n operand of # or ## operator) separately,"
},
{
"path": "tests/test-c/n_26.c",
"chars": 1049,
"preview": "/* n_26.c: The name once replaced is not furthur replaced. */\n\n#include \"defs.h\"\n\nint f( a)\n int a;\n{\n "
},
{
"path": "tests/test-c/n_27.c",
"chars": 1738,
"preview": "/* n_27.c: Rescanning of a macro replace any macro call in the replacement\n text after substitution of parameter"
},
{
"path": "tests/test-c/n_28.c",
"chars": 735,
"preview": "/* n_28.c: __FILE__, __LINE__, __DATE__, __TIME__, __STDC__ and\n __STDC_VERSION__ are predefined. */\n\n#in"
},
{
"path": "tests/test-c/n_29.c",
"chars": 368,
"preview": "/* n_29.c: #undef directive. */\n\n#include \"defs.h\"\n\nmain( void)\n{\n int DEFINED = 1;\n\n fputs( \"started\\n\""
},
{
"path": "tests/test-c/n_3.c",
"chars": 652,
"preview": "/* n_3.c: Handling of comment. */\n\n#include \"defs.h\"\n\n#define str( a) # a\n\nmain( void)\n{\n int abcd = "
},
{
"path": "tests/test-c/n_30.c",
"chars": 714,
"preview": "/* n_30.c: Macro calls. */\n/* Note: Comma separate the arguments of function-like macro call,\n but comma b"
},
{
"path": "tests/test-c/n_32.c",
"chars": 531,
"preview": "/* n_32.c: Escape sequence in character constant in #if expression. */\n\n#include \"defs.h\"\n\nmain( void)\n{\n fput"
},
{
"path": "tests/test-c/n_37.c",
"chars": 3587,
"preview": "/* n_37.c: Translation limits. */\n\n#include \"defs.h\"\n\n/* 37.1: Number of parameters in macro: at least 31. */\n#de"
},
{
"path": "tests/test-c/n_3_4.c",
"chars": 322,
"preview": "/* n_3_4.c: Handling of comment and <backslash><newline>. */\n\n/* 3.4: Comment and <backslash><newline> in #error line."
},
{
"path": "tests/test-c/n_4.c",
"chars": 405,
"preview": "/* n_4.c: Special tokens. */\n\n#include \"defs.h\"\n\nmain( void)\n{\n/* 4.1: Digraph spellings in directive line. */\n%"
},
{
"path": "tests/test-c/n_5.c",
"chars": 491,
"preview": "/* n_5.c: Spaces or tabs are allowed at any place in pp-directive line,\n including between the top of a pp-dire"
},
{
"path": "tests/test-c/n_6.c",
"chars": 688,
"preview": "/* n_6.c: #include directive. */\n\n#include \"defs.h\"\n/* 6.1: Header-name quoted by \" and \" as well as by < and > can"
},
{
"path": "tests/test-c/n_7.c",
"chars": 606,
"preview": "/* n_7.c: #line directive. */\n\n#include \"defs.h\"\n\nmain( void)\n{\n fputs( \"started\\n\", stderr);\n\n/* 7.1: Line n"
},
{
"path": "tests/test-c/n_8.c",
"chars": 342,
"preview": "/* n_8.c: #error directive. */\n\n/* 8.1: Argument of #error directive is not a subject of macro expansion.\n Ou"
},
{
"path": "tests/test-c/n_8_2.c",
"chars": 103,
"preview": "/* n_8_2.c: Argument of #error is optional. */\n\n/* 8.2: #error should be executed. */\n#error\n\n"
},
{
"path": "tests/test-c/n_9.c",
"chars": 303,
"preview": "/* n_9.c: #pragma directive. */\n\n#include \"stdio.h\"\n\n/* 9.1: Any #pragma directive should be processed or ignored,"
},
{
"path": "tests/test-c/n_i_.lst",
"chars": 180,
"preview": "n_1\nn_2\nn_3\nn_4\nn_5\nn_6\nn_7\nn_9\nn_10\nn_11\nn_12\nn_13\nn_13_5\nn_13_7\nn_13_8\nn_13_13\nn_15\nn_18\nn_19\nn_20\nn_21\nn_22\nn_23\nn_24"
},
{
"path": "tests/test-c/n_std.c",
"chars": 23761,
"preview": "/*\n * n_std.c\n *\n * 1998/08 made public kmatsui\n * 2002/08 revised no"
},
{
"path": "tests/test-c/nest1.h",
"chars": 53,
"preview": "/* nest1.h */\n\n nest = 1;\n\n#include \"nest2.h\"\n"
},
{
"path": "tests/test-c/nest10.h",
"chars": 35,
"preview": "/* nest10.h */\n#include \"nest11.h\"\n"
},
{
"path": "tests/test-c/nest11.h",
"chars": 35,
"preview": "/* nest11.h */\n#include \"nest12.h\"\n"
},
{
"path": "tests/test-c/nest12.h",
"chars": 35,
"preview": "/* nest12.h */\n#include \"nest13.h\"\n"
},
{
"path": "tests/test-c/nest13.h",
"chars": 35,
"preview": "/* nest13.h */\n#include \"nest14.h\"\n"
},
{
"path": "tests/test-c/nest14.h",
"chars": 35,
"preview": "/* nest14.h */\n#include \"nest15.h\"\n"
},
{
"path": "tests/test-c/nest15.h",
"chars": 51,
"preview": "/* nest15.h */\n#ifdef X0F\n nest = 0x0f;\n#endif\n"
},
{
"path": "tests/test-c/nest2.h",
"chars": 53,
"preview": "/* nest2.h */\n\n nest = 2;\n\n#include \"nest3.h\"\n"
},
{
"path": "tests/test-c/nest3.h",
"chars": 53,
"preview": "/* nest3.h */\n\n nest = 3;\n\n#include \"nest4.h\"\n"
},
{
"path": "tests/test-c/nest4.h",
"chars": 53,
"preview": "/* nest4.h */\n\n nest = 4;\n\n#include \"nest5.h\"\n"
},
{
"path": "tests/test-c/nest5.h",
"chars": 53,
"preview": "/* nest5.h */\n\n nest = 5;\n\n#include \"nest6.h\"\n"
},
{
"path": "tests/test-c/nest6.h",
"chars": 53,
"preview": "/* nest6.h */\n\n nest = 6;\n\n#include \"nest7.h\"\n"
},
{
"path": "tests/test-c/nest7.h",
"chars": 53,
"preview": "/* nest7.h */\n\n nest = 7;\n\n#include \"nest8.h\"\n"
},
{
"path": "tests/test-c/nest8.h",
"chars": 78,
"preview": "/* nest8.h */\n\n#ifndef X0F\n nest = 8;\n#else\n#include \"nest9.h\"\n#endif\n\n"
},
{
"path": "tests/test-c/nest9.h",
"chars": 34,
"preview": "/* nest9.h */\n#include \"nest10.h\"\n"
},
{
"path": "tests/test-c/side_cpp",
"chars": 1806,
"preview": " \n \n "
},
{
"path": "tests/test-c/u_1_1.c",
"chars": 487,
"preview": "/* u_1_1.c: Undefined behaviors on unterminated line, comment or macro. */\n\nmain( void)\n{\n\n/* u.1.1: End of a sour"
},
{
"path": "tests/test-c/u_1_11.c",
"chars": 363,
"preview": "/* u_1_11.c: Undefined behaviors on undefined #include syntax or header-\n name. */\n\n/* u.1.11: Header-name "
},
{
"path": "tests/test-c/u_1_12.c",
"chars": 213,
"preview": "/* u_1_12.c: Undefined behaviors on undefined #include syntax or header-\n name. */\n\n/* u.1.12: Argument of "
},
{
"path": "tests/test-c/u_1_13.c",
"chars": 217,
"preview": "/* u_1_13.c: Undefined behaviors on undefined #include syntax or header-\n name. */\n\n/* u.1.13: Excessive ar"
},
{
"path": "tests/test-c/u_1_14.c",
"chars": 396,
"preview": "/* u_1_14.c: Undefined behaviors on undefined #line syntax. */\n\nmain( void)\n{\n\n/* u.1.14: #line directive without a"
},
{
"path": "tests/test-c/u_1_17.c",
"chars": 662,
"preview": "/* u_1_17.c: Undefined behaviors on out-of-range #line number. */\n\n#include <stdio.h>\n\nmain( void)\n{\n\n/* u.1.17:"
},
{
"path": "tests/test-c/u_1_19.c",
"chars": 1096,
"preview": "/* u_1_19.c: Undefined behaviors on undefined #define and #undef syntax. */\n\n#include <stdio.h>\n\nmain( void)\n{\n\n/*"
},
{
"path": "tests/test-c/u_1_22.c",
"chars": 755,
"preview": "/* u_1_22.c: Undefined behaviors on generating invalid pp-token by ##\n operator. */\n\n#include <stdio.h>\n#"
},
{
"path": "tests/test-c/u_1_23.c",
"chars": 353,
"preview": "/* u_1_23.c: Undefined behaviors on generating invalid pp-token by #\n operator. */\n\n#include <stdio.h>\n#d"
},
{
"path": "tests/test-c/u_1_24.c",
"chars": 1293,
"preview": "/* u_1_24.c: Undefined behaviors on empty argument of macro call. */\n\n/* u.1.24: Empty argument of macro call. "
},
{
"path": "tests/test-c/u_1_25.c",
"chars": 574,
"preview": "/* u_1_25.c: Undefined behaviors on undefined macro argument. */\n\n#include <stdio.h>\n#define str( a) # a\n#d"
},
{
"path": "tests/test-c/u_1_27.c",
"chars": 212,
"preview": "/* u_1_27.c: Pseudo-directive-line. */\n\n/* u.1.27: Unknown preprocessing directive (other than #pragma). */\n#ifde"
},
{
"path": "tests/test-c/u_1_28.c",
"chars": 538,
"preview": "/* u_1_28.c: Macro expanding to name identical to directive. */\n\n#define D define\n/* u.1.28: There are following t"
},
{
"path": "tests/test-c/u_1_5.c",
"chars": 428,
"preview": "/* u_1_5.c: Undefined behaviors on illegal characters. */\n\n/* u.1.5: Illegal characters (in other than string lit"
},
{
"path": "tests/test-c/u_1_7_big5.c",
"chars": 364,
"preview": "/* u_1_7_big5.c: Invalid multi-byte character sequence (in string literal,\n character constant, header-name or"
},
{
"path": "tests/test-c/u_1_7_eucjp.c",
"chars": 301,
"preview": "/* u_1_7_eucjp.c: Invalid multi-byte character sequence (in string literal,\n character constant, header-name or"
},
{
"path": "tests/test-c/u_1_7_gb.c",
"chars": 360,
"preview": "/* u_1_7_gb.c: Invalid multi-byte character sequence (in string literal,\n character constant, header-name or com"
},
{
"path": "tests/test-c/u_1_7_jis.c",
"chars": 305,
"preview": "/* u_1_7_jis.c: Invalid multi-byte character sequence (in string literal,\n character constant, header-name or com"
},
{
"path": "tests/test-c/u_1_7_ksc.c",
"chars": 360,
"preview": "/* u_1_7_ksc.c: Invalid multi-byte character sequence (in string literal,\n character constant, header-name or com"
},
{
"path": "tests/test-c/u_1_7_sjis.c",
"chars": 365,
"preview": "/* u_1_7_sjis.c: Invalid multi-byte character sequence (in string literal,\n character constant, header-name or"
},
{
"path": "tests/test-c/u_1_7_utf8.c",
"chars": 494,
"preview": "/* u_1_7_utf8.c: Invalid multi-byte character sequence (in string literal,\n character constant, header-name or"
},
{
"path": "tests/test-c/u_1_8.c",
"chars": 540,
"preview": "/* u_1_8.c: Undefined behaviors on unterminated quotations. */\n\n/* u.1.8: Unterminated character constant. */\n/"
},
{
"path": "tests/test-c/u_2.c",
"chars": 258,
"preview": "/* u_2.c: Undefined behaviors on undefined constant expression. */\n\n/* u.2.1: Undefined escape sequence. */\n#if "
},
{
"path": "tests/test-c/unbal1.h",
"chars": 22,
"preview": "/* unbal1.h */\n#endif\n"
}
]
// ... and 10 more files (download for full content)
About this extraction
This page contains the full source code of the ned14/pcpp GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 210 files (861.8 KB), approximately 240.8k tokens, and a symbol index with 371 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.