phrep

manpage
Login

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

#defineMUL(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

#defineMSTR@(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)



Attachments: