phrep [-OPTIONS] -i input.php [-o output.php]


The phrep command applies #define, #include, #if, #else, #endif and other C-style preprocessing directives for PHP scripts. It also replaces collected constants and macros within <?php code sections, then outputs the resulting source code. Other comments and the code structure are preserved.

It provides some command-line similarity to cpp(1) and further syntax compatibility with preprocess(1).py and phpp(1). It can read most C/C++ header .h files or doubly-escaped // #directives. Whereas the #if expr syntax is closer to PHP.


Option arguments can be space-separated -o arg, adjoined -oarg, or use an equal sign -o=arg.

-i file.php

Reads the input PHP script to be processed. There’s no requirement as to the specific file extension being used. For Makefiles or other build systems a .phpp extension or .p.php might make sense. phrep only processes one file at a time. If -i- is used instead of a filename, then standard input is read instead.

-o output.php

When specified, writes the converted source file to a specific name. One can also use -o- to write it to standard output (that’s the default anyway). With -oi or -oinput the original input file is overwritten. Whereas -otarget is a magic name that can be set from within proccessed files via #pragma(target=bld/targetfn.php).


Force overwriting of output file. Which phrep doesn’t do per default, unless -oi or -oinput was specified.


Predefines a constant or a macro. Constants simply take the form NAME=1.2.3 for substition values, or just -D FLAG for options that are just probed in #ifdef or #ifndef directives. Whereas macros require arguments in parens DIV(x,y)=x/y. And often you’d want to enclose this option in quotes to avoid shell substitution.

-I lib/inc/

Adds a directory to the search path for #include <fn> directives.


If an existing file is given as -I argument, then that’s read before the main input. It’ll however just be used to collect constants and macros, but will not be prepended or generate output.


Suppress all warning messages.


Turn all warnings into errors instead, and stop execution.

-m token

The constant/macro substitution phase is context-sensitive per default. It will only replace constants within <?php code sections.

  • The alternative -m regex mode however will replace constants irrespective of that (in raw HTML areas before PHP code, in strings, in comments; really everywhere).

  • You can define custom delimiters with -m "regex [[ ]]" to constrain that. Thus constants would only be replaced where written as [[DEFNAME]] or macros enclosed as [[HTML_INPUT(text,title,href]] for example.

  • Or use predefined constant delimiters %{ and } with -m erb, or in the -m phpp mode {{{ and }}} for example.


Keep empty lines in place for #include or #define and #if etc directives.

-p opt=val

Set further processing (#pragma) options.






Print program version number.


Outputs a short help page and option summary.

DIRECTIVES (No! They’re not hashtags)

Preprocessing #directives are mostly in-line with their CPP equivalents. They must be noted leftmost in source code. Albeit up to two ␣␣ spaces may be prepended.

#define CONSTANT

Declares a constant without value. This is mostly used to provide known identifiers for #ifdef and #ifndef directives.


Value literals can be interpolated in <?php sections later. The value can be string or number, or often a version number. To use them in PHP code sections it’s sensible to enquote "strings" already.

#define MACRO(x,y) (2x+3y)

Defines a standard macro. Complex macros (see next section) are defined by naming them with a trailing @. Note that #macro is an alias for #define.


Undefines a previously defined constant or macro.


Checks for a declared identifier. If it’s undefined, then following source code is omitted from output until an #else, #elif or #endif etc.

#ifndef CONSTANT

Probes if a constant does not exist.


If all previous conditional sections failed, then code between #else and #endif will be written out.

#if expr

You can check for more complex conditions using an if expression.

  • 7 * 12 > 3 / 0.5 || (12 / 4 ^ 2) ⇒ Common arithmetic and comparison operations.

  • CONST > 2.0.0-beta ⇒ Is often used for comparing version tuples or floats.

  • VER =~ beta ⇒ Does a case-insensitive regex comparison.

  • defined(WHATEVER) || defined("PKG_VERSION") ⇒ The defined() function tests for existing constants within arbitrary expressions. A few PHP more functions like strpos, is_int, etc. may also be used. Most constants can be written as literals and/or put in quotes.

#elif expr

Works like #if, but is used as alternative condition leave between if and else/endif.


Ends a conditional section. Note that #if/#endif constructs can be nested. Which is where minimally space-indentend ␣#if* directives become useful.

#include <config.php>

Loads a referenced file, consumes its constant and macro definitions and literal source output, but has <?php and ?> tags stripped. Files are searched among the -I include dirs, when relative paths have been given. Filename enclosures <> and "" or '' are all equivalent to phrep (unlike for cpp), and they can even be omitted.

  • "lib/" - Common extensions for PHP includes are just .php or .ph for header-style files, or even the olden .inc, and are usually interpolated.

  • <header.h> - While C header .h or macro .def files have their output suppressed by default.


Sets preprocessing and substition options from within source files.
For instance there are:

  • output=0 to omit further code from the current or included files.

  • target=filename.php to override the target filename for phrep -o target.

  • omit=*.{h,def} is a glob pattern to declare which includes to generally suppress output from.

  • comments=0 strips inline comments from constants.

  • macros=0 disables reading macro definitions.

  • complex=0 disables complex macros (PHP callback code).

  • multipass=1 enables macro-in-macro substitution.

  • keep_empty=1 retains empty lines for inactive conditional sections (see -k flag).

  • fail=1 makes preprocessing fail with fatal errors instead of warnings (equals -W option).

  • quiet=1 disables warnings (equals -w option).

  • interpolate=delim << >> is the -m option.

  • dirs=./lib:../includes can add further search paths, like the -I option.

The more traditional #pragma option value syntax is also allowed.

#stderr Message string

Outputs a warning or error message. (To be used within conditional sections).

#srcout Literal code

Adds code to the output. This is a phrep-specific extension. It’s intended to keep unpreprocessed .php scripts running, by escaping some literal code that would trip up PHP interpretion else.

#macro NAME(x) (x+1)

Is just an alias for #define.


Now some care must be taken to not inadvertently overwrite PHP-code constants everywhere. Define your preprocessing constants with unambiguous names. Use common prefixes such as PKG_, BLD_ or USE_.

Internal/C-style predefined constants for example are STDC_VERSION, TIMESTAMP, and PHP_VERSION (which is the PHP version used at build/preprocessing time, not the PHP runtimes´ PHP_VERSION in later script executions).


Standard/basic macros allow code substitutions. They’re in line with CPP, and simply #define MACRO(a,b) names with a list of params along. Params don’t use $ variable prefixes in their definition or the replacement code.



Usage in PHP code

$var = MUL(7,5);


$var = (75);

This is obviously not the most useful example. Their purpose is to shorten lengthier code templates. Important to note however is that interpolated args a or b often need to be parenthesized (a)*(b) themselves. Because macro arguments MUL(1+2,3+4) can be expressions instead of just literals.


Complex macros can be defined using an @-decorated macro name and an anonymous function body. The param definition again doesn’t use $ signs, but the substitution code must:


#defineMSTR@(i,str){return '"'.str_repeat($str,$i).'"';}

Usage in PHP code

$var = MSTR@(3,abc);


$var = "abcabcabc";

Notably now the macro must take care to produce valid PHP code from its literal/stringified arguments, which become $i and $str.

A varg… parameter can also be used as macro declaration argument. It becomes $varg for the callback, and collects extraneous arguments (as a list of expr/value strings).

There’s also an implied $token parameter for each complex macro callback. It’s an array of all macro arguments, but not in string form. Each entry is a list of PHP parser tokens (T_VARIABLE, T_IS_EQUAL, T_LNUMBER, etc). Obviously they’re more involving to craft, but would allow more complex expression transformations.



Successfully successed.


Failure (syntax or usage error; document processing failure; etc).


No input -i file given.


Internal software error, mostly invalid preprocessing directives or #if expressions.


Refusing to overwriting existing -o output file.

Anyway, just check for an exit code > 0 and output on stderr.



May predefine a list of -I include search dirs.


No configuration file is present per default. One can however craft a ~/.config/php/phrep.php script. - It’ll run after $opts and $proc have been initialized. Which allows to override some settings, or predefine utility functions / bindings for complex macro callbacks.


Yes, certainly.




MIT License


cpp(1), phpp(1), preprocess(1), php(1), ccpp(1)