PPWIZARD is a free preprocessor for HTML, REXX, Visual Basic or any text files.
This command provides a simple way to define multi line/statement rexx code without requiring line continuation characters. This is useful for:
You use this command to define the start and end of a block of rexx code and anything in between is either rexx code or a ppwizard command.
The fact that ppwizard commands are interpreted while the block is being processed allows you to use useful commands such as #include or #if to selectively include or exclude parts of the rexx code (at definition time). To make decisions at runtime you must use the rexx "if" statement and not the ppwizard #if command!
Each line of rexx goes through the following processing:
Please see the #DefineRexx Tracing section for more information and for details on restrictions. If debug is off then this command will be ignored.
Note that the end of each rexx line is expected to be the end of a rexx statement so if a rexx statement spans multiple lines you will still need to use line continuation on these lines.
Note that if you combine multiple macros generated this way you must separate them with ';' as this command does not terminate the last statement.
At the end of the block the complete rexx code may have symbols substituted depending on how the DefineMacroReplace option is set.
Note that the last line/statement of the block will not be terminated with a semicolon, if you wish to combine blocks you will need to take this into account.
Note that rexx does not support the definition of functions within the code to be executed, please see the "Rexx Subroutines in PPWIZARD" section for ways around this limitation.
If PPWIZARD detects a syntax error in the rexx code (assuming correct configuration) it will be able to pin point the line number and statement that failed. This is very much worth your while configuring correctly!.
[WhiteSpace]#DefineRexx[+] [["]Variable["] ["]NOPACK["] "TRACE:OFF" "TRACE:ON" "TRACE:AUTO"]
If the command was "#DefineRexx+" then if a redefine of a variable occurs then this is considered to be OK and no warnings are generated.
If the Variable parameter is supplied it defines the name of a #define to be generated with the following lines as their contents. If no parameters are supplied the rexx code block is completed.
If the Variable parameter is given as "" (empty) then the rexx code is immediately executed and not saved. When code is executed immediately then any macro parameters are always replaced.
The TRACE:? options override the default set with the PpwTrace option.
The default situation is that rexx code is packed, the optional NOPACK keyword allows you to prevent this. Some rexx interpreters have trouble with legal rexx code when excess spaces are removed! Rather than completely disabling all packing you can also make use of the AllowPack option to selectively prevent the packing of certain lines.
|Use Within Macros|
The line by line processing described above can not occur when the rexx code is being defined within a macro (it sees one line).
I recommend that you do not use this command within a macro definition unless this command is used for the immediate execution the rexx code. If defining a macro containing rexx code then there is no reason why it need be imbedded.
You need to end each line with either a ";" or space as appropriate, consider the following:
#( '' #define EnclosingMacro ... #DefineRexx 'Something' Var1 = '' if (Test) then do fred = 1 end #DefineRexx ... #)
The rexx code actually ends up looking like:
Var1 = ''if (Test) thendofred = 1end
It was the "#(" command which did this, not the "#DefineRexx" command (it only sees the one "line"!).
Now to fix it you could ensure a ";" was on each line, in the following I use a space also (purely for example):
#( '' #define EnclosingMacro ... #DefineRexx 'Something' Var1 = ''; if (Test) then \ do; fred = 1; end; #DefineRexx ... #)
Now the line will look like (ignoring any packing that "#DefineRexx" might do):
Var1 = '';if (Test) then do;fred = 1;end
Much better! This is valid rexx and so should work!
You can turn on rexx's inbuilt tracing by ensuring that you have set the "REXXTRACE" DebugLevel and setting the "REXXTRACE" macro to an appropriate value. This tracing does not work well on regina (excellent on OS/2 though).
To simply test a few spots for correct function typically you would use standard rexx "say" commands like:
say 'About to do stuff, Line = "' || TheLine || '"';
A better method to do the same thing is to use the "$trace" facility, the command would now look like:
$trace About to do stuff
The above "$trace" would display the string and dump the contents of all known variables. It would also be possible to set breakpoints and the values at the end of the execution of the rexx code also get displayed.
Now you can also turn on "$trace mode" where $trace commands are automatically added to each line however you should read about the (reasonable) restrictions you should follow when formatting your code.
|MORE ON PACKING|
The preprocessor packs well written code (by my definition!) and can fail to correctly pack code where strings are appended without the use of the "||" operator (as the excess spaces will be removed). For example the following statement will not create the string you expect when packed:
BothPartsCombined = 'Value:' TheValue;
The following statement is a version of the above that will work:
BothPartsCombined = 'Value: ' || TheValue;
Note that PPWIZARD may not be able to correctly pack lines that refer to macro variables such as in the following:
#DefineRexx ValidateUrlR_REXX_Location #Option PUSH AllowPack=NO do IncIndex = 1 to <?IncludeLevel> ;;This line can't be packed #Option POP ;--- Format the input file at this level --- ThisBit = FilePart('name', InputComponentLevel(IncIndex)); ThisBit = ThisBit || '(' || AddCommasToDecimalNumber(InputComponentLineLevel(IncIndex)) || ')'; ;--- Update location string ---------------- if IncIndex = 1 then UrlSourceLocation = ThisBit; else UrlSourceLocation = UrlSourceLocation || '->' || ThisBit; end #DefineRexx
The reason for the failure to pack (without the #option commands) in this circumstance is that the rexx code is not valid until the substitution has taken place, this confuses the packing logic (it is not packing "pure" rexx code).
#DefineRexx SomeRexxCode TRACE:auto ;--- Comment to be removed (as are blank lines) --- $trace At start of rexx code RexxVar1 = strip(GetEnv('PATH')); /*--- This rexx comment will also be removed ----*/ RexxVar2 = '[' || 'stuff'; /*This rexx comment gets removed*/ ;--- Lets not pack the following rexx code --- #option PUSH AllowPack=OFF BothPartsCombined = 'Value:' TheValue; #option POP ;--- Gets some code from a file --- #include "SomeRexx.X" #DefineRexx #evaluate ^^ ^<$SomeRexxCode>^
You could also have a look at the PPWSORT.H header file as a further example.