cgv
Loading...
Searching...
No Matches
ppp, the pre-pre-processor

Introduction to ppp

ppp was originally developed to extend the functionallity of the C++ preprocessor. This was done by embedding special commands inside a preheader file with extension *.ph and then transforming the preheader to a real header file interpreting the special commands. ppp (speek tripel-p) has its name from the three 'p's in the word pre-preprocessor.

The embedding of special commands inside a text document proved useful for other applications too and in this way ppp was also used to transform template files based on previously collected information into target files. This template transformation process is applied for

  • makefile generation
  • source code generation for type reflection as described in later sections.

Motivation for usage of another preprocessor

If possible it would be best to avoid custom build tools whereever possible. ppp has been implemented to develop repetitive code needed in template programming, where looping is necessary. The C++ pre-processor can be used for this purpose also but the resulting code is incomprehensible, it does not work together with debuggers and documentation tools like doxygen do neither work.

User Guide

Line and Custom Build Rules

The source code of ppp is located in "$(CGV_DIR)/tool/ppp". A precompiled executable is provided for windows and located in "$(CGV_DIR)/bin/ppp.exe". ppp can be invoked in two ways:

  • to process one file into another
    ppp.exe [-name=value]* source-file target-file
  • to get information from one file and use this to transform one or several template files into target files.
    ppp.exe [-name=value]* source-file [template-file target-file]+
    In both cases one can specify variable definitions marked by a minus sign. When several template files are transformed to several target files, the variable definitions are parsed once before each processing of a template file.

Used extensions for ppp input files:

  • ".ph" ... for pre-header files that are used to generate code
  • ".ppp" ... files that are used solely to configure ppp. The standard ppp configuration file is located in "<cgv/config/ppp.ppp>".
  • ".hh" ... header files of classes that uses the automatic type reflection mechanism
  • ".pj" ... project files used for make file generation
  • ".tm" ... template files

For the visual studio development environment, custom build rules are defined for ".ph", ".hh" and ".pj" files. The custom rule files are located in the folder "$(CGV_DIR)/make/vs".

Example Pre-Header File and Generated Header

A simple example of the usage of ppp is given in the header abst_signal.ph which is located in the namespace cgv::base. It contains a templated class signature representing an arbitrary signature of a functor.

cgv/base/abst_signal.ph:

template <int i, @["typename T1 = type::invalid_type"; ", "; "typename T".N_ARG." = type::invalid_type"]>
struct signature;
@for (i=0; i<=N_ARG; i=i+1) @{
template <@["typename T1"; ", "; "typename T".N_ARG]>
struct signature<@(i),@["T1"; ", "; "T".N_ARG]>
{
@for (j=1; j<=i; j=j+1) @{
typedef typename type::func::make_argument<T@(j)>::type A@(j);
@}
};

All ppp commands are preceeded by a -symbol. This example includes three ppp commands:

  • the @exclude-command includes the proceeding files but does not add a corresponding include directive in the target file (what is done by the @include-command). The included file ppp.ppp defines several global ppp-variables, one of them is N_ARG .
  • the list command @[...] repeats a string, i.e. "typename T1", into a list separated for example by ", ". In each entry numbers in the string are incremented.
  • the @(...) simply writes the value of a ppp internal variable to the target file.
  • the @for-commands iterate everything within the ppp-block markers and