Justin Collier 4f7ddeb864 | ||
---|---|---|
include/pputl | ||
test | ||
tools | ||
.clang-format | ||
.gitignore | ||
.gitmodules | ||
CHANGELOG.md | ||
LICENSE | ||
Makefile | ||
README.md |
README.md
pputl 0.2.2 | API Docs | CHANGELOG
__ ___
/\ \__/\_ \
_____ _____ __ __\ \ ,_\//\ \
/\ '__`\/\ '__`\/\ \/\ \\ \ \/ \ \ \
\ \ \_\ \ \ \_\ \ \ \_\ \\ \ \_ \_\ \_
\ \ ,__/\ \ ,__/\ \____/ \ \__\/\____\
\ \ \ \ \ \ \/___/ \/__/\/____/
\/_/ \/_/
pputl Preprocessor Utilities
About
pputl is a C++ preprocessor utilities library. It provides basic preprocessor tools
such as concatenation of multiple symbols, control flow, integer manipulation, etc.
It utilizes a reduce mechanism for some of the logic; see below for more info.
Currently, it uses __VA_OPT__
, so a supportive compiler is required (or C++20).
Future releases may ship with a build script for generating the project without this requirement.
Requirements
- C++20 (or
__VA_OPT__
support)
Usage
This is a header-only library; include the include/
directory for access.
install
# copies headers to ${DESTDIR}${PREFIX}/include/pputl/
make install
use
#include <pputl/pputl.h>
#define THREE PPUTL_SUM(1, 1, 1)
#if PPUTL_NEQ(THREE, 3)
static_assert(false);
#endif
#define MULTICAT PPUTL_CAT(my, cool, cat) // mycoolcat
#define SUM_REDUCER(accum, val, i) PPUTL_ADD(accum, val)
#define SUM(...) PPUTL_REDUCE(SUM_REDUCER, 0, __VA_ARGS__)
#define SEVEN SUM(1, 2, 4)
// const char *my_cool_string = "my.cool.string";
const char *PPUTL_JOIN_GLUE(_, my, cool, string) =
PPUTL_STRINGIZE(PPUTL_JOIN_DOT(my, cool, string));
Tools
pputl comes with a reduce macro generator in the tools/
folder.
This script generates a set of macros that allow for pseudo-recursive value reduction.
Due to the inability for the preprocessor to recurse (without special, [slow!] expansion logic),
it's necessary to generate a new set of macros if REDUCE
call chaining is desired.
Output is sent to stdout.
# node genReduceMacro [NAMESPACE] [PREFIX=REDUCE] [STACK_DEPTH=256] [DETAIL=true]
node tools/genReduceMacro NS REDUCE 4 false # true makes entry macro name NS_DETAIL_REDUCE
#define NS_REDUCE(reducer, initial, ...) \
NS_DETAIL_REDUCE_CHOOSER(__VA_ARGS__) \
(reducer, initial, (0, 1, 2, 3)__VA_OPT__(, ) __VA_ARGS__)
#
#define NS_DETAIL_REDUCE_CAT_X(a, b) a##b
#define NS_DETAIL_REDUCE_CAT(a, b) NS_DETAIL_REDUCE_CAT_X(a, b)
#
#define NS_DETAIL_REDUCE_FIRST(i, ...) i
#define NS_DETAIL_REDUCE_REST(_, ...) __VA_ARGS__
#/* */ // clang-format off
#define NS_DETAIL_REDUCE_0(r, a, is) a
#define NS_DETAIL_REDUCE_1(r, a, is, v) r(a, v, NS_DETAIL_REDUCE_FIRST is)
#define NS_DETAIL_REDUCE_2(r, a, is, v, ...) NS_DETAIL_REDUCE_1(r, r(a, v, NS_DETAIL_REDUCE_FIRST is), (NS_DETAIL_REDUCE_REST is), __VA_ARGS__)
#define NS_DETAIL_REDUCE_3(r, a, is, v, ...) NS_DETAIL_REDUCE_2(r, r(a, v, NS_DETAIL_REDUCE_FIRST is), (NS_DETAIL_REDUCE_REST is), __VA_ARGS__)
#/* */ // clang-format on
#define NS_DETAIL_REDUCE_CHOICE(_3, _2, _1, size, ...) \
NS_DETAIL_REDUCE_CAT(NS_DETAIL_REDUCE_, size)
#
#define NS_DETAIL_REDUCE_CHOOSER(...) \
NS_DETAIL_REDUCE_CHOICE(__VA_ARGS__ __VA_OPT__(, ) 3, 2, 1, 0)
The reducing control flow is capable of perfoming any kind of operation,
but other types (e.g. transform) may be useful. More generation scripts may be added here.
Testing
All API features are statically tested with jpcx/cctest (embedded).
make -j8 test
Contributing
Contribution is welcome! Please make a pull request.
I'd like to maximize the utility of the preprocessor, especially in the wake of __VA_OPT__
.
Documentation
Project documentation is generated by Doxygen and is hosted by GitHub Pages.
License
pputl Preprocessor Utilities
Copyright (C) 2020, 2021 Justin Collier <m@jpcx.dev>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the internalied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.