Skip to content

jpcx/pputl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

28 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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/>.