PPWIZARD is a free preprocessor for HTML, REXX, Visual Basic or any text files.
[Bottom][Contents][Search][Prev]: #RexxVar[Next]: #undef
\ -> Commands -> #transform

#transform

This command allows you to define a block of lines for which transformations (that you define) should take place.

I got the idea when creating some javascript to output html (using javascript's "document.writeln()" routine), this can be hard as the html code becomes less readable and you have problems with handling quotes.

I needed to use javascript to generate HTML controls that should only be available if the javascript they need can also be available.

What I wanted was an automated way of adding the "document.writeln()" code and taking care of any content issues such as handling quote characters. This way I just edit the easily readable html code and not worry about which quotes I'm allowed to use or what to do when I need both!

A transformation is one of the last things to occur before a line is generated into the output file.

To perform transformations you must first define the rexx code which is called for each line to be output. The code can read/write these rexx variables:

  1. FileLine
    This read/write variable contains the contents of the line. You can split or add lines by adding "MarksNewLine".

  2. Remove
    This variable should be set to non-empty value to cause the line to be ignored. The value you set (the reason) will be output if debug mode is on.

  3. DoPrevious
    If you have nested the #transform command and you wish any previous transformation code to be executed then you must set this variable to "Y".

You can nest transform commands but you must "close" each opened transform. You will need to be careful about the use of this command if you also use #output (to ensure any of your state variables are referring to the current file).

An example of code which handles the problem described above (converting HTML to javascript) follows:

#DefineRexx DOC_WRITELN
            ;--- Escape any escape characters -------------------------------
            FileLine = ReplaceString(FileLine, "\", "\\");

            ;--- Escape any single quotes (we use this below) ---------------
            FileLine = ReplaceString(FileLine, "'", "\'");

            ;--- Now wrap in javascript code to write it out ----------------
            FileLine = "document.writeln('" || FileLine || "')";
#DefineRexx

Once you have defined the transformation code you can then mark the start and end of the block of lines that get transformed on output. You can not nest transformation blocks.

Syntax

[WhiteSpace]#Transform  [["]MacroContainingCodeName["]]

If the single parameter exists then this marks the start of the block, if missing it marks the end of the block. To start the block you need to supply the name of the macro that contains the transformation code.

If the macro referred to is empty then #transform processing is suspended (useful to pause transformation without turning it off).

Example #1

I used this code in some VB Script in a Windows HTA (HTML application) to create "document.writeln" calls automatically and take care of quoting issues:

;--- Define how to convert HTML code into VB "document.writeln()" code ------
#DefineRexx DOC_WRITELN_IN_VB
       FileLine = ReplaceString(FileLine, '"', '""');       ;;Double up double quote characters
       FileLine = 'document.writeln("' || FileLine || '")'  ;;Wrap in VB code to create the HTML or code
#DefineRexx

;--- Create a couple of aliases to hopefully make code self explanatory -----
#define WriteLn    \
        #Transform DOC_WRITELN_IN_VB
#define WriteLnEnd \
        #Transform


;############################################################################
sub AddFooter()
;
;   Graphics from
;   ~~~~~~~~~~~~~
;   http://www.iconbazaar.com/alphabets/animated/great_stars/pg01.html
;############################################################################
   #define Bsd                                 \
           <img src="AnimatedStar-{$#1}.gif"   \
             border="0"                        \
             height="20"                       \
              width="20"                      -\
           >
   <$WriteLn>
       <p>
       <hr size="1" color="red">
       <center>
       PRINTQS v<$PGM_VERSION>
       <BR>
   <$WriteLnEnd>
       document.writeln(FormatDateTime(date(), vbLongDate) & " at " & FormatDateTime(time(), vbLongTime))
   <$WriteLn>
       <BR>
       <a href="http://www.bnz/intranet/bsd/bsd_home.htm"     \
          target="_blank"                                     \
           title="Developed by Branch Application Development \
                  Click to open browser at BAD homepage."    -\
       >                                                     -\
           <$Bsd "B">                                        -\
           <$Bsd "A">                                        -\
           <$Bsd "D">                                        -\
       </a>
       </center>
   <$WriteLnEnd>
end sub

Example #2

This code show another larger chunk of rexx code being used to transform some html:


;--- Turn tracing off (or huge debug output) --------------------------------
#define     REXXTRACE OFF

;--- Define some transformation code ----------------------------------------
#DefineRexx HIDE_HTML
            ;--- Convert into codes -----------------------------------------
            Before = FileLine;
            After  = '';
            do Posn = 1 to length(Before)
               ;--- Get the next byte ---------------------------------------
               ThisByte = substr(Before, Posn, 1);     ;;Byte As Character

               ;--- Want Hex or Octal codes (Hex is default)? ---------------
               #ifndef  HIDE_HTML_IN_OCTAL
                   ;--- Calculate HEX code ----------------------------------
                   Code = '\x' || c2x(ThisByte);       ;;Byte As Hex code
               #elseif
                   ;--- Convert to code (octal) -----------------------------
                   ThisByte = c2d(ThisByte);           ;;Byte As ASCII
                   Code = '';
                   do  while ThisByte <> 0
                       ;--- Add next digit ----------------------------------
                       Code = Code || (ThisByte // 8);

                       ;--- Prepare for next loop ---------------------------
                       ThisByte = ThisByte % 8;
                   end;

                   ;--- Add escape and put digits in correct order ----------
                   Code = left(Code, 3, '0');          ;;MUST be 3 digits
                   Code = '\' || reverse(Code);        ;;Byte As Octal code
               #endif

               ;--- Add to output (note I don't check max literal length!) --
               After = After || Code;
            end;

            ;--- Now wrap in javascript code to write it out ----------------
            FileLine = "document.writeln('" || After || "')";
#DefineRexx

;--- Start HTML -------------------------------------------------------------
<HTML>
<BODY>

;--- Now create encoded body ------------------------------------------------
<SCRIPT LANGUAGE=JavaScript>
   #transform  HIDE_HTML
               <H1>Simplest Hidden code Possible</H1>

               <P>This is a sample of the simplest way to
               hide code, of course it only works if user's
               browser can handle javascript.

               <P>You could get much more complicated and
               encrypt the code however anything you do can
               still be undone as of course while the codes
               can't be read directly the javascript can, one
               way out of this might be to include the javascript
               at runtime.

               <P>Note I have since realised that not all browsers
               show the source code, they show the "resultant"
               code instead, however this is still good demonstration
               code!
   #transform
</SCRIPT>

;--- Show something if no javascript ----------------------------------------
<NOSCRIPT>
   <P>Sorry your browser does not handle
   javascript or you have it turned off!
</NOSCRIPT>

;--- End of HTML ------------------------------------------------------------
</BODY>
</HTML>

Example #3

I wanted to be able to show as an example the output of a macro, however it generated html/xml code and would therefore not display correctly in a browser (it also generated characters that upset IPF code).

What I needed to do was "transform" the end result, this is what I did:

;--- Define required IPF & HTML transformations -----------------------------
#DefineRexx "MAKE_HTML_VIEWABLE"
   #if ['<$DocType>' = 'HTML']
       FileLine = ReplaceString(FileLine, '<', '&lt;');     ;;Hide HTML from browser
   #elseif
       FileLine = ReplaceString(FileLine, ':', '&colon.');  ;;For IPF - Hide ':'
   #endif
#DefineRexx

;--- Show example -----------------------------------------------------------
<$ExampleFormatted>
#transform MAKE_HTML_VIEWABLE
<$WantToSeeWhatItExpandsTo>
#transform
<$eExampleFormatted>

Example #4 - Filters blank lines

This is a transform which ensures that we don't output more than one blank line. A blank line is defined as a line that is empty or only contains whitespace characters (spaces etc).

Note that this code will not work correctly if you use #output while filtering, you would need to turn if off then on.

#NextId
#DefineRexx 'Rexx4#TRANSFORM=Max1BlankLine'
   if  FileLine <> '' then
       @@BlankLineCnt = 0      ;;Found a line which isn't blank
   else
   do
       ;--- Allow at most one blank line through ---
       @@BlankLineCnt = @@BlankLineCnt + 1;
       if  @@BlankLineCnt > 1 then
           Remove = 'Want at most one blank line!'
   end;
#DefineRexx
#define Max1BlankLine                                 \
        #RexxVar   @@BlankLineCnt = 0                -\
        #transform 'Rexx4#TRANSFORM=Max1BlankLine'
#define /Max1BlankLine \
        #transform

;--- Test code ---
<$Max1BlankLine>
1
2
<?NewLine>
4
<?NewLine>
<?NewLine>
<?NewLine>
<?NewLine>
6
<?NewLine>
<?NewLine>
<?NewLine>
<$/Max1BlankLine>

Example #4 - Filters blank lines + Trailing

This modifies the code in the above example so that trailing blank lines won't be output and removes all leading and trailing spaces on all lines.

#DefineRexx 'Rexx4#TRANSFORM=Max1BlankLine'
   ;--- Remove leading & trailing spaces ------------------------------------
   FileLine = strip(FileLine);

   ;--- Blank line logic ----------------------------------------------------
   if  FileLine = '' then
   do
       ;--- Always remove blank lines here ----------------------------------
       @@BlankLineCnt = @@BlankLineCnt + 1;
       Remove = 'Want at most one blank line (no trailing blank lines either!)!'
   end;
   else
   do
       ;--- Have a non-blank line (any blank lines to output?) --------------
       if  @@BlankLineCnt <> 0 then
       do
           ;--- We need to output a single blank line -----------------------
           FileLine = MarksNewLine || FileLine;  ;;Add blank line to start
           @@BlankLineCnt = 0
       end;
   end;
#DefineRexx

Example #5 - Example 4 but #output "safe"

This modifies the code to use HOOK_OUTPUT so that the state variables exist per output file.

;--- Hook to keep track of state information per output file! ---------------
#NextId
#NextId LOCK "MyTransformCode"
#RexxVar   @@Level          = 1        ;;Already processing a file!
#RexxVar   @@BlankLineCnt.1 = 0        ;;Init this files counter
#DefineRexx 'HOOK_OUTPUT'
   if OutputState = 'START' then
   do
       ;--- Starting new file with #output ----------------------------------
       call Debug "HOOK_OUTPUT:SAVE  - Level = " || @@level || ', Counter = ' || @@BlankLineCnt.@@Level;
       @@Level                = @@Level + 1
       @@BlankLineCnt.@@Level = 0
   end;
   if OutputState = 'END' then
   do
       ;--- Finished the file -----------------------------------------------
       @@Level = @@Level - 1
       call Debug "HOOK_OUTPUT:RESTORE - Level = " || @@level || ', Counter = ' || @@BlankLineCnt.@@Level;
   end;
#DefineRexx

;--- Define transform code --------------------------------------------------
#DefineRexx 'Rexx4#TRANSFORM=Max1BlankLine'
   ;--- Remove leading & trailing spaces ------------------------------------
   FileLine = strip(FileLine);

   ;--- Blank line logic ----------------------------------------------------
   if  FileLine = '' then
   do
       ;--- Always remove blank lines here ----------------------------------
       @@BlankLineCnt.@@Level = @@BlankLineCnt.@@Level + 1;
       Remove = 'Want at most one blank line (no trailing blank lines either!)!'
   end;
   else
   do
       ;--- Have a non-blank line (any blank lines to output?) --------------
       if  @@BlankLineCnt.@@Level <> 0 then
       do
           ;--- We need to output a single blank line -----------------------
           FileLine = MarksNewLine || FileLine;  ;;Add blank line to start
           @@BlankLineCnt.@@Level = 0
       end;
   end;
#DefineRexx
#define Max1BlankLine                                 \
        #RexxVar @@BlankLineCnt.@@Level = 0          -\
        #transform 'Rexx4#TRANSFORM=Max1BlankLine'
#define /Max1BlankLine \
        #transform
#NextId UNLOCK "MyTransformCode"


email me  any feedback, additional information or corrections.
See this page online (look for updates)

[Top][Contents][Search][Prev]: #RexxVar[Next]: #undef


PPWIZARD Manual
My whole website and this manual itself was developed using PPWIZARD (free preprocessor written by Dennis Bareis)
Sunday November 05 2017 at 10:00am