phrep(1) Manual Page
NAME
phrep - Macro preprocessor for PHP scripts
SYNOPSIS
phrep [-OPTIONS] -i input.php [-o output.php]
DESCRIPTION
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.
OPTIONS
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
). - -f
-
Force overwriting of output file. Which phrep doesn’t do per default, unless -oi or -oinput was specified.
- -D CONST=VAL
-
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.
- -I preload.inc
-
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.
- -w
-
Suppress all warning messages.
- -W
-
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.
-
- -k
-
Keep empty lines in place for #include or #define and #if etc directives.
- -p opt=val
-
Set further processing (#pragma) options.
- -E
-
NOP.
- -v
-
NOP.
- -V
-
Print program version number.
- -h
-
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.
- #define CONSTANT VALUE
-
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.
- #undef CONSTANT
-
Undefines a previously defined constant or macro.
- #ifdef CONSTANT
-
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.
- #else
-
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.
- #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/deps.ph" - 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.
-
- #pragma(option=value)
-
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.
CONSTANT USAGE
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 MACROS
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.
- Declaration
-
#define ␣ MUL(a,b) ␣ (ab)
- Usage in PHP code
-
$var = MUL(7,5);
- Becomes
-
$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
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:
- Declaration
-
#define ␣ MSTR@(i,str) ␣
{return '"'.str_repeat(
$str,$i).'"';}
- Usage in PHP code
-
$var = MSTR@(3,abc);
- Becomes
-
$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.
EXIT STATUS
- 0
-
Successfully successed.
- 1
-
Failure (syntax or usage error; document processing failure; etc).
- 66
-
No input -i file given.
- 70
-
Internal software error, mostly invalid preprocessing directives or #if expressions.
- 73
-
Refusing to overwriting existing -o output file.
Anyway, just check for an exit code > 0 and output on stderr.
ENVIRONMENT
- PHP_INCLUDE_PATH
-
May predefine a list of -I include search dirs.
- XDG_CONFIG_HOME
-
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.
BUGS
Yes, certainly.
AUTHOR
:x
LICENSE
MIT License
SEE ALSO
cpp(1), phpp(1), preprocess(1), php(1), ccpp(1)
- Repository/Docs
- Announcements