PreprocessorWizard

Facebooktwitterredditpinterestlinkedinmail

Topics: Perl download free java preprocessor Javascript C C++ C-sharp NetBeans conditional compilation tutorial define ifdef free software development tools IDE WYSIWIG

PreprocessorWizard.pl is a WYSIWYG Conditional Compilation Preprocessor for Java, Perl, C, C++, Basic, PowerShell, C#, JavaScript, and other programming languages.

Many C and C++ developers rely heavily on the C preprocessor, and lament the lack of a preprocessor in Java, scripting languages, and other programming languages.  The principal objection to a preprocessor is that it makes one's code difficult to read.  This is indeed true for the C preprocessor.  It is sometimes difficult to determine which lines of code are active and which are not.  Being WYSIWYG, the PreprocessorWizard multi-language WYSIWIG preprocessor resolves the problem of code being difficult to read.  WYSIWIG means the PreprocessorWizard commentizes inactive code and replaces the original source code file with the commentized file (after copying the original to a backup dir).  That makes the inactive lines very easy to spot; i.e., what you see is what you get.

 

Given the WYSIWIG approach, PreprocessorWizard is even useful for C/C++ programmers.  For C/C++ programmers, code riddled with C preprocessor directives can become horrendously difficult to follow.  With a WYSIWG preprocessor such as PreprocessorWizard, your code will become far easier to comprehend.   What is or is not active would be very easy to detect, especially with a color-coding editor.  The PreprocessorWizard directives can be used in parallel with standard C/C++ preprocessor directives.

 

In addition, PreprocessorWizard provides one preprocessing syntax for all languages with left-delimited comments.

 

The PreprocessorWizard requires Perl, but Perl is easy to get and install if you do not already have it; e.g. at ActiveState for Windows.

 

The PreprocessorWizard is easy to use as a standalone application and it can also be easily integrated with almost any IDE.

 

If you tried PreprocessorWizard and liked it, please leave a review at https://sourceforge.net/projects/preprocesssorwizard/

 

A Simple Example.  Create the file DoFile.pl (a global configuration file) with just this line:

          $global{BuildFreeware} = 1;

Create a java file with this content:

Now run PreprocessorWizard.pl on the above file.  The result will be this:

The inactive lines are now commentized and the active lines can clearly be identified.  Your original will have been backed up by PreprocessorWizard.pl.

Now change DoFile.pl to this so you can build the Pro version:

          $global{BuildFreeware} = 0;

Then rerun PreprocessorWizard.pl to get this result:

Again, the active lines are clearly identifiable.  What you see is what you get.

PreprocessorWizard Language

{C}define SimpleVar

{C}undef  SimpleVar

{C}if     SimpleVar | SimpleExpression | PerlExpression

{C}ifndef SimpleVar | SimpleExpression | PerlExpression

{C}elsif  SimpleVar | SimpleExpression | PerlExpression

{C}else

{C}endif

{C}eval   PerlExpression

where

{C} is the commentizer, which is user-specified (e.g., it could be #. or #% for Perl, or //. as in the above Java example)

SimpleVar is just a string of alphanumeric characters. 

define SimpleVar is exactly the same as eval $local{SimpleVar} = 1.  

undef SimpleVar is exactly the same as   eval $local{SimpleVar} = 0.

SimpleExpression is any expression that includes SimpleVars and does not include Perl variables or strings.  Examples:
         
          //.if (UseZip || UseZap) && !OmitBeta
          //.if Version == 2

PerlExpression is any Perl expression.  PerlExpression may reference the global variables %ENV (environment variables), %local, %global, @Files, and any other global variables in PreprocessorWizard.pl and/or the optional, user-supplied DoFile.  The DoFile can define subs and PerlExpression can use them.

When SimpleVar is used in if, ifndef, or elsif,  it is the same as:
         
          defined($local{SimpleVar} ) ? $local{SimpleVar}  :
          defined($global{SimpleVar}) ? $global{SimpleVar} :
          defined($ENV{SimpleVar})    ? $ENV{SimpleVar}    : 0

I.e., SimpleVar accesses the file-local SimpleVar if it exists, else SimpleVar accesses the global SimpleVar if it exists, else  SimpleVar accesses the environment variable SimpleVar if it exists, else 0 is used.

%local=( ); is executed for each file processed. 

%global is never cleared by PreprocessorWizardPreprocessorWizard does not assign to %global even in undef.  Only the user-supplied DoFile assigns to %global.  See the Java example above.

Features of PreprocessorWizard.pl. 

*    PreprocessorWizard can be fed multiple files in one run.  The files for the run are stored in the Perl array @Files.  @Files can be populated by: (1) A search beginning from a specified directory, (2) wildcard specs entered on the command line or by the user, (3) by the user-supplied DoFile, or (4) by the List option (example below).

*    PreprocessorWizard will back up all files before changing them.  Up to four backups are made for each file.

*    PreprocessorWizard has a Decommentize option, so everything can be reversed.

*    PreprocessorWizard can be used for C/C++ in addition to the C/C++ preprocessor.  The big advantage of using PreProcessorWizard in a C/C++ project is that it is WYSIWIG

*    PreprocessorWizard can be used standalone, or it can be easily integrated with almost any IDE.  See the example below for a NetBeans Java project.

*    PreprocessorWizard can process several hundred files/second if the files to preprocess are specified using the List option (example below).

Usage.  You can run PreProcessorWizard.pl -help for a complete explanation of all possible options.  However, the simplest and most efficient way is to run it like this:

PreprocessorWizard.pl -List MyFiles.txt -Extns c -DoFile MyDoFile.pl -BackupDir MyBackupDir

Where MyFiles.txt is a text file that contains lines that may be:  (1) blank, or (2) contain Perl style comments, or (3) contain files specs that can be Perl-globbed.  For example, MyFiles.txt could contain these lines:

# List of file specs for the WhizBang project
WhizBang/*.h  WhizBang/*.cpp   WhizBang/*.js
Utils/*.h     Utils/*.cpp
DBUtils/*.h   DBUtils/*.cpp

This would preprocess all C++ and JavaScript files in the WhizBang subdirectory, and all C++ files in the Utils and DBUtils subdirectories.  The purpose of the Extns option is just to define the commentizers (//. for commands and //| for commentizing inactive lines).

For a subsequent run where nothing is to be changed from the previous run, you could just enter this:

PreprocessorWizard.pl -batch

This will cause PreprocessorWizard to run without prompting for any options.  PreprocessorWizard will just use the previous options, which are stored in the pwiz subdirectory that it creates.

Example of Calling PreprocessorWizard for a Java project from an ANT build script.  Define the target "-pre-compile" (this is already defined for you if you use NetBeans) and add something like the following to your build.xml:

    <target name="-pre-compile">

        <echo> Running PreprocessorWizard </echo>

        <exec executable="perl" >

            <arg value="c:\path\to\PreprocessorWizard.pl"/>

            <arg value="-batch"/>

            <arg value="-Extns=java"/>

            <arg value="-StartDir=src"/>

            <arg value="-BackupDir=src.bak"/>

            <arg value="-DoFile=scripts/DoFile.pl"/>

        </exec>

    </target>

Then PreprocessorWizard will be executed on all *.java files in the tree starting at dir src whenever you do a clean and build.  Your backups and the PreprocessorWizard log file will be found in src.bak.  Note that using the StartDir option is not very efficient.  It would be much faster to use the List option as in the WhizBang example above.  The only advantage to using the StartDir option is that one would not need to update the List option file if a new subdirectory were added.

Integration with NetBeans.  I use the PreprocessorWizard in NetBeans and apply it not only to my *.java files, but also my project.properties file. The latter allows me to build from a single application different versions for different customers and put the different versions in different jar files in different directories. I just need to change a single line in my DoFile.pl and I automatically get the version I want in the place I want it when I click "Clean & Build".  The code I don't want for a specific customer is commentized and so that customer's jar file bytecode would not contain that code and could not be decompiled by that customer to see what he is missing.  Nor does the unwanted code bloat the jar file.

This is how to preprocess the project.properties file in an Ant file:

    <target name="-pre-init" unless="application.title">

        <!-- Executed prior to NetBeans reading project.properties -->

        <echo>*** Running PreprocessorWizard on project.properties ***</echo>

        <exec executable="perl" >

            <arg value="c:\path\to\PreprocessorWizard.pl"/>

            <arg value="-batch"/>

            <arg value='-Extns=properties'/>

            <arg value="-BackupDir=C:\path\to\BackupDir"/>

            <arg value="-DoFile=scripts/DoFile.pl"/>

            <arg value="nbproject/project.properties"/> <!-- the one file to preprocess -->

        </exec>

    </target>

Naturally, the project.properties file would contain #.if ... #.else ... #.endif statements to conditionally define your dist.dir and dist.jar.

More Help.  For more help, try running PreprocessorWizard.pl -help

Speed.  PreprocessorWizard.pl with the -List option (see above) takes less than 1 second to process about 300 files in my current (2016) C++/JavaScript project

Download PreprocessorWizard.  PreprocessorWizard.zip  This zip file should contain everything you need.

No Perl on Your Windows Machine?  You can get Perl from ActiveState.  It has always installed without any problems for me.  Then just put the above files in the same directory.  That should be all you need to do.  Probably less than 10 minute's work.

More Info:  See this Code Ranch discussion: https://coderanch.com/t/371584/java/preprocessor-directives

Change Log:

Date

Changes

5/4/15

1.   If $StartDir is not blank, then $DoDirPtns can be specified to limit what subdirectories are searched for files to preprocess.

2.   end can be used as an alias for endif or end if.

3.   Print %global hash into the log file.

4.   If there are missing endifs, print the line number of the if/ifndef to which the missing endif most likely belongs.  This is triggered by finding a command for which the indentation level has unexpectedly decreased below what is expected.  For this to work, you will need to have correct indentation.  Previously, missing endifs were not detected until the end of the file was reached and it was difficult to know where to look to fix the error.

5.   Exit more gracefully if called from a background process. 

6.   Increased scope of the eval function to test %ENV.  NOTE: This change could affect you if you have been using variable names that are the same as any of your environment variable names.

7/29/15

1.   Fixed error in default value of Commentizer2.  Previously, the default value was always "//|" for any value of $Extns.

2.   Enhanced the if, ifndef, and else if expressions to allow a SimpleExpression to be used.  Previously, only SimpleVar, and PerlExpression were supported.

3.   Added the List option, which makes the program simpler and more efficient.  See the usage example above.

8/5/15

1.   Updated documentation only.

06/16/17

1.   Print a summary of the %global hash on stdout at the conclusion of a run.  One line lists globals that contain "DEBUG_" and another line lists the other globals.

This page was last modified Wed Oct 07 17:41:38 2020

 

PreprocessorWizard was last modified: by