## 14 Using the patcher

Occasionally we have needed to modify slightly the standard include files. So, we developed a simple mechanism that allows us to create modified copies of the include files and use them instead of the standard ones. For this purpose we specify a patch file and we run a program caller Patcher which makes modified copies of include files and applies the patch.

The patcher is invoked as follows:

    lib/patcher [options]

    Options:
      --help       Prints this help message
      --verbose    Prints a lot of information about what is being done
      --mode=xxx   What tool to emulate:
                    GNUCC     - GNU CC
                    MSVC      - MS VC cl compiler

      --dest=xxx   The destination directory. Will make one if it does not exist
      --patch=xxx  Patch file (can be specified multiple times)
      --ppargs=xxx An argument to be passed to the preprocessor (can be specified
                   multiple times)

      --ufile=xxx  A user-include file to be patched (treated as \#include "xxx")
      --sfile=xxx  A system-include file to be patched (treated as \#include <xxx>)

      --clean       Remove all files in the destination directory
      --dumpversion Print the version name used for the current compiler

     All of the other arguments are passed to the preprocessor. You should pass
     enough arguments (e.g., include directories) so that the patcher can find the
     right include files to be patched.

Based on the given mode and the current version of the compiler (which the patcher can print when given the dumpversion argument) the patcher will create a subdirectory of the dest directory, such as:

      /usr/home/necula/cil/include/gcc_2.95.3-5

In that file the patcher will copy the modified versions of the include files specified with the ufile and sfile options. Each of these options can be specified multiple times.

The patch file (specified with the patch option) has a format inspired by the Unix patch tool. The file has the following grammar:

      <<< flags
      patterns
      ===
      replacement
      >>>

The flags are a comma separated, case-sensitive, sequence of keywords or keyword = value. The following flags are supported:

- file=foo.h - will only apply the patch on files whose name is foo.h.
- optional - this means that it is Ok if the current patch does not match any of the processed files.
- group=foo - will add this patch to the named group. If this is not specified then a unique group is created to contain just the current patch. When all files specified in the command line have been patched, an error message is generated for all groups for whom no member patch was used. We use this mechanism to receive notice when the patch triggers are out-dated with respect to the new include files.
- system=sysname - will only consider this pattern on a given operating system. The “sysname” is reported by the “$Ô” variable in Perl, except that Windows is always considered to have sysname “cygwin.” For Linux use “linux” (capitalization matters).
- ateof - In this case the patterns are ignored and the replacement text is placed at the end of the patched file. Use the file flag if you want to restrict the files in which this replacement is performed.
- atsof - The patterns are ignored and the replacement text is placed at the start of the patched file. Uf the file flag to restrict the application of this patch to a certain file.
- disabled - Use this flag if you want to disable the pattern.

The patterns can consist of several groups of lines separated by the ||| marker. Each of these group of lines is a multi-line pattern that if found in the file will be replaced with the text given at the end of the block.

The matching is space-insensitive.

All of the markers <<<, |||, === and >>> must appear at the beginning of a line but they can be followed by arbitrary text (which is ignored).

The replacement text can contain the special keyword @__pattern__@, which is substituted with the pattern that matched.