home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / ppw1320.zip / ppwizard.inf (.txt) next >
OS/2 Help File  |  2001-11-16  |  521KB  |  19,116 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. Introduction ΓòÉΓòÉΓòÉ
  3.  
  4. Introduction 
  5.  
  6. This is a generic preprocessor which allows you to use some very powerful 
  7. features such as "#if", "#define" and "#include". The preprocessor is known to 
  8. work under: 
  9.  
  10.        1. Windows NT/2000 
  11.        2. Windows 95/98/ME 
  12.        3. OS/2 
  13.        4. UNIX (including Linux, FreeBSD, Solaris) 
  14.        5. BeOS 
  15.        6. Windows 3.1 (use DOS) 
  16.        7. DOS 
  17.  
  18.  PPWIZARD is more powerful than virtually any other preprocessor available and 
  19.  unlike many others remains simple to use (no complicated syntax); its 
  20.  replacement syntax is HTML like. 
  21.  
  22.  PPWIZARD can be particularly useful for people who like to hand code their 
  23.  HTML and use an HTML editor. The use of a GUI-based editor does not, however, 
  24.  rule out PPWIZARD's use and some editors allow you to define your own tags 
  25.  (allowing you to add PPWIZARD's tags and commands). 
  26.  
  27.  The free "Regina" interpreter is required for operating systems other than 
  28.  OS/2 (this is installed for you under Windows). 
  29.  
  30.  Before I go further, if it all starts to sound complicated (and it certainly 
  31.  can be) then please check out the Beginners Guide section (you may wish to 
  32.  look at some of the sites PPWIZARD users have created at 
  33.  http://www.labyrinth.net.au/~dbareis/ppwusers.htm). Since PPWIZARD is a 
  34.  generic tool, using it can be as easy or as hard as your level of experience 
  35.  can handle. Even at its simplest level PPWIZARD can easily save you heaps of 
  36.  time, not only initially building a site, but in keeping it up to date and 
  37.  running (where you will find all the work actually is). 
  38.  
  39.  This preprocessor is commonly used as an HTML preprocessor as well as a REXX 
  40.  preprocessor, however there is no reason why this one preprocessor can't 
  41.  handle almost any file you have around (example: you can change the 
  42.  preprocessor to use "!if" etc and leave "#if" commands alone if you wish). 
  43.  
  44.  Most people would probably find the #include and #define commands the most 
  45.  useful, as they could be used to ensure that you need never specify something 
  46.  more than once.  For example, you might refer to a specific link (or image) in 
  47.  tens of places in different HTML pages but you can define it in one place. 
  48.  When you need to change it you make the one change and regenerate the HTML. 
  49.  It's not just easier and fast, it eliminates mistakes. You could set up your 
  50.  source and have automatic checking of the existence of any resources on your 
  51.  web page (no incorrect links). 
  52.  
  53.  The "#if" support is much more powerful than that of any other preprocessor 
  54.  due to the fact that what it executes is REXX code. What this means is that 
  55.  any REXX expression can be called, including your own REXX procedures.  The 
  56.  "#evaluate" command allows you to parse files or do whatever you need to in 
  57.  order to obtain the text you wish to use in your HTML. 
  58.  
  59.  You can use this program to produce different versions of your HTML pages for 
  60.  different locations.  For example, for an offline copy you may not want to 
  61.  have links to internet sites or may want to have different links. The 
  62.  preprocessor could be used in conjunction with an HTML editor, however it is 
  63.  most useful for power users. 
  64.  
  65.  This tool can be used to automatically calculate image widths and heights, 
  66.  file sizes, or file dates and times, and basically do all the drudge work (the 
  67.  stuff most likely to otherwise quickly become out of date). 
  68.  
  69.  By default excess leading spaces are removed from the output file so that you 
  70.  can format the input as much as you like without impacting download speed. 
  71.  
  72.  If you can't explain why an error message is being displayed or your code is 
  73.  not generated as you'd expect then I highly recommend you try the "/debug" 
  74.  command line switch.  I'd also like the debug output if you report problems. 
  75.  
  76.  If you have used a previous version of the preprocessor then I'd recommended 
  77.  you examine the change history section to determine what changes might affect 
  78.  you. 
  79.  
  80.  Please see my web page at http://www.labyrinth.net.au/~dbareis/ppwizard.htm 
  81.  for the latest copy of this program or contact me (Dennis Bareis) via e-mail 
  82.  (dbareis@labyrinth.net.au). I value feedback from users. 
  83.  
  84.  If the examples in this INF version of the documentation don't look correct 
  85.  (fonts overlap, etc.) then you have removed "Courier 8' font from your 
  86.  operating system.  Please restore it... 
  87.  
  88.  Note that I would have loved to have written this in Java, however as a 
  89.  compiled language it does not have an "interpret" instruction. Apparently 
  90.  something is being added to version 1.2 which might allow something similar; 
  91.  I'll have a look then.  The "interpret" instruction is important as it allows 
  92.  the preprocessor to be extended as well as doing a lot of work I'd otherwise 
  93.  need to do myself (and I wouldn't do it as well).  I will not be rewriting the 
  94.  preprocessor in Java (as it wouldn't be compatible with the REXX version), but 
  95.  with any luck I'd be able to write any similar future stuff in Java.... 
  96.  
  97.  
  98. ΓòÉΓòÉΓòÉ 1.1. Operating System Status ΓòÉΓòÉΓòÉ
  99.  
  100. Operating System Status 
  101.  
  102. This free html preprocessor runs natively under OS/2 or under the free Regina 
  103. interpreter (available at "http://www.lightlink.com/hessling"). You may wish to 
  104. have a look at a list of some of the operating systems PPWIZARD users use 
  105. (http://www.labyrinth.net.au/~dbareis/ppwusers.htm). 
  106.  
  107. Note that I only expect the PPWIZARD program to work correctly on the native 
  108. OS/2 or Regina REXX interpreters. 
  109.  
  110. Note that Regina looks in the directories mentioned in the "REGINA_MACROS" 
  111. environment variable for REXX scripts if they are not in the current directory 
  112. (it does not use the "PATH" environment variable). Unless "ppwizard.rex" is 
  113. located in a path mentioned in "REGINA_MACROS" then a command such as 
  114. "regina ppwizard tryme.it" will fail unless PPWIZARD is in the current 
  115. directory. Of course it will also fail if "regina" is not in one of the 
  116. directories mentioned in the "PATH" environment or in the current directory. 
  117.  
  118. Your Source 
  119.  
  120. I have made the preprocessor cross platform. This means that PPWIZARD will run 
  121. across many platforms, but does not mean that your source will build correct 
  122. output for multiple platforms. There are issues that you will need to take care 
  123. of to ensure that your code is cross platform also (if you care)! 
  124.  
  125. As an example of a mistake you could easily have made, you could have used the 
  126. OS/2 "filespec()" routine instead of the PPWIZARD "_filespec" call. The 
  127. resulting output would function correctly only on the OS/2 platform. 
  128.  
  129. Status Under OS/2 
  130.  
  131. Works like a champ! 
  132.  
  133. Regina - All Operating Systems 
  134.  
  135. Some things that are currently disabled are: 
  136.  
  137.          /FILTERINPUT 
  138.          /FILTEROUTPUT 
  139.          #MacroSpace 
  140.  
  141.  Some other situations not fully supported yet: 
  142.  
  143.          No colors used by default (except under OS/2).  You could try 
  144.           "/Color" but it may not work. 
  145.  
  146.          PPWIZARD is not expected to work under old versions of Regina. Use 
  147.           supported versions and none before version "0.08f". 
  148.  
  149.  Status Under Windows XP 
  150.  
  151.  I don't expect any issues. 
  152.  
  153.  Status Under Windows NT/2000 
  154.  
  155.  No known issues. I now do all development and testing under Windows 2000. 
  156.  
  157.  Example command when "W32SETUP" has been used to install PPWIZARD is: 
  158.  
  159.       ppwizard  tryme.it
  160.  
  161.  Status Under Windows ME 
  162.  
  163.  No known issues. It has been tested. Works as per Windows 98. 
  164.  
  165.  Status Under Windows 98 
  166.  
  167.  People are happily using it under Windows 98. Works as per Windows 95. 
  168.  
  169.  I believe Windows 98 has the same 5 or 6 year old bug with its command 
  170.  processor as Windows 95 (see below). 
  171.  
  172.  Status Under Windows 95 
  173.  
  174.  PPWIZARD under Windows 95 works exactly like the DOS version. 
  175.  
  176.  It appears that a bug in Windows 95 (thanks Microsoft!) might prevent you 
  177.  getting the return code and so automatically determining if everything worked 
  178.  or not. Obviously games don't require return codes! 
  179.  
  180.  As for all non-NT based Windows releases, you will have to preceed the 
  181.  PPWIZARD command with "regina". Example command command is: 
  182.  
  183.       regina ppwizard  tryme.it
  184.  
  185.  Status Under Windows 3.1 
  186.  
  187.  Use DOS version of Regina. 
  188.  
  189.  Status Under DOS 
  190.  
  191.  My own web site is reasonably complex and the DOS (DPMI) version has 
  192.  successfully compiled it. 
  193.  
  194.  Had to increase DMPI memory to do my whole site in one hit (*.IT), if you have 
  195.  a similar problem just call PPWIZARD many times (maybe processing "A*.IT B*.IT 
  196.  ... K*.IT" in one go and the rest the next. You get the idea!  An even simpler 
  197.  method would be to use dependancies (/DependsOn); this way if you run out of 
  198.  memory, you simply restart the build and it will pick up from where it left 
  199.  off. 
  200.  
  201.  Status Under Unix 
  202.  
  203.  All command line switches can be specified using '-' or '/'. I believe that 
  204.  PPWIZARD will run under all unix operating systems (although some may need 
  205.  some tweeking such as with SunOS). 
  206.  
  207.  I either test under or have reason to believe that PPWIZARD works under: 
  208.  
  209.        1. Linux 
  210.           Known to work with RedHat: 
  211.               5.1 
  212.               5.2 
  213.               6.2 Ultrasparc Linux (64-bit kernel) 
  214.        2. FreeBSD 
  215.        3. SunOS 
  216.           Tested on SunOS 5.8 (64 bit enabled) using GNU "find" version 4.1 (64 
  217.           bit) in place of Sun's regular "find". If you do not wish to change 
  218.           the "find" command (which appears to be very non-standard) you could 
  219.           use a /Hook of "GetFileList". 
  220.        4. TSO 
  221.           I am modified PPWIZARD for it to work on REXX370 on OS390/zOS (Unix 
  222.           environment - omvs?). It may or may not work (at least for routine 
  223.           things). Let me know if you try - PLEASE. I now think it probably 
  224.           won't - yet. 
  225.  
  226.  You will need to obtain the Regina source code and compile it (there are now 
  227.  binaries in Red Hat package manager format). All my testing used the generated 
  228.  "REXX" program. The source can be obtained from my 
  229.  http://www.labyrinth.net.au/~dbareis/regina.htm. 
  230.  
  231.  Note that temporary files are put into the directory identified by the "TMP" 
  232.  environment variable, you must have write access to this. If the environment 
  233.  variable does not exist then files are placed into the "/tmp" directory. 
  234.  
  235.  If you have any problems (such as PPWIZARD not locating the input file) then 
  236.  you may need to use the /RedirMethod switch. 
  237.  
  238.  You may need to use /Hook (for "GetFileList"); if you need to use this to get 
  239.  PPWIZARD going then let me know (I need "-debug" output) and I'll fix it. 
  240.  
  241.  As with all operating systems, I am keen to fix any problems. Unix is a bigger 
  242.  unknown to me with all its different shells, etc. 
  243.  
  244.  If you have a problem, please use the "-debug" command line switch and 
  245.  redirect the command's output, along with the name of the shell you are using 
  246.  and any other relevant details (all zipped please). I will typically have a 
  247.  fix for you in a few days and maybe a workaround even faster. 
  248.  
  249.  Status Under BeOS 
  250.  
  251.  Looks like Unix to PPWIZARD. No known issues. 
  252.  
  253.  Status Under Amiga 
  254.  
  255.  Not supported however as regina is available for this operating system I am 
  256.  waiting for someone to offer to perform testing for me etc. It is not expected 
  257.  to be difficult to ensure PPWIZARD works on the Amiga. 
  258.  
  259.  Status Under Macintosh OS X 
  260.  
  261.  Maybe... It sounds like the operating system is Unix based and Regina works on 
  262.  this operating system. 
  263.  
  264.  Let me know if you try, if it doesn't work it shouldn't need nuch tweeking to 
  265.  get going. 
  266.  
  267.  Status Under AIX 
  268.  
  269.  May or may not work (probably does), regina is available. Anyone using it on 
  270.  AIX? 
  271.  
  272.  Status Under HP-UX 
  273.  
  274.  May or may not work (probably does), regina is available. Anyone using it on 
  275.  HP-UX? 
  276.  
  277.  Status Under QNX 
  278.  
  279.  May or may not work, regina is available. Anyone using it on QNX? 
  280.  
  281.  Other Operating Systems 
  282.  
  283.  If Regina works on your operating system, but your operating system is not 
  284.  listed above, then contact me. 
  285.  
  286.  If you are prepared to help (test changes, etc.), then I will try to get it to 
  287.  work for you. Before contacting me please download the latest "rexx4ppw" 
  288.  package from http://www.labyrinth.net.au/~dbareis/ppwizard.htm and send me the 
  289.  redirected output. 
  290.  
  291.  Problems 
  292.  
  293.  When reporting problems please run the preprocessor with the "/debug" flag and 
  294.  give the the command line used, the redirected output, and the source file(s). 
  295.  
  296.  
  297. ΓòÉΓòÉΓòÉ 1.2. Change History ΓòÉΓòÉΓòÉ
  298.  
  299. Change History 
  300.  
  301. Please note that my version numbers are of the format "YY.DDD" where "YY" 
  302. represents the year and "DDD" is the day of the year (1-366). While this format 
  303. does not let you know of the magnitude of any changes (my change history shows 
  304. this) it does make it simple to know the "age" of a release. <P>Please let me 
  305. know of any bugs or issues and do not assume that someone else has reported it. 
  306. I have fixed all known bugs/issues. The very fact that you are having a problem 
  307. means that I probably do not know of it! In rare cases I do get snowed under 
  308. and forget things, in this case remind me! 
  309.  
  310.        1. Version "Next Release" 
  311.  
  312.               You tell me, feedback please! 
  313.                Have you ever looked at a product and said "Wouldn't it be nice 
  314.                if ...", well get on your backside and send an email, make it 
  315.                so! I'm not always right and believe it or not I don't mind 
  316.                being told so. 
  317.               Your idea here :-). 
  318.  
  319.        2. Version 01.320 
  320.  
  321.               Fix to base directory validation problem in 01.316 when filemask 
  322.                began with '+'. 
  323.               New "/COPY" switch (binary copy). 
  324.               All processing mode switches (/COPY, /HTML, /OTHER and /REXX) as 
  325.                well as /DependsOn and /OUTPUT can now be specified per input 
  326.                mask. Extra code ensures backwards compatability. 
  327.               The /Making switch is completely different. Default text now 
  328.                uses long output name and includes processing mode. 
  329.  
  330.        3. Version 01.316 
  331.  
  332.               The 'for' and 'set' "loops" would always go though at least 
  333.                once. Also improved "empty" set handling. 
  334.               Output files created last run are now deleted by default on 
  335.                following build. New /DeletePrev switch to change this. 
  336.               New /BaseDir switch (or "{ENDBASE}" filemask text) to allow you 
  337.                to process subtree easier. New "<?BaseDir>" definition to allow 
  338.                you to access the information. Removed limitation which 
  339.                restricted use of "{$path}" specs (its up to you to only use 
  340.                where appropriate). 
  341.               New /OutHeader switch. This can add/alter or remove headers into 
  342.                output files. 
  343.               Output Headers are now generated for files generated with the 
  344.                #output command (also see "NoHeader" parameter). 
  345.               A default output header is now added to any file with extension 
  346.                ".VBS" (assumed to be VbScript). 
  347.               Improved error reporting where "rexxsql.dll" can't be loaded (on 
  348.                regina versions which don't crash...). 
  349.  
  350.        4. Version 01.309 
  351.  
  352.               The _SysFileTree() routine was not working under native OS/2 
  353.                rexxes. This would have prevented a few add-ons from working 
  354.                ("FTPLIKE" and anything relying on it). 
  355.               Macros in any parameters passed on the " #{" command are now 
  356.                replaced. Syntax tweeked to allow you to access the internal 
  357.                loop counter which exists anyway. 
  358.               More internal redesign to simplify porting. 
  359.  
  360.        5. Version 01.302 
  361.  
  362.               Made a lot of internal changes to try to port to REXX370 on IBM 
  363.                OS390 unix environment (omvs?), this has modified a fair bit of 
  364.                code for all operating systems. PLEASE let me know of any 
  365.                issues. 
  366.               The #{ command has been extended to support "set" loops. This 
  367.                can also be used to bypass the commands nesting issue as it can 
  368.                effectively provide you with a "flat" nested (to any level) 
  369.                loop. 
  370.               New ArraySplit(), ArrayRemoveDup() and ArrayTranslate() 
  371.                routines. 
  372.               Windows install changes: 
  373.                  -  In non-english countries the start menu items were 
  374.                     incorrectly going into the "programs" folder (should have 
  375.                     gone into "Programme" for German etc). 
  376.                  -  New version of regina (2.2) now in Windows package. 
  377.               Looks like I've been using the 2.2 beta as PPWIZARD would fail 
  378.                on some operating systems with the recently downloaded GA regina 
  379.                version 2.2 (the uname() BIF changed between the beta I was 
  380.                using and the official release - what is worse is that I 
  381.                requested the change!). I have corrected this problem. 
  382.               New definition of "<?OpSysSpecific>", this holds the "real" 
  383.                operating system for example if the "<?OpSys>" symbol contains 
  384.                "UNIX", then this symbol might contain "FREEBSD" or "TSO". 
  385.                PPWIZARD now uses this value internally in most places. 
  386.               Updated /#Include handling so that <?InputFile> can be used in 
  387.                included files. 
  388.               The #{ 'FOR' command has been improved to handle rexx variables 
  389.                that start with "_" or other valid non alpha characters. 
  390.               Modified #import so as not to generate blank lines where you 
  391.                might have been trying to restrict the generated output. 
  392.               Better formatting of any trapping rexx being evaluated in 
  393.                console or error file output. 
  394.               Default quote debug characters now set to some quite "safe" 
  395.                non-blank characters. 
  396.               You may need to modify your source, see following issues: 
  397.                  a. While unlikely you might need to modify any existing use of 
  398.                     "<?OpSys>". It will no longer contain "WIN95 - WINXP" but 
  399.                     only "WIN32" (for all). To get the specific operating 
  400.                     system information you will need to use "<?OpSysSpecific>". 
  401.  
  402.        6. Version 01.281 
  403.  
  404.               Windows install changes: 
  405.                  -  For install on Windows NT/2000, PATHEXT updating is now 
  406.                     done last, if this fails all other setup has still been 
  407.                     done. I will come up with something better in future. 
  408.                     Anyone know of any reliable way of doing so (maybe 
  409.                     utility)? 
  410.                  -  For install on Windows 95/98/ME, made "PATH" updating 
  411.                     smarter so it won't update variables like "INFOPATH". 
  412.                  -  For install on Windows 95/98/ME, added work around for 
  413.                     "Failed making backup copy" problem. It appears that WinME 
  414.                     at unknown times can set the hidden attribute on 
  415.                     autoexec.bat. We now remove any hidden or read-only 
  416.                     attributes and use the "type" command in place of "copy". 
  417.  
  418.        7. Version 01.269 
  419.  
  420.               The installer for Windows now defaults the install directory for 
  421.                PPWIZARD to "C:\PPW" for DOS versions (Windows 95/98/ME). Other 
  422.                changes (to registry) to decrease the length of the command line 
  423.                allowing you to use longer filenames. Note Windows NT/2000/XP 
  424.                etc have no restrictions on file size. If upgrading you may wish 
  425.                to remove "C:\Program Files\PPWIZARD" from the PATH environment 
  426.                variable in "\AUTOEXEC.BAT". 
  427.               Minor change to the MakeWebLinks() routine to add "-" (minus) to 
  428.                characters that are valid in a URL. 
  429.               Documented existing GetQuotedText() and GetQuotedRest() 
  430.                routines. 
  431.  
  432.        8. Version 01.247 
  433.  
  434.               The #( command can now be nested. 
  435.               Minor fix to improve error message if the file specified on a 
  436.                /Template switch does not exist. 
  437.               Fixed another minor error reporting bug which occurred if 
  438.                ppwizard initialization failed very early. 
  439.  
  440.        9. Version 01.213 
  441.  
  442.               Fixed "T2H" and "WRAP" bug in #import ("DOPASS2" undefined). 
  443.  
  444.       10. Version 01.211 
  445.  
  446.               Created new StackPush() and StackPop() routines which can be 
  447.                used to store information or for validation where steps must be 
  448.                executed in pairs. 
  449.               New "#PUSH and #POP stack commands to allow easier saving of 
  450.                macros and rexx variables. 
  451.               The above mentioned stack changes have pretty much obsoleted the 
  452.                "PUSHPOPM.H" and "NESTCHK.H" add-ons. The functionality was 
  453.                moved into PPWIZARD to improve the performance of my 
  454.                BOOKMARK/FTPLIKE add-ons and PPWIZARD has some similar 
  455.                validation code internally which I will eventually update to use 
  456.                the new code. 
  457.  
  458.       11. Version 01.204 
  459.  
  460.               The #{ command has been extended to support simple "for" loops. 
  461.               A new "*PpwPgm" dependancy type. This is used to replace the old 
  462.                method of depending on the version of ppwizard being used as 
  463.                this did not cover all possibilities. 
  464.               A new "*Rexx" dependancy type which can execute rexx 
  465.                expression(s). 
  466.               Added/reorganised some debug code. Fixed undocumented "DEBUG" 
  467.                command. 
  468.  
  469.       12. Version 01.197 
  470.  
  471.               Fixed a recently introduced bug which affected users using the 
  472.                OS/2 object rexx interpreter (incorrectly formatted call to 
  473.                "value"). 
  474.               Removed some caching of file timestamps, this removes a minor 
  475.                glitch which occured where a file is read if it exists and 
  476.                created if not. 
  477.               Updated masks that GenerateFileName() can handle and all 
  478.                switches etc that rely on it. 
  479.               A new "*CmdLine" dependancy type. This check is performed when 
  480.                /DependsOnComplete is ON (the default). 
  481.  
  482.       13. Version 01.187 
  483.  
  484.               Updated '{$?}' to correctly quote strings that contain both 
  485.                single and double quotes. 
  486.  
  487.       14. Version 01.183 
  488.  
  489.               New Dependancies filter capability if a rexx macro called 
  490.                HOOK_DEPENDSON exists. 
  491.  
  492.       15. Version 01.152 
  493.  
  494.               Fixed bug in Multi line import record filter where a EOF 
  495.                "command" to ignore the rest of the database was being ignored. 
  496.  
  497.       16. Version 01.135 
  498.  
  499.               The "*expires" dependancy cmd has been much improved. 
  500.               New TimeStamp() routine. 
  501.               Improved PPWIZARD Command line so that you can now use a number 
  502.                of characters to quote filenames or switches that may contain 
  503.                spaces (not just double quotes which for example don't always 
  504.                work under Windows/Regina). 
  505.               Oops, accidentally disabled custom installs under Windows. 
  506.               The "right click" build options would fail in Windows NT/2000 if 
  507.                the directory or filename contained spaces (this was not an 
  508.                issue under Windows 95/98/ME). 
  509.  
  510.       17. Version 01.129 
  511.  
  512.               A new dependancy type of "TODAY" added to "#DependsOn" command. 
  513.               The #{ command would fail if used within a macro which expanded 
  514.                during #OnExit processing (could not locate end of loop). 
  515.  
  516.       18. Version 01.120 
  517.  
  518.               Fixed call to "OptionSetValue" around line 9930 which would fail 
  519.                under OS/2 using OREXX. 
  520.  
  521.       19. Version 01.112 
  522.  
  523.               Major improvement to "#OnExit" command. 
  524.               Windows Install updated. 
  525.  
  526.       20. Version 01.102 
  527.  
  528.               New /UNC switch which turns off path slash reduction to allow 
  529.                UNC names etc. 
  530.               Some #( related improvements. 
  531.               Improved GetAmPmTime() and GetAmPmTimeFromHhMmSs() routines. 
  532.               You can now specify multiple lines of output on the #error 
  533.                command. 
  534.               Removed most of the "PPWIZARD Extensions" section, I will 
  535.                probably eliminate it altogether soon. 
  536.  
  537.       21. Version 01.091 
  538.  
  539.               New #( & #) commands. These are replacements for #OneLine & 
  540.                #OneLineEnd (although these will continue to exist - at least 
  541.                for a while). 
  542.               New MakeWebLinks() routine to simplify processing of http & ftp 
  543.                addresses. 
  544.               New QueryExists() routine to simplify checking file existence 
  545.                (getting full path). 
  546.               Default of previous error file being deleted was not working 
  547.                correctly. 
  548.               Minor change to UrlEncode(). 
  549.  
  550.       22. Version 01.083 
  551.  
  552.               New $$RXEXEC "$$" macro command which allows rexx code to be 
  553.                directly executed without requiring the usual annoying "linking" 
  554.                #evaluate command. 
  555.               New BD2DATE() routine and the BaseDate() routine was rewritten 
  556.                (no bug just better code). 
  557.               New AddTempFileToDependancyList() routine which allows you to 
  558.                indicate temporary files which should be ignored by PPWIZARD. 
  559.                The #DependsOn command also updated. 
  560.               New "<?PpwizardAuthorBaseWebDir>" 
  561.               In "quiet" mode PPWIZARD no longer displays overall summary when 
  562.                no files were made. 
  563.               You may need to modify your source, see following issues: 
  564.                  a. The change above for the $$RXEXEC command required me to 
  565.                     alter how "$$" macro commands are handled. The exact 
  566.                     mechanism was not documented before so if you were relying 
  567.                     on the action taking place BEFORE parameter subtitution 
  568.                     then you should note that it now occurs AFTER! It is 
  569.                     probably more "right" now. If you think it might be wise to 
  570.                     allow for both let me know. 
  571.  
  572.       23. Version 01.072 
  573.  
  574.               New "GetDependancyInfo()" routine allows you to access input and 
  575.                output file dependancy information. 
  576.               "#NextId" command tweeked so that value is only incremented if 
  577.                it was actually used. 
  578.               New /Making switch. 
  579.               You can now comment out items on the command line to aid in 
  580.                testing. 
  581.               Minor change to fix ppwizard name in Copyright banner on non 
  582.                OS/2 systems. 
  583.  
  584.       24. Version 01.059 
  585.  
  586.               Fixed a bug preventing ppwizard running on OS/2 (native rexx). 
  587.                OS/2 problem probably introduced in the 01.036 version. Root 
  588.                cause probably earlier, self corrected but code now modified so 
  589.                can't happen again. 
  590.               Changed "$trace" code generation so that it should now never 
  591.                produce invalid rexx or ppwizard code. This mainly affects 
  592.                blocks of rexx code that also expanded other macros or complex 
  593.                parameters. 
  594.  
  595.       25. Version 01.049 
  596.  
  597.               By default PPWIZARD now deletes generated files if an error 
  598.                occurs. You can control this via the new /DeleteOnError switch. 
  599.               Command line switches can now start with either '-' or '/' in 
  600.                all operating systems. 
  601.               When '-' used on /DependsOn switch, the copyright will not 
  602.                display unless there is work to do (ie ppwizard is quiet). 
  603.               New option to not strip leading spaces from the value in a 
  604.                Multi Line import. 
  605.               Added option which allows you to disable PASS2 processing on 
  606.                #import. 
  607.  
  608.       26. Version 01.036 
  609.  
  610.               Fixed bug in "_SysFileDelete()", it would not correctly delete a 
  611.                file containing spaces in all operating systems except OS/2. 
  612.                This would sometimes have prevented an output file being built 
  613.                where the directory or file components contained spaces. 
  614.               New "MustDeleteFile()" routine. 
  615.               New "#option" of ParmVal. 
  616.               New "OptionGet()" and "OptionSet()" routines. 
  617.  
  618.       27. Version 01.029 
  619.  
  620.               Fixed up glitch with OS/2 install batch file. 
  621.               Updated doco for #import SQL to show how you can access Excel 
  622.                Spreadsheets and text based databases such as command seperated 
  623.                value files. 
  624.               Added an example of how bar or pie charts can be automatically 
  625.                created under Windows and saved as "GIF" or "JPG". 
  626.               You may need to modify your source, see following issues: 
  627.                  a. The "Die When Unused Parms" validation had a minor bug and 
  628.                     has now been enhanced, a number is no longer accepted. 
  629.  
  630.       28. Version 01.022 
  631.  
  632.               The "expand all macro parameters as rexx code" would fail under 
  633.                regina if a parameter had a very long value. 
  634.               New SStrip() routine. 
  635.               New Add2() routine. 
  636.               New LoadRexxSql() routine. 
  637.               New "ID3.H" addon which can read ID3 version 1 and 1.1 tags 
  638.                (typically used on MP3 files for song title etc). 
  639.               Fixed up a few "case" related issues with Unix, not in ppwizard 
  640.                itself but in "tryme.it" etc. 
  641.               Added example of automatically reading EXCEL spreadsheet via 
  642.                VbScript. 
  643.               Minor change to "<?SemiColon>" code, not backwards compatible 
  644.                however extremely unlikely to affect anyone. 
  645.  
  646.       29. 01.013 
  647.  
  648.               While you could always perform SQL imports directly with rexx 
  649.                code, I have now simplified the process by updating the #import 
  650.                command making it very simple to perform imports of SQL data 
  651.                from MS Access etc. Other minor import tweeks. 
  652.               New ErrorSQL() routine to dump information on SQL errors. 
  653.               New SetXCode() routine makes it easier to make a large number of 
  654.                definitions. 
  655.  
  656.       30. 01.007 
  657.  
  658.               New "Die When Unused Parms" macro validation. 
  659.               The "Expand All Unused Parameters" tag no longer marks 
  660.                parameters as being used. Also note there is now also a tag 
  661.                which will reset "used" state. 
  662.               Fixed and enhanced "expand all macro parameters as rexx code". 
  663.               More tweeking of Windows install package. The "PPWW32.ZIP" 
  664.                download now simply wraps the "EXE", the ZIP file exists only to 
  665.                cater for the many sites that point to it. There is now a simple 
  666.                debug option as well as a "no setup" option. 
  667.  
  668.       31. 01.002 
  669.  
  670.               Added a Wise Installer OLE automation example which allows you 
  671.                to generate MSI (Windows Installer) packages via a simple "user 
  672.                friendly" script. VbScript (no knowledge of this language is 
  673.                required) is generated which is then executed from the command 
  674.                line or make files to generate the MSI (and WSI) files. 
  675.               Fixed bug in /ConsoleFile switch and improved logic a bit. 
  676.               Changed FindFileInPath() routine to allow you to specify 
  677.                directory trees to be searched. 
  678.               The "FILEINFO.H" header was changed so that not only can you 
  679.                specify a path but you can also specify a search path (as per 
  680.                FindFileInPath()). This should not effect any existing use of 
  681.                the header. 
  682.               Changed the FindFile() routine to always search relative to 
  683.                current directory first (while slightly less flexible, this 
  684.                makes it more efficient). 
  685.               New "expand all macro parameters as rexx code" facility. 
  686.               New "Expand Macro Name" facility. 
  687.               Changed GetEnv() routine to log use when debug is on. This makes 
  688.                it easier to understand ppwizard's use of environment variables 
  689.                as well as your own. 
  690.               Fixed minor bug in handling of "$$" macro commands. 
  691.               Added "rexx stem" like example to "Macros With Optional 
  692.                Parameters". 
  693.               Better trap output is written to console/error files. 
  694.               More tweeking of Windows install package. 
  695.  
  696.  Older Entries Than Those Above 
  697.  
  698.  If you need to see older entries then please have a look at my html 
  699.  documentation as I had to remove this information from the IPF/INF version due 
  700.  to compiler problems. 
  701.  
  702.  
  703. ΓòÉΓòÉΓòÉ 1.3. Installing PPWIZARD ΓòÉΓòÉΓòÉ
  704.  
  705. Installing PPWIZARD 
  706.  
  707. Please see one or more of the following sections: 
  708.  
  709.        1. Hand Installation 
  710.  
  711.        2. Window's Install 
  712.  
  713.        3. OS/2 Install 
  714.  
  715.  
  716. ΓòÉΓòÉΓòÉ 1.3.1. Hand Installation ΓòÉΓòÉΓòÉ
  717.  
  718. Do I need to hand install at All? 
  719.  
  720. There are some special setup programs or information available for these 
  721. operating systems: 
  722.  
  723.          OS/2 
  724.          Windows 95/98/ME/NT/2000 
  725.  
  726.  If your operating system is listed above please read the appropriate section 
  727.  before proceeding. If it is not listed, any information you can provide will 
  728.  help write a new section for your operating system for others. 
  729.  
  730.  Looks like I need to hand install! 
  731.  
  732.  This section describes how to install PPWIZARD so it can be used from a 
  733.  command line or batch file. Windows and OS/2 setup programs do extra work to 
  734.  set up PPWIZARD so that they can be used via their graphical shells (Windows 
  735.  Explorer and OS/2 WPS); this sort of setup would be perfectly possible in any 
  736.  operating system and while only a minor tweek to what is done for OS/2 or 
  737.  Windows is not described here (maybe in the future - any help appreciated...). 
  738.  
  739.  Note: to simplify installation and testing I suggest that Regina and PPWIZARD 
  740.  be installed into the same directory. 
  741.  
  742.  The information shown here can be applied to any operating system supported by 
  743.  PPWIZARD. 
  744.  
  745.  There is one and only one PPWIZARD runtime (distributed as "PPWIZARD.REX"), 
  746.  this runs on all operating systems. PPWIZARD detects the operating environment 
  747.  (REXX interpreter and operating system) and executes accordingly. 
  748.  
  749.  REXX Interpreter 
  750.  
  751.  PPWIZARD requires a REXX interpreter, only the following are supported: 
  752.  
  753.          Native OS/2 interpreters 
  754.           Of course no installation required for these! 
  755.  
  756.          Regina 
  757.           This is a free product which you will need to obtain. Download this 
  758.           from http://www.lightlink.com/hessling/. Note that if you already use 
  759.           a different REXX interpreter then Regina should be able to run 
  760.           alongside it, as it has few requirements. 
  761.  
  762.           For ease of use Regina should be installed in a directory that is in 
  763.           your path as this means that you will not have to enter the full name 
  764.           of the program but can just enter "regina". 
  765.  
  766.           The directory containing PPWIZARD should also be in the path as well 
  767.           as the Regina environment variable REGINA_MACROS. 
  768.  
  769.  Note that if Regina can't find PPWIZARD, it comes up with a message similar 
  770.  to: 
  771.  
  772.          Error 3 running "ppwizard.rex": Failure during initialization
  773.          Error 3.1: Failure during initialization: Program is unreadable
  774.  
  775.  If you see this message, PPWIZARD is not corrupt, it simply can't be located. 
  776.  Double check that the directory containing PPWIZARD is mentioned in Regina's 
  777.  REGINA_MACROS environment variable. 
  778.  
  779.  PPWIZARD 
  780.  
  781.          The directory containing PPWIZARD should be specified in the path. 
  782.  
  783.          Under OS/2, PPWIZARD has the extension ".CMD" and not the ".REX" that 
  784.           is used in all other operating systems. 
  785.  
  786.  TESTING PPWIZARD 
  787.  
  788.  PPWIZARD should display an error message (no files specified) if one of the 
  789.  following commands is used: 
  790.  
  791.          PPWIZARD 
  792.           This form should work in OS/2 as well as Windows NT and 2000. This is 
  793.           because these operating systems either know about how to execute REXX 
  794.           code or can be told. 
  795.  
  796.           Please tell me if you know how to configure other operating system to 
  797.           work this way. 
  798.  
  799.          REGINA PPWIZARD 
  800.           This form will be required in Windows 95/98/ME and DOS. Unix, BEOS, 
  801.           etc. probably also require this form. 
  802.  
  803.  If neither of the above two commands work, then the chances are you have made 
  804.  a mistake in configuration or you haven't rebooted since your last change. If 
  805.  it still fails after a reboot, change to the directory where you installed 
  806.  Regina and PPWIZARD and try again. If you can't work it out then contact me 
  807.  (dbareis@labyrinth.net.au) for help. 
  808.  
  809.  If one of the above works then please see the PPWIZARD command line section of 
  810.  the documentation for more information on how to run it. 
  811.  
  812.  
  813. ΓòÉΓòÉΓòÉ 1.3.2. Window's PPWW32.EXE ΓòÉΓòÉΓòÉ
  814.  
  815. Installing using PPWW32.EXE in Windows <p>The "PPWW32.EXE" download for windows 
  816. is a self extracting version which means that no separate unarchiving tool is 
  817. required. This contains the Regina interpreter, PPWIZARD, and documentation in 
  818. HTML format. 
  819.  
  820. Nothing prevents you hand installing PPWIZARD on Windows, however this download 
  821. makes the installation much easier and sets up the Windows shell so you can 
  822. work via Explorer if you wish. If you do hand install, then I assume my Windows 
  823. install is doing something you don't like; let me know and I will probably do 
  824. something about it. 
  825.  
  826. Note that the install process does not delete any files in the install 
  827. directory if it exists. If you wish, you could delete this first, however if 
  828. you have installed files from other downloads into this directory do not do 
  829. this! PPWIZARD has uninstall support. Simply uninstall it as you would any 
  830. other application. 
  831.  
  832. The install procedure is as follow: 
  833.  
  834.        1. Windows 95 users might need to download 
  835.           http://www.labyrinth.net.au/~dbareis/zip3rdp/msvcrt.exe. This is a 
  836.           self-extracting program which contains the Microsoft 'C' runtime 
  837.           (must be installed into the c:\windows\system directory). Check if it 
  838.           is already in your directory, if not then run this program to 
  839.           install. 
  840.  
  841.        2. If you have the EXE simply execute it to unzip the contents and run 
  842.           the installation. I recommend that you install into the default 
  843.           location of "C:\Program Files\PPWIZARD". 
  844.  
  845.        3. If you have the ZIP you need to unzip it with WinZip or similar tools 
  846.           and then run "SETUP.EXE" (a renamed PPWW32.EXE) to start the setup. 
  847.  
  848.        4. Follow bouncing ball. PPWIZARD creates a sample HTML page which it 
  849.           displays as part of the setup. 
  850.  
  851.        5. The install directory is added to the PATH and right click options 
  852.           appear in Explorer on "standard" extensions (see "PPW_95.RIT" or 
  853.           "PPW_NT.RIT", depending on which platform you are on, for details on 
  854.           these and other associations). 
  855.  
  856.        6. Reboot before using. 
  857.  
  858.        7. If you right click on ".IT", ".X" or ".PPW" file types the PPWIZARD 
  859.           build options should appear and work! 
  860.  
  861.  Shell Integration (Explorer context menus) 
  862.  
  863.  This doco needs more work, however if you right click on ".IT", ".IH", ".X", 
  864.  ".XH" or ".PPW" files you will see edit and build options that PPWIZARD has 
  865.  installed. 
  866.  
  867.  
  868. ΓòÉΓòÉΓòÉ 1.3.3. OS/2's OS2SETUP.CMD ΓòÉΓòÉΓòÉ
  869.  
  870. Setup PPWIZARD for OS/2 WPS 
  871.  
  872. Run "OS2SETUP.CMD" to install PPWIZARD for a graphical environment. 
  873.  
  874. This creates a PPWIZARD folder on the desktop with some doco icons plus an 
  875. "association" folder. 
  876.  
  877. I have left the association folder visible so you can see the icons along with 
  878. their associations. Do not delete these! 
  879.  
  880. Setup PPWIZARD for Command Prompt or Batch 
  881.  
  882. Unless you wish to specify the full path to Regina and PPWIZARD you will have 
  883. to update CONFIG.SYS for the "PATH" and "REGINA_MACROS" sections (see Hand 
  884. Installation). 
  885.  
  886.  
  887. ΓòÉΓòÉΓòÉ 1.4. FAQ ΓòÉΓòÉΓòÉ
  888.  
  889. PPWIZARD FAQ 
  890.  
  891. The following (currently short list) of questions are answered: 
  892.  
  893.        1. Can ppwizard accept options from a configuration file? Currently I 
  894.           have some very long command lines and it's hard to swap between 
  895.           frequently used configurations. 
  896.        2. I have a perfectly working series of lines that I wish to place into 
  897.           a macro. The macro takes one or more parameters so that I can 
  898.           generate many versions of the output. I use the example tags, #AsIs" 
  899.           or #AutoTag" commands but these don't seem to be working correctly. 
  900.           What am I doing wrong? 
  901.  
  902.  
  903. ΓòÉΓòÉΓòÉ 1.4.1. QUESTION #1 - Does PPWIZARD support config files? ΓòÉΓòÉΓòÉ
  904.  
  905. QUESTION #1 
  906.  
  907. Can ppwizard accept options from a configuration file? Currently I have some 
  908. very long command lines and it's hard to swap between frequently used 
  909. configurations. 
  910.  
  911. ANSWER 
  912.  
  913. You can use the /List switch to load files containing command line switches. 
  914. This method allows you to comment switches. You can include other list files 
  915. however no checking for infinite loops is performed. 
  916.  
  917. PPWIZARD can also accept switches from environment variables. In most operating 
  918. systems you can either put your options in "config.sys" or in a batch file 
  919. (such as "autoexec.bat") that you run for your project. 
  920.  
  921. You can create a whole range of different common options and select from them 
  922. as you wish, hopefully the following example demonstates the method: 
  923.  
  924.     @echo off
  925.  
  926.     REM *** YOU MIGHT WISH TO SET THIS IN "AUTOEXEC.BAT" ETC *******
  927.     SET PPWIZARD_OPTIONS=/beep /color:n
  928.  
  929.  
  930.  
  931.     REM *** NOW SET SOME OTHER STUFF ****
  932.     SET PPWDEBUG=/debug /option:DebugLevel{x3D}"-ALL"
  933.     SET   STUPID=/DependsOn:out\*.DEP
  934.     SET   OTHERS=/GetEnv:Stupid
  935.  
  936.     REM *** START PPWIZARD ***
  937.     if     "%1" == "" ppwizard *.IT  /GetEnv:OTHERS
  938.     if not "%1" == "" ppwizard %1.IT /GetEnv:OTHERS
  939.  
  940.     REM *** IF I'd wanted debug ***
  941.     goto Endbatch
  942.     if     "%1" == "" ppwizard *.IT  /GetEnv:PPWDEBUG /GetEnv:OTHERS
  943.     if not "%1" == "" ppwizard %1.IT /GetEnv:PPWDEBUG /GetEnv:OTHERS
  944.     :Endbatch
  945.  
  946.  
  947. ΓòÉΓòÉΓòÉ 1.4.2. QUESTION #2 - My macros are not generating output correctly? ΓòÉΓòÉΓòÉ
  948.  
  949. QUESTION #2 
  950.  
  951. I have a perfectly working series of lines that I wish to place into a macro. 
  952. The macro takes one or more parameters so that I can generate many versions of 
  953. the output. I use the example tags, #AsIs" or #AutoTag" commands but these 
  954. don't seem to be working correctly. What am I doing wrong? 
  955.  
  956. ANSWER 
  957.  
  958. The #AsIs and #AutoTag commands only work on data read directly from the a 
  959. file. This means that you may need to use a bit of trial and error (maybe 
  960. swearing a bit) and you can get it to work. 
  961.  
  962. What is probably easier is rather than creating a macro, put the information 
  963. into its own header file, then instead of macro parameters you simply #define+ 
  964. each "parameter" prior to each #include command. 
  965.  
  966.  
  967. ΓòÉΓòÉΓòÉ 1.5. Bugs, Problems or Suggestions ΓòÉΓòÉΓòÉ
  968.  
  969. Before asking questions, I would appreciate it if you'd ensure that your answer 
  970. was not in the FAQ or this manual! 
  971.  
  972. Requested Information - Bugs or Problems 
  973.  
  974. If reporting bugs/problems please supply: 
  975.  
  976.        1. A detailed description of the problem. Please don't bother wasting 
  977.           your and my time by telling me "it did not work". 
  978.  
  979.        2. All files involved (input, output, and any batch files used to run 
  980.           the preprocessor). You have hopefully trimmed out everything which is 
  981.           not required by me to recreate the problem. 
  982.  
  983.        3. When supplying the redirected output from PPWIZARD please ensure that 
  984.           you had used /DEBUG on the command line to turn on debug mode. 
  985.  
  986.  The easier you make it for me the faster I will be able to come up with a fix 
  987.  or tell you what you're doing wrong, etc. 
  988.  
  989.  Reporting Bugs/Problems or Suggestions 
  990.  
  991.  There are two main ways to report PPWIZARD issues or ask questions. They are: 
  992.  
  993.        1. PPWIZARD Discussion List 
  994.           People who are very interested in PPWIZARD can now join an e-mail 
  995.           based discussion group, any e-mail sent to ppwizard@egroups.com will 
  996.           be seen by all subscribers. Hopefully I won't have to answer them 
  997.           all, but if one person answers, everyone gets the benefit of the 
  998.           response. All messages are archived so you can always go back and see 
  999.           previous messages. I will also make announcements on this list. 
  1000.  
  1001.           If you think the problem might be a PPWIZARD or Regina bug (which you 
  1002.           think others probably haven't encountered) you may wish to contact me 
  1003.           directly as others may not be interested (we don't want too many 
  1004.           messages). 
  1005.  
  1006.           Please don't attach large files to e-mails sent to this address 
  1007.           (there is a 100K limit as well anyway). 
  1008.  
  1009.           We'll have to see how it goes. Hopefully it does not need to become 
  1010.           moderated (I probably haven't got time for that!). 
  1011.  
  1012.        2. Authors Email Address 
  1013.           I will take feedback in this manner but in general prefer the e-mail 
  1014.           list mentioned above. Exceptions might be where you have large 
  1015.           attachments, you don't think anyone else would be interested, you 
  1016.           don't want to join the group (why not?) or you really want to hammer 
  1017.           me! 
  1018.  
  1019.           If you must e-mail me directly then send it to 
  1020.           dbareis@labyrinth.net.au. If I think it's appropriate I will "CC" the 
  1021.           above discussion group with my response. 
  1022.  
  1023.           If you do email me directly please make sure your reply address is 
  1024.           valid! I have spent quite a bit of time on a number of replies that 
  1025.           were rejected (either unauthorised or no such email address). I 
  1026.           respond to all emails that require one, if you don't get a reponse 
  1027.           reasonably quickly then I didn't get your email, the response got 
  1028.           lost somehow or I'm on holidays! 
  1029.  
  1030.  Please zip attachments. This reduces the size of the e-mail and ensures that 
  1031.  the information gets here uncorrupted. 
  1032.  
  1033.  Known Bugs or Problems 
  1034.  
  1035.  The following bugs are PPWIZARD bugs: 
  1036.  
  1037.        1. None Known. 
  1038.  
  1039.  The following bugs may occur when using the native interpreters under OS/2: 
  1040.  
  1041.        1. None Known. 
  1042.  
  1043.  The following bugs may occur under any operating system using Regina (I will 
  1044.  assume on "one of my recommended versions only"): 
  1045.  
  1046.        1. The debug time will be plus or minus a second (this can produce 
  1047.           negative times, etc.). 
  1048.  
  1049.        2. Regina has a number of 'query exists' bugs, the one that might affect 
  1050.           you is if you specify an input file such as "C:\CONFIG.SYS" and 
  1051.           PPWIZARD tells you it can't open the "CONFIG.SYS" file in a 
  1052.           completely different directory! Another one is where "garbage" might 
  1053.           appear after a filename. 
  1054.  
  1055.  
  1056. ΓòÉΓòÉΓòÉ 1.6. Disclaimer ΓòÉΓòÉΓòÉ
  1057.  
  1058. Disclaimer 
  1059.  
  1060. I believe it is very unlikely that PPWIZARD or Regina will cause damage to your 
  1061. system, however I feel that it is wise to advise you of steps you can take if 
  1062. your data is highly critical. 
  1063.  
  1064. I wish to stress that you take full responsibility for ensuring that PPWIZARD 
  1065. (or any other software related to PPWIZARD) is suitable for use in your 
  1066. intended environment. 
  1067.  
  1068. PPWIZARD is supplied "as is" and may contain bugs. It is just impossible to 
  1069. test software (or even information) in all environments as there are just too 
  1070. many possibilities. For this reason you should test any software/information 
  1071. yourself for suitability before using in production or placing onto machines 
  1072. containing important information. By doing this you will have helped ensure 
  1073. that there are no unintended drastic side effects. Prior to testing it is 
  1074. recommended that a full backup of your hard disk be performed. 
  1075.  
  1076. Updating from Older Versions 
  1077.  
  1078. While I will try to keep PPWIZARD backwards compatible with older versions, I 
  1079. will at times (intentionally or not) change it in such a way as to require you 
  1080. to make changes to your source (batch files, code, etc.) if you wish to upgrade 
  1081. to the newer version of PPWIZARD. 
  1082.  
  1083. I will have expected you to have read the Change History as it will usually 
  1084. indicate any source changes that you might need to make, plus any other 
  1085. potentially important information. 
  1086.  
  1087. It is recommended that you backup your source (including any batch files, etc.) 
  1088. AND the older versions of my programs before trying a newer version. 
  1089.  
  1090. LINKS 
  1091.  
  1092. Any links I mention are provided "as is"; it is up to you to determine the 
  1093. quality of any site I link to or any software I mention... 
  1094.  
  1095.  
  1096. ΓòÉΓòÉΓòÉ 2. Beginners Guide ΓòÉΓòÉΓòÉ
  1097.  
  1098. Beginners Guide 
  1099.  
  1100. This page will attempt to show you, in one spot, all the basic information you 
  1101. will need to know. I will refer to HTML generation here, however almost 
  1102. everything said will also apply to other types of generation (such as REXX 
  1103. code). Because this is a beginners section some of my statements will be 
  1104. greatly simplified and therefore may not be strictly correct. 
  1105.  
  1106. PPWIZARD is a free tool. Its basic aim is to allow a template or style-sheet 
  1107. design approach to web sites. It can aid in ensuring that the look and feel is 
  1108. the same across all your pages and can automate many common and difficult 
  1109. tasks. This manual was written using PPWIZARD. 
  1110.  
  1111. PPWIZARD is an extremely powerful and capable tool and this appears to make 
  1112. some people believe that it is complex to use, this I believe to be wrong. Just 
  1113. because a feature exists does not mean you have to use it. To use the basic 
  1114. features as described below is not difficult and I would say that ppwizard does 
  1115. it in a simpler and more straight forward manner than any other preprocessor 
  1116. available. Most other preprocessors are flawed by design and are typically also 
  1117. too simplistic. You have nothing to advance to once you have learnt the 
  1118. fundamentals and by the time you realise you are being limited by the 
  1119. preprocessor's basic capabilities you are committed to using it. 
  1120.  
  1121. One of PPWIZARD's main aims is to ensure that you only need to do (specify) 
  1122. something once, no matter how many places require it. Because of this, testing 
  1123. becomes easier, bugs are found faster, and your site becomes more reliable. As 
  1124. a further aid you can use my free URL checker to check that external links all 
  1125. exist (detect 404's before your users do)! 
  1126.  
  1127. PPWIZARD does not "clash" with normal html syntax, for this reason you should 
  1128. be able to take any existing html pages and slowly modify them to use more and 
  1129. more ppwizard features. 
  1130.  
  1131. If you have any problems getting started with PPWIZARD or understanding things, 
  1132. then please email me at (dbareis@labyrinth.net.au). I do not mind questions of 
  1133. any sort as long as some effort at reading and understanding the documentation, 
  1134. etc. has been made! It is also best to supply any sample code that you have 
  1135. been trying, so I can see where you are going wrong. 
  1136.  
  1137. So...let's begin... There are really only two easy commands that you will need 
  1138. to start with. They are: 
  1139.  
  1140.        1. #include 
  1141.           This command allows you to include another file. There are no 
  1142.           restrictions on where this file is location or it's name. 
  1143.  
  1144.        2. #define 
  1145.           This command allows you to define something like an e-mail or web 
  1146.           address in one place and use it in all your pages. 
  1147.  
  1148.  The "#include" Command 
  1149.  
  1150.  This command allows you to include one file at any point within another file. 
  1151.  The included file can contain commonly used text, consisting of one or more 
  1152.  HTML paragraphs, an HTML header or footer, or macros which create text output. 
  1153.  
  1154.  Since the included text exists in only one place, all that is required to make 
  1155.  a change is to edit one file and then regenerate the HTML (see below). 
  1156.  
  1157.  The "#define" Command 
  1158.  
  1159.  This command allows you to define common components such as e-mail and web 
  1160.  addresses in one place. Here are some examples: 
  1161.  
  1162.       #define MyEmailAddress                 dbareis@labyrinth.net.au
  1163.       #define ImgUpdated                     <IMG SRC="graphics/updated1.gif" HSPACE=10 ALIGN=middle BORDER=0 WIDTH=52 HEIGHT=12 ALT="updated">
  1164.       #define ImgNew                         <IMG SRC="graphics/new.gif"      HSPACE=10 ALIGN=middle BORDER=0 WIDTH=35 HEIGHT=20 ALT="new">
  1165.       #define HttpMainJavasoftPage           java.sun.com
  1166.       #define HttpJavaFoundationClassesPage  <$HttpMainJavasoftPage>/products/jfc/
  1167.  
  1168.  In the above commands you will notice how we give "names" to common 
  1169.  components, for example I called my e-mail address "MyEmailAddress" and gave 
  1170.  it the value "dbareis@labyrinth.net.au". 
  1171.  
  1172.  You will normally put all of the commands like those above into a single file; 
  1173.  let's get creative and call it "common.ih" (you could call it absolutely 
  1174.  anything). Now, in any HTML page that requires one of the above definitions, 
  1175.  you would place a statement similar to the following, near the top: 
  1176.  
  1177.       #include "common.ih"
  1178.  
  1179.  Using Common "#define" Components 
  1180.  
  1181.  To refer to a previously defined value you preceed the "name" you gave it with 
  1182.  "<$" and end it with ">". For example, the following text refers to the e-mail 
  1183.  address we defined above: 
  1184.  
  1185.       <P>If you have any questions or suggestions for improvements please feel free to
  1186.       <A HREF="mailto:<$MyEmailAddress>">e-mail me</A>.
  1187.  
  1188.  You might have previously noticed that I snuck in a #define that also referred 
  1189.  to a previously defined value; it was this command: 
  1190.  
  1191.       #define HttpJavaFoundationClassesPage  <$HttpMainJavasoftPage>/products/jfc/
  1192.  
  1193.  Quotes in PPWIZARD 
  1194.  
  1195.  PPWIZARD's quotes are similar to HTML's in that both single and double quotes 
  1196.  can be used; where they differ is that virtually any convenient character can 
  1197.  be used. The following are all valid quoted values: 
  1198.  
  1199.          "quoted value containing the ' character" 
  1200.          'quoted value containing the " character' 
  1201.          +quoted value containing the " and ' characters+ 
  1202.          $quoted value containing the " and ' and + characters$ 
  1203.  
  1204.  Generating Your HTML 
  1205.  
  1206.  The main concept to understand is that what you edit is called source code and 
  1207.  what you create from this source (with PPWIZARD) is HTML or output code. You 
  1208.  would never edit the generated HTML; you go back to the source, make whatever 
  1209.  changes you require, and then regenerate new HTML. 
  1210.  
  1211.  I recommend that your source files use the extension ".it", except for any 
  1212.  source files that are common and are only included by other source files (for 
  1213.  those, use the extension ".ih"; these types of files are frequently called 
  1214.  header files). 
  1215.  
  1216.  Generation via Windows Explorer or OS/2 WPS 
  1217.  
  1218.  Any operating system that supports icons can be configured to run ppwizard so 
  1219.  that you need never use a command line. The Windows and OS/2 install packages 
  1220.  both perform setup for this purpose. 
  1221.  
  1222.  In Windows and OS/2 this allows you to right click on an ".IT" file and select 
  1223.  "Generate HTML" off the context menus (OS/2 users will find the option under 
  1224.  the "Open" menu). There are other menu options such as for editing the file. 
  1225.  
  1226.  PPWIZARD has also set up the GUI environment for project files so right 
  1227.  clicking on these files brings up edit and build options. 
  1228.  
  1229.  Generation via a Command Line 
  1230.  
  1231.  If you follow the naming conventions mentioned above then you can simply 
  1232.  recreate all your HTML with the following command: 
  1233.  
  1234.       ppwizard *.it
  1235.  
  1236.  The above command should work on OS/2 and should also work on Windows NT and 
  1237.  Windows 2000, other operating systems require the free "Regina" interpreter 
  1238.  (see http://www.labyrinth.net.au/~dbareis/regina.htm) and can't be configured 
  1239.  to run it automatically. Regina is very easy to install and the executable 
  1240.  will be called either "regina.exe" or "rexx.exe" (no extension under unix). 
  1241.  Thus if the the above command does not work try: 
  1242.  
  1243.       regina ppwizard.rex *.it
  1244.   OR: 
  1245.  
  1246.       rexx ppwizard.rex *.it
  1247.  
  1248.  If none of the above work then you should check out the "Hand Installation" 
  1249.  section for clues. 
  1250.  
  1251.  Getting slightly more advanced, you may get sick of rebuilding all your HTML 
  1252.  when only a page or two needs to be processed; this command will only 
  1253.  regenerate those that require it: 
  1254.  
  1255.       regina ppwizard.rex *.it /DependsOn:*.dep
  1256.  
  1257.  Getting even more advanced, I like to keep source files in one directory and 
  1258.  generated files elsewhere. The default HTML extension is ".htm"; this example 
  1259.  also shows how this can be changed: 
  1260.  
  1261.       regina ppwizard.rex *.it /DependsOn:out\depend\*.dep /Output:out\*.html
  1262.  
  1263.  Tab Characters In Source 
  1264.  
  1265.  By default PPWIZARD generates warnings when it encounters tab characters as it 
  1266.  really can't correctly process these without your help. By default it also 
  1267.  converts each tab to a space. 
  1268.  
  1269.  If you do not wish the warnings (which will also by default prevent 
  1270.  dependancychecking from working) then the easiest solution is probably to 
  1271.  configure your editor so that it generates spaces when the tab key is used. 
  1272.  
  1273.  If that is not an acceptable solution to you then you should use the /option 
  1274.  switch or the #option command to configure the Tabs setting, for example: 
  1275.  
  1276.       regina ppwizard.rex *.it /option:Tabs=ToSpaces
  1277.  
  1278.  Capturing PPWIZARD's Output 
  1279.  
  1280.  You should investigate the /ConsoleFile and /ErrorFile switches as these can 
  1281.  capture almost all output. 
  1282.  
  1283.  Not all debugging output can be captured however so at times you will need to 
  1284.  redirect output from the command line. Please be aware that due to Windows 
  1285.  NT/2000 bugs even if PPWIZARD is configured such that you don't normally need 
  1286.  to specify the rexx interpreter on every PPWIZARD command line you will need 
  1287.  to when redirecting, an example under windows follows (note that almost all 
  1288.  operating systems use a very similar syntax): 
  1289.  
  1290.       regina ppwizard.rex *.it /debug > c:\tmp\output.txt 2>&1
  1291.  
  1292.  Organising Source  Destination Trees 
  1293.  
  1294.  You might already have a directory tree which is an image of your web site 
  1295.  (contains images and html etc). This is useful for local testing and 
  1296.  simplifies things when updating your web server. 
  1297.  
  1298.   you will pass through PPWIZARD). 
  1299.  
  1300.  Now you can use ppwizard to "make" the images (copys you don't forget which is 
  1301.  which!). 
  1302.  
  1303.  Note that if you wish to use graphical HTML editors you should have a look at 
  1304.  the "/HideCmd" switch. 
  1305.  
  1306.  The use of separate tree, the "/COPY" switch and "/HideCmd" would be a good 
  1307.  approach if you wish non-technical people to maintain the source (or maybe 
  1308.  while you get used to PPWIZARD and test it out). 
  1309.  
  1310.  tories and deleting obsolete files or directories. If you use WINDOWS I have a 
  1311.  free self installing download that makes it extremely easy to setup (unlike 
  1312.  the official download...). 
  1313.  
  1314.  What Next? 
  1315.  
  1316.  You will want to read up more about macros and macro parameters. These (if you 
  1317.  are careful) will allow you to create CSS like "styles" such that you can 
  1318.  leave the source alone and change the macros to obtain different effects as 
  1319.  required. 
  1320.  
  1321.  You will also want to read up about the following commands and switches: 
  1322.  
  1323.          /Define 
  1324.          #if 
  1325.          #IfDef 
  1326.          #IfNDef 
  1327.  
  1328.  
  1329. ΓòÉΓòÉΓòÉ 3. Converting From ORB To PPWIZARD ΓòÉΓòÉΓòÉ
  1330.  
  1331. Converting From ORB To PPWIZARD 
  1332.  
  1333. This page will describe the steps required to convert from the "ORB" html 
  1334. preprocessor to PPWIZARD. I am working off the current version of "orbman.txt" 
  1335. as at 1/2/2000 which is for version 1.3 of ORB. 
  1336.  
  1337. This page is being worked on and so is not complete... 
  1338.  
  1339. Since ORB is very simplistic this is a relatively easy task. Most Orb feature 
  1340. map straight across to ppwizard and where limits exist ORB seems to be the most 
  1341. restrictive. 
  1342.  
  1343. You have control over virtually everything that PPWIZARD does, you might wish 
  1344. to check the available options if ppwizard is doing something you disagree with 
  1345. (for example removing leading whitespace). Most of the information below is 
  1346. subject to what options you have set and basically assumes default settings. 
  1347.  
  1348.        1. Orb Comments 
  1349.           Orb has block comments using "$comment" and "$endcomment" or "$/*" 
  1350.           and "$*/". PPWIZARD does not have block comments except that a #ifdef 
  1351.           can be used for this purpose if required. 
  1352.  
  1353.           Orb also has "line" comments of "$rem" or "$//", ppwizard has the ";" 
  1354.           character (by default). 
  1355.  
  1356.           PPWIZARD has "inline" comments as well, if the ";;" sequence is found 
  1357.           everything after the last occurance is removed. 
  1358.  
  1359.           Some examples: 
  1360.  
  1361.                         ;--- Include our common code (line comment) ----
  1362.                         #include "common.ih"   ;;An inline comment
  1363.  
  1364.        2. File Inclusion 
  1365.           Orb uses "$include" and ppwizard uses #include the variable name is 
  1366.           surrounded by "PPWIZARD quotes", for example: 
  1367.  
  1368.                         #include "common.ih"
  1369.  
  1370.           Instead of using the "ORBPATH" environment variable you can use the 
  1371.           "PPWIZARD_INCLUDE" or "INCLUDE" variables. 
  1372.  
  1373.           By convention main files have the extension ".IT" and header files 
  1374.           have the extension ".IH". 
  1375.  
  1376.        3. Defining Orb Variables 
  1377.           Orb uses "$define", "$def" or "$set" commands to define variables. 
  1378.           PPWIZARD uses the #define command to create it's variables. You can 
  1379.           also use /define from the command line. 
  1380.  
  1381.           PPWIZARD is much much more powerful than ORB, see the macros section 
  1382.           for more details. An example: 
  1383.  
  1384.                         #define email dbareis@labyrinth.net.au
  1385.  
  1386.        4. Using Orb Variables 
  1387.           Orb uses "[[Variable]]" when replacing variables, PPWIZARD uses 
  1388.           "<$Variable>", for example: 
  1389.  
  1390.                         #define email dbareis@labyrinth.net.au
  1391.  
  1392.                         My email address is "<$email>".
  1393.  
  1394.           Note that PPWIZARD unlike ORB does not quietly ignore "errors" so you 
  1395.           will always know if you forget to define something or you spell it 
  1396.           incorrectly. If you actually want the string of characters output 
  1397.           with no substitution taking place then have a look at PPWIZARD's 
  1398.           standard definitions. Another point is that ppwizard's variable names 
  1399.           can contain almost any character and be any length, the contents can 
  1400.           also span lines and include other ppwizard commands and macros. 
  1401.  
  1402.        5. Removing Orb Variables 
  1403.           Orb uses "$undef" command to remove variables. PPWIZARD uses the 
  1404.           #undef command to create it's variables. An example: 
  1405.  
  1406.                         #undef email
  1407.  
  1408.        6. Conditional Compilation 
  1409.           PPWIZARD can do much more than ORB (see the #if command) however when 
  1410.           ORB uses "$ifdef" or "$ifndef" then ppwizard uses #ifdef or #ifndef. 
  1411.  
  1412.           Orb's documentation does not say if nesting of conditional code is 
  1413.           allowed.  PPWIZARD allows nesting to any level. An example: 
  1414.  
  1415.                         #ifdef P_email
  1416.                                <P>My email address is "<$email>".
  1417.                         #endif
  1418.  
  1419.        7. User Defined Errors 
  1420.           ORB uses "$error" and ppwizard uses #error, for example: 
  1421.  
  1422.                         #ifdef P_email
  1423.                                #ifndef TRANSLATE_MODE
  1424.                                        #error "You forgot to define 'TRANSLATE_MODE'!"
  1425.                                #endif
  1426.                         #endif
  1427.  
  1428.        8. User Defined Messages 
  1429.           ORB uses "$message" or "$msg" to generate messages, ppwizard uses 
  1430.           #info and #warning. 
  1431.  
  1432.        9. ORB's $VAL 
  1433.           Orb has a "$val" command that ppwizard does not have, you could 
  1434.           implement as ppwizard code like: 
  1435.  
  1436.                         #ifdef email
  1437.                                <$email>
  1438.                         #elseif
  1439.                                Default text
  1440.                         #endif
  1441.  
  1442.           The above would create a one new line with either the value of the 
  1443.           variable or the default text, if you must have the text "inline" as 
  1444.           ORB would then you would need to create a macro. 
  1445.  
  1446.       10. ORB's $TIME 
  1447.           Orb has a "$time" command, ppwizard does have a "<?CompileTime>" 
  1448.           variable but it is of a fixed format. In general you will not be 
  1449.           happy with this format and will use the "#evaluate" or "#DefineRexx" 
  1450.           commands to create your own format. 
  1451.  
  1452.           Basically you will be using standard rexx date() and time() routines 
  1453.           to build up a time in whatever format you desire, for example: 
  1454.  
  1455.                         ;--- Capture date/time information (<$CompileTime> --> Friday March 27 1998 at 7:46pm ---
  1456.                         #evaluate CompileTime @date('WeekDay') || ' ' || date('Month') || ' ' || substr(date('Sorted'), 7, 2) || ' ' || left(date('Sorted'), 4) || ' at ' || time('Civil')@
  1457.  
  1458.                         ;--- Use the captured date/time ----
  1459.                         <P>This HTML was built at <$CompileTime>.
  1460.  
  1461.       11. ORB's $TARGET 
  1462.           Orb has a "$target" command, ppwizard has a "#output" command which 
  1463.           is more powerful but has one major difference, you must also close 
  1464.           any file you open. 
  1465.  
  1466.       12. Predefined ORB Variables 
  1467.           Firstly you might wish to check out the standard definitions section. 
  1468.  
  1469.           A list of ORB variables follows: 
  1470.  
  1471.               orb_platform 
  1472.                Have a look at <?OpSys>. 
  1473.  
  1474.               orb_vernum 
  1475.                Have a look at <?Version>. 
  1476.  
  1477.               orb_version 
  1478.                The closest match is <?Version>. 
  1479.  
  1480.               orb_generator 
  1481.                Have a look at <?PpwizardGeneratorMetaTags> and the 
  1482.                /HtmlGenerator switch. 
  1483.  
  1484.               base 
  1485.                Have a look at <?InputFile>. 
  1486.  
  1487.               Source 
  1488.                Have a look at <?InputComponent>. 
  1489.  
  1490.               Target 
  1491.                Have a look at <?OutputFile>. 
  1492.  
  1493.               datetime_gmt 
  1494.                See earlier comments reguarding the "$time" command. 
  1495.  
  1496.               datetime_local 
  1497.                See earlier comments reguarding the "$time" command. 
  1498.  
  1499.               NL 
  1500.                Have a look at <?NewLine>. 
  1501.  
  1502.               SP 
  1503.                Have a look at <?Space>. 
  1504.  
  1505.               OBR 
  1506.                Not required. 
  1507.  
  1508.               OBR2 
  1509.                Not required. 
  1510.  
  1511.               CBR 
  1512.                Not required. 
  1513.  
  1514.               CBR2 
  1515.                Not required. 
  1516.  
  1517.       13. Line Continuation or Splicing 
  1518.           PPWIZARD has line continuation characters. 
  1519.  
  1520.       14. Orb Command Line 
  1521.           See PPWIZARD's switch documentation. 
  1522.  
  1523.       15. MAKE 
  1524.           Not only can ppwizard be used in make files but ppwizard includes a 
  1525.           much more powerful mechanism, see the "/DependsOn" command. 
  1526.  
  1527.  
  1528. ΓòÉΓòÉΓòÉ 4. Converting From SSI To PPWIZARD ΓòÉΓòÉΓòÉ
  1529.  
  1530. Converting From SSI To PPWIZARD 
  1531.  
  1532. There is now a PPWIZARD add-on available from the download page which allows 
  1533. you to easily migrate from Server Side Includes (SSI) to PPWIZARD at your own 
  1534. pace. You can have both SSI and PPWIZARD tags in the same files. 
  1535.  
  1536. It will tell you where all SSI tags are located and tell you which ones can't 
  1537. be handled. If a tag can't be handled then you have the option of leaving it in 
  1538. place, dropping it, or outputting an error message into the generated HTML. 
  1539.  
  1540. For more information see the header file in the "SSI" download. 
  1541.  
  1542.  
  1543. ΓòÉΓòÉΓòÉ 5. PPWIZARD Command Line ΓòÉΓòÉΓòÉ
  1544.  
  1545. PPWIZARD Command Line 
  1546.  
  1547. Windows NT/2000 users should be able to start PPWIZARD like this: 
  1548.  
  1549.     PPWIZARD  [[+]InputMask] [@Project] [Options[:parms]]
  1550.  
  1551. OS/2 users can also use the syntax shown above (make sure PPWIZARD is named 
  1552. "PPWIZARD.CMD"). 
  1553.  
  1554. Windows 95/98/ME and Unix users will probably need to use (and NT/2000 users 
  1555. can use): 
  1556.  
  1557.     REGINA PPWIZARD  [[+]InputMask] [@Project] [Options[:parms]]
  1558.  
  1559. As a simple example to build "tryme.htm" from the source file "tryme.it" 
  1560. (supplied with ppwizard) one possible format of the command is: 
  1561.  
  1562.     REGINA  PPWIZARD  tryme.it
  1563.  
  1564. You should read up about curley codes as these can be used to take care of 
  1565. difficult characters such as spaces, another example is if you had a filename 
  1566. or mask that begins with a minus sign (this normally indicates the start of a 
  1567. command line switch). Spaces can also be handled by surrounding any item on the 
  1568. command line with a range of "quote" characters. This can be very handy in 
  1569. cases where the normally useful double quotes are causing problems (getting 
  1570. dropped by operating system etc). The quote characters you can use include 
  1571. single, double and backwards quotes as well as the "~!#$%^([" characters. If 
  1572. "(" or "[" is used the matching end quote is ")" or "]", otherwise the starting 
  1573. and ending quote characters are the same, valid examples are 'one parm' and 
  1574. [one parm]. 
  1575.  
  1576. Any item that starts with ';' (such as ";/debug) is commented out and is 
  1577. ignored. This should be helpful when testing combinations of switches. 
  1578.  
  1579. Note that Regina looks in the directories mentioned in the "REGINA_MACROS" 
  1580. environment variable for REXX scripts if they are not in the current directory 
  1581. (it does not use the "PATH" environment variable). Unless "ppwizard.rex" is 
  1582. located in a path mentioned in "REGINA_MACROS" then a command such as 
  1583. "regina ppwizard tryme.it" will fail unless PPWIZARD is in the current 
  1584. directory. Of course it will also fail if "regina" is not in one of the 
  1585. directories mentioned in the "PATH" environment or in the current directory. 
  1586.  
  1587. Command Line: InputMask 
  1588.  
  1589. You may specify more than one input mask and they may appear anywhere on the 
  1590. line (however none are processed until after all switches have been). 
  1591.  
  1592. Each mask (anything that does not look like a switch/option) can be the name of 
  1593. a single file or may contain the normal wildcard characters for your operating 
  1594. system ("?" & "*" for OS/2 and Windows). See the documentation for your 
  1595. operating system for more details. Note that with a GETFILELIST hook you can 
  1596. enhance the way that the mask is handled. Note that for some operating systems 
  1597. ppwizard gets passed a pre-expanded list of files and never sees the wildcards, 
  1598. if this is not what you want you can always use curley codes to hide the value 
  1599. from the operating system or regina. 
  1600.  
  1601. If a mask (which may include a path) is preceeded by the "+" character then 
  1602. this indicates that you wish to process all files matching the mask in the 
  1603. indicated (or current) directory and all of it's subdirectories. 
  1604.  
  1605. To specify the location where ppwizard will place the generated output files 
  1606. (current directory by default!) you need to use the /output switch. You may 
  1607. wish to also use a similar specification for the /DependsOn switch if you use 
  1608. it (if not, why not????). 
  1609.  
  1610. Each source file may include other (external) files such as common header files 
  1611. containing your standard definitions and macros. 
  1612.  
  1613. If all input files end in the extension ".X" then the default processing mode 
  1614. is /rexx, the default situation is /html. 
  1615.  
  1616. Each file has an associated base directory, to override the default value (the 
  1617. masks directory) you can use the /BaseDir switch or imbed the "{ENDBASE}" 
  1618. (upper case) string within the InputMask after one of the slashes (the string 
  1619. marks the end of the base directory). Note that if you do mark the base 
  1620. directory this way the Input mask should specify a full path (or begin with '.' 
  1621. or '..' followed by a slash). An example of specifying the base directory would 
  1622. be "c:\projects\source\main\{ENDBASE}subdir1\*.IT". 
  1623.  
  1624. Command Line: Switches / Options 
  1625.  
  1626. All Options begin with '/' or '-' and are executed in the following order: 
  1627.  
  1628.        1. If the optional environment variable "PPWIZARD_OPTIONS" exists these 
  1629.           are processed first. 
  1630.  
  1631.        2. If the optional ppwizard project file "ppwizard.ppw" exists then this 
  1632.           is processed via the /List switch. You can override any switches 
  1633.           specified in the environment variable above if you need to. PPWIZARD 
  1634.           first looks in the current directory and then in the same location as 
  1635.           the ppwizard runtime if required. 
  1636.  
  1637.        3. Any options specified on the command line. You can override any 
  1638.           switches specified in the environment variables or project files 
  1639.           above if you need to. 
  1640.  
  1641.  Normally files or options are separated by spaces, if the file or option needs 
  1642.  to contain spaces then you can surround it by double quotes. If you use double 
  1643.  quotes the quoted value must not contain double quotes (encode with "{x22}"). 
  1644.  
  1645.  Available switches are: 
  1646.  
  1647.        1. /#Include 
  1648.        2. /$Trace 
  1649.        3. /**/ 
  1650.        4. /@Extn 
  1651.        5. /BaseDir 
  1652.        6. /Beep 
  1653.        7. /CGI 
  1654.        8. /Color 
  1655.        9. /ConsoleFile 
  1656.       10. /Copy 
  1657.       11. /CopyRight 
  1658.       12. /CrLf 
  1659.       13. /Debug 
  1660.       14. /DebugChars 
  1661.       15. /DebugCols 
  1662.       16. /DebugTime 
  1663.       17. /Define 
  1664.       18. /DeleteOnError 
  1665.       19. /DeletePrev 
  1666.       20. /DependsOn 
  1667.       21. /DependsOnComplete 
  1668.       22. /DependsOnWarnings 
  1669.       23. /DropFiles 
  1670.       24. /ErrorFile 
  1671.       25. /Exclude 
  1672.       26. /Exec 
  1673.       27. /FileNames 
  1674.       28. /FilterInput 
  1675.       29. /FilterOutput 
  1676.       30. /GetEnv 
  1677.       31. /HideCmd 
  1678.       32. /Hook 
  1679.       33. /Html 
  1680.       34. /HtmlGenerator 
  1681.       35. /Inc2Cache 
  1682.       36. /IncludePath 
  1683.       37. /Info 
  1684.       38. /List 
  1685.       39. /Making 
  1686.       40. /OnERROR 
  1687.       41. /OnOK 
  1688.       42. /Option 
  1689.       43. /Other 
  1690.       44. /Output 
  1691.       45. /OutHeader 
  1692.       46. /Pack 
  1693.       47. /RedirMethod 
  1694.       48. /RegSyntax 
  1695.       49. /Rexx 
  1696.       50. /Sleep 
  1697.       51. /SpellAddWord 
  1698.       52. /SpellCheck 
  1699.       53. /SpellShowAll 
  1700.       54. /Template 
  1701.       55. /UNC 
  1702.       56. /Validate 
  1703.       57. /WarningsRc 
  1704.       58. /XSlash 
  1705.  
  1706.  LONG COMMAND LINES / CONFIGURATION FILES 
  1707.  
  1708.  PPWIZARD supports storing configuration information in the following ways: 
  1709.  
  1710.        1. Environment Variables 
  1711.           Using the /GetEnv switch you can easily retrieve previously stored 
  1712.           command line options (possibly set up in "config.sys" or windows 
  1713.           registry). 
  1714.  
  1715.        2. In List File 
  1716.           Using the /List switch you can easily retrieve command line options 
  1717.           from a configuration file. A major advantage of a "list" file is that 
  1718.           you do not have to handle characters such as '>' as you would have to 
  1719.           if it came from the command line. 
  1720.  
  1721.           Note that ppwizard will automatically read in any file named 
  1722.           "ppwizard.ppw" (default project file). 
  1723.  
  1724.  RETURN CODES 
  1725.  
  1726.          A return code of 0 indicates success. 
  1727.  
  1728.          A return code of 1 indicates success (with warnings) and /WarningsRc 
  1729.           was not used to turn them off. 
  1730.  
  1731.          Any other value indicates an error occurred. 
  1732.  
  1733.  The /ErrorFile and /ConsoleFile can help you capture any text output by 
  1734.  ppwizard which can be particulary useful if you don't work from the command 
  1735.  line. 
  1736.  
  1737.  EXAMPLE 
  1738.  
  1739.  This example has the following attributes: 
  1740.  
  1741.        1. Make file functionality without the hassle. 
  1742.  
  1743.        2. All source files have an extension of ".IT" (headers use ".IH"). 
  1744.  
  1745.        3. All output to have the extension ".html" and go into the "OUT" 
  1746.           directory. 
  1747.  
  1748.       +-[ MAKEIT.CMD ]------------------------------------------------+
  1749.       | @echo off                                                     |
  1750.       | md OUT        >nul 2>&1                                       |
  1751.       | md OUT\DEPEND >nul 2>&1                                       |
  1752.       | ppwizard %1.IT /Output:OUT\*.html /DependsOn:OUT\DEPEND\*.DEP |
  1753.       | if errorlevel 1 echo ERROR: Command failed!                   |
  1754.       +---------------------------------------------------------------+
  1755.  
  1756.  Example - Redirection 
  1757.  
  1758.  Ppwizard (or any other program) can at times generate quite a lot of output. 
  1759.  When /Debug is used you will definitely wish to "redirect" the output into a 
  1760.  file, the following is an example which would work in virtually all operating 
  1761.  systems (including linux bash shell - change switch characters to '-'!): 
  1762.  
  1763.       [regina] ppwizard index.it /Output:OUT\*.htm /Debug   > OUT\output.TXT 2>&1
  1764.  
  1765.  If the redirection example does not work you will need to read the 
  1766.  documentation for the operating system you are using to determine the correct 
  1767.  method. If this failed on Windows NT or 2000 (one of the 1,234,657 bugs!) then 
  1768.  you will need to specify the regina interpreter first ("regina ppwizard" etc). 
  1769.  
  1770.  
  1771. ΓòÉΓòÉΓòÉ 5.1. Project Files ΓòÉΓòÉΓòÉ
  1772.  
  1773. Command Line: @Project 
  1774.  
  1775. PPWIZARD allows you to put all or some of your file specifications or switches 
  1776. into project (configuration) files with a default file extension of ".ppw" and 
  1777. easily refer to them from the command line. 
  1778.  
  1779. PPWIZARD uses FindFile() to search for project files. Basically the project 
  1780. facility is a "smarter" version of the /List functionality (and easier to 
  1781. type!). If you need to refer to project files in specific directories then the 
  1782. "/list" switch is required. 
  1783.  
  1784. PPWIZARD automatically looks for a specific project file (called 
  1785. "ppwizard.ppw"). By default if all input files have the same extension then 
  1786. ppwizard will also try to load an extension based project file, see the /@EXTN 
  1787. switch for more information. 
  1788.  
  1789. See the /List switch for more details on the file format, but here is a sample 
  1790. configuration file (lets call it "all.ppw"): 
  1791.  
  1792. ;-----------------------------------------------------------------------
  1793. ;--- This file builds HTML for all "*.IT" files in current directory ---
  1794. ;-----------------------------------------------------------------------
  1795.  
  1796. *.IT                       ;;Only build files matching this mask
  1797. /DependsOn:DEP\*.DEP       ;;Only rebuild files that need it (new or modified)
  1798. /Output:OUT\*.htm          ;;I like files generated into the "out" directory and with the ".htm" extn
  1799.  
  1800. To use the "all.ppw" file shown above you could say: 
  1801.  
  1802.     ppwizard @all
  1803.  
  1804. As shown above all "*.it" files will be processed if we wished to process a 
  1805. single file but still make use of the project file for the options then you 
  1806. would need to make use of the /DropFiles switch. 
  1807.  
  1808. As documented for "/list" nothing stops one list or project file from loading 
  1809. others. 
  1810.  
  1811.  
  1812. ΓòÉΓòÉΓòÉ 5.2. Curley Codes ΓòÉΓòÉΓòÉ
  1813.  
  1814. Curley Codes 
  1815.  
  1816. These codes are used to specify characters that might otherwise be incorrectly 
  1817. interpreted by either your operating system or PPWIZARD. 
  1818.  
  1819. If you know the ASCII code of a character (in hex) you can encode it, for 
  1820. example "{x20}" represents a space. If a code looks invalid then it is ignored. 
  1821.  
  1822. The following are codes for some of the more difficult command line characters 
  1823. you are likely to need: 
  1824.  
  1825. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1826. ΓöéAscii  ΓöéCode   ΓöéDescription     Γöé
  1827. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1828. Γöé32     Γöé{x20}  ΓöéSpace           Γöé
  1829. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1830. Γöé33     Γöé{x21}  Γöé!               Γöé
  1831. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1832. Γöé34     Γöé{x22}  Γöé" (double quote)Γöé
  1833. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1834. Γöé35     Γöé{x23}  Γöé#               Γöé
  1835. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1836. Γöé36     Γöé{x24}  Γöé$               Γöé
  1837. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1838. Γöé37     Γöé{x25}  Γöé%               Γöé
  1839. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1840. Γöé38     Γöé{x26}  Γöé&               Γöé
  1841. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1842. Γöé39     Γöé{x27}  Γöé' (single quote)Γöé
  1843. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1844. Γöé40     Γöé{x28}  Γöé(               Γöé
  1845. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1846. Γöé41     Γöé{x29}  Γöé)               Γöé
  1847. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1848. Γöé42     Γöé{x2A}  Γöé*               Γöé
  1849. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1850. Γöé43     Γöé{x2B}  Γöé+               Γöé
  1851. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1852. Γöé44     Γöé{x2C}  Γöé,               Γöé
  1853. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1854. Γöé45     Γöé{x2D}  Γöé-               Γöé
  1855. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1856. Γöé46     Γöé{x2E}  Γöé. (dot)         Γöé
  1857. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1858. Γöé47     Γöé{x2F}  Γöé/               Γöé
  1859. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1860. Γöé58     Γöé{x3A}  Γöé                Γöé
  1861. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1862. Γöé59     Γöé{x3B}  Γöé;               Γöé
  1863. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1864. Γöé60     Γöé{x3C}  Γöé<               Γöé
  1865. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1866. Γöé61     Γöé{x3D}  Γöé=               Γöé
  1867. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1868. Γöé62     Γöé{x3E}  Γöé>               Γöé
  1869. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1870. Γöé63     Γöé{x3F}  Γöé?               Γöé
  1871. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1872. Γöé64     Γöé{x40}  Γöé@               Γöé
  1873. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1874. Γöé91     Γöé{x5B}  Γöé[               Γöé
  1875. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1876. Γöé92     Γöé{x5C}  Γöé\               Γöé
  1877. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1878. Γöé93     Γöé{x5D}  Γöé]               Γöé
  1879. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1880. Γöé94     Γöé{x5E}  Γöé^               Γöé
  1881. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1882. Γöé95     Γöé{x5F}  Γöé_ (underscore)  Γöé
  1883. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1884. Γöé96     Γöé{x60}  Γöé`               Γöé
  1885. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1886. Γöé123    Γöé{x7B}  Γöé{               Γöé
  1887. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1888. Γöé124    Γöé{x7C}  Γöé|               Γöé
  1889. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1890. Γöé125    Γöé{x7D}  Γöé}               Γöé
  1891. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1892. Γöé126    Γöé{x7E}  Γöé~               Γöé
  1893. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1894.  
  1895.  
  1896. ΓòÉΓòÉΓòÉ 5.3. /BaseDir ΓòÉΓòÉΓòÉ
  1897.  
  1898. Switch /BaseDir[:SomeAbsoluteDirectory] 
  1899.  
  1900. This is a PPWIZARD command line switch. You can set up your own default 
  1901. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  1902.  
  1903. Each input file has an associated "base directory", if your input mask did not 
  1904. specify that subdirectories were being processed then this directory is the 
  1905. directory the file is in otherwise it is the directory of the specified mask 
  1906. (of course these values may be the same for all or some files). 
  1907.  
  1908. The value supplied on this switch overrides all following default base 
  1909. directories for input filemasks. 
  1910.  
  1911. The value should have a terminating slash and must begin any filemasks you 
  1912. attempt to use or ppwizard processing will abort. 
  1913.  
  1914. You can restore normal processing by using "/BaseDir" without a directory. The 
  1915. directory you use must be an absolute directory or the result will not be 
  1916. correct. There are some simple relative paths that PPWIZARD can convert to 
  1917. absolute such as those starting with '..' and '.' followed by a slash. 
  1918.  
  1919. You would probably never wish or need to override the base directory value 
  1920. unless you normally process a whole tree and now wish to process a subtree as 
  1921. if the whole tree were being processed. 
  1922.  
  1923. The value can be accessed with the "<?BaseDir>" definition. 
  1924.  
  1925. Alternative 
  1926.  
  1927. An alternative way of specifying the base directory is to imbed the "{ENDBASE}" 
  1928. (upper case) string within the filemask after one of the slashes (the string 
  1929. marks the end of the base directory). 
  1930.  
  1931.  
  1932. ΓòÉΓòÉΓòÉ 5.4. /Beep ΓòÉΓòÉΓòÉ
  1933.  
  1934. Switch /Beep[:YesOrNo] 
  1935.  
  1936. This is a PPWIZARD command line switch. You can set up your own default 
  1937. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  1938.  
  1939. You can determine if beeps occur in some situations such as ppwizard detecting 
  1940. errors. 
  1941.  
  1942. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  1943. one of the following values is expected: 
  1944.  
  1945.          Y 
  1946.          N 
  1947.          YES 
  1948.          NO 
  1949.  
  1950.  
  1951. ΓòÉΓòÉΓòÉ 5.5. /CGI ΓòÉΓòÉΓòÉ
  1952.  
  1953. Switch /CGI:LogFile 
  1954.  
  1955. This is a PPWIZARD command line switch. You can set up your own default 
  1956. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  1957.  
  1958. This command changes the way PPWIZARD works to allow it to be used as a web 
  1959. server based CGI program (or part of a bigger CGI process). 
  1960.  
  1961. The output goes to stdout and what would normally go to stdout is prevented 
  1962. from going there. 
  1963.  
  1964. If the optional "LogFile" is not specified then all status, debug and error 
  1965. output is dropped.  If you need to see this you would specify the name of a 
  1966. file.  If the filename includes "?" then a "random" 8.3 filename (no path) is 
  1967. chosen and replaces the "?". 
  1968.  
  1969. If the ppwizard output is not part of a larger process then you may want to 
  1970. make use of the "<?CgiStart>" variable. 
  1971.  
  1972. Being a CGI script (or part of one) you would want your code to be as fast as 
  1973. possible, I highly recommend you read the "performance" documentation. 
  1974.  
  1975. CGI OPTIONS 
  1976.  
  1977. You may /define, #define or #evaluate the following variables to control the 
  1978. output which occurs in the case of a fatal error (the default is to display the 
  1979. information): 
  1980.  
  1981.          CGI_FATAL_MY_MESSAGE_ONLY 
  1982.           Define this variable if you don't want any details of the message to 
  1983.           be displayed in the HTML output.  Leave this variable empty so as not 
  1984.           to indicate an error (other than truncated output!) or supply the 
  1985.           HTML codes and text you wish displayed. 
  1986.  
  1987.          CGI_FATAL_HEADER 
  1988.           This variable controls the HTML codes that are sent to stdout before 
  1989.           the lines that contain the details of the error.  It is recommended 
  1990.           that these codes include "<PRE>" or similar to retain the line 
  1991.           formatting on error lines. 
  1992.  
  1993.          CGI_FATAL_TRAILER 
  1994.           This variable controls the HTML codes that are sent to stdout after 
  1995.           the lines that contain the details of the error.  The codes will 
  1996.           usually reverse those you specified for use before the error details. 
  1997.  
  1998.  Example 
  1999.  
  2000.  The following examples show the options being specified on the command line, 
  2001.  it is probably better to have any common options specified in CONFIG.SYS on 
  2002.  the web server. 
  2003.  
  2004.       ppwizard EmailForm.TEM /CrLf /CGI
  2005.       ppwizard EmailForm.TEM /CrLf /CGI:LOGS\LAST.LOG
  2006.       ppwizard EmailForm.TEM /CrLf /CGI:LOGS\?
  2007.  
  2008.  
  2009. ΓòÉΓòÉΓòÉ 5.6. /Color ΓòÉΓòÉΓòÉ
  2010.  
  2011. Switch /Color[:YesOrNo] 
  2012.  
  2013. This is a PPWIZARD command line switch. You can set up your own default 
  2014. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2015.  
  2016. You can determine if colors are used in displayed output.  Useful if 
  2017. redirecting output to log files (or you just hate colors!). 
  2018.  
  2019. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  2020. one of the following values is expected: 
  2021.  
  2022.          Y 
  2023.          N 
  2024.          YES 
  2025.          NO 
  2026.  
  2027.  For colors to work the session must support ANSI color strings. OS/2 does this 
  2028.  by default.  NT does not seem to. 
  2029.  
  2030.  
  2031. ΓòÉΓòÉΓòÉ 5.7. /ConsoleFile ΓòÉΓòÉΓòÉ
  2032.  
  2033. Switch /ConsoleFile:[+]FileName 
  2034.  
  2035. This is a PPWIZARD command line switch. You can set up your own default 
  2036. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2037.  
  2038. Sometime it would be handy to duplicate all the PPWIZARD output that goes to 
  2039. the console to a file. This is particularly true if you are not working from a 
  2040. command prompt or PPWIZARD is generating heaps of output as it will if debug 
  2041. mode is on (e.g. you used the /Debug switch). 
  2042.  
  2043. Of course redirection of the console output is another way the output can be 
  2044. captured particularly if you don't actually want the output sent to the 
  2045. console. 
  2046.  
  2047. By default console output does not go to a file. If you just wish to see an 
  2048. error output then have a look at the /ErrorFile switch. 
  2049.  
  2050. The environment variable "PPWIZARD_CONSOLEFILE" is an alternative way to set 
  2051. the filename. It takes the desired filename (not a file mask). If the filename 
  2052. begins with "+" then the file is appended to and not deleted every time 
  2053. ppwizard starts. 
  2054.  
  2055. If no parameter is supplied on this switch then console output is not sent to a 
  2056. file otherwise the format is exactly the same as that described for the 
  2057. environment variable. 
  2058.  
  2059. Note that this switch can only take effect from the time that ppwizard is 
  2060. processing the command line and has seen the switch, so it can not handle any 
  2061. console output before this. You may wish to use the environment variable to set 
  2062. it and in any case use this switch as early as possible on the command line. 
  2063.  
  2064. Rexx tracing performed by the interpreter can't be sent to the file as I 
  2065. recommend PPWIZARD tracing in any case you may not be using it. 
  2066.  
  2067. Do not simply use the rexx "say" command or the "charout" call to send output 
  2068. to standard out because if you do it will not appear in the console file, you 
  2069. need to use the Say() and Chars() calls instead. 
  2070.  
  2071. EXAMPLE #1 
  2072.  
  2073. In the following example we use the switch to specify a file name and directory 
  2074. for the console file and specify that we wish to append to the end of the file 
  2075. rather than delete it every time ppwizard begins: 
  2076.  
  2077.     ppwizard *.IT /ConsoleFile:+out\PPWIZARD.CON /Output:OUT\*.html
  2078.  
  2079. EXAMPLE #1 
  2080.  
  2081. In the following example we use the switch to specify a file name and directory 
  2082. for the console file and specify that we wish ppwizard to start with a clean 
  2083. file, we also don't wish to see any output: 
  2084.  
  2085.     ppwizard *.IT /ConsoleFile:out\PPWIZARD.CON /Output:OUT\*.htm > nul 2>&1
  2086.  
  2087. Note that the redirection syntax may differs between operating systems (it is 
  2088. not a ppwizard feature). Windows 95/98 users are basically using DOS and so the 
  2089. "2>&1" bit can't be used but the example can be used in most other operating 
  2090. systems. 
  2091.  
  2092.  
  2093. ΓòÉΓòÉΓòÉ 5.8. /Copy ΓòÉΓòÉΓòÉ
  2094.  
  2095. Switch /Copy 
  2096.  
  2097. This is a PPWIZARD command line switch. You can set up your own default 
  2098. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2099.  
  2100. This processing mode switch indicates that you simply want the input file 
  2101. copied from one place to another (source and destination filenames don't need 
  2102. to have the same name). 
  2103.  
  2104. All following input masks are processed in "COPY" mode, the "/output" switch 
  2105. determines the destination directory and filename (it would normally include 
  2106. "*.*"). 
  2107.  
  2108. This can be used to syncronise .GIF, .JPG or other binary files with a local 
  2109. homepage image. Note that you would normally also use the /DependsOn switch so 
  2110. that the copy only occurs when the file has changed! PPWIZARD will not 
  2111. particularly care whether the source file time is newer or older (or in fact 
  2112. the same) than the output file, it simply cares whether the source file has 
  2113. changed (exactly what you'd like). 
  2114.  
  2115. This switch can be used any number of times and will affect all input masks 
  2116. that follow. For backwards compatability, if an input mask is found before any 
  2117. processing mode switch then the last instance of a processing mode switch is 
  2118. used these. 
  2119.  
  2120. EXAMPLE OF USE 
  2121.  
  2122. You might already have a directory tree which is an image of your web site 
  2123. (contains images and html etc). This is useful for local testing and simplifies 
  2124. things when updating your web server. 
  2125.  
  2126.  you will pass through PPWIZARD). 
  2127.  
  2128. d does not care what extensions you use - as long as you don't forget which is 
  2129. which!). 
  2130.  
  2131. Note that if you wish to use graphical HTML editors you should have a look at 
  2132. the "/HideCmd" switch. 
  2133.  
  2134. The use of separate tree, the "/COPY" switch and "/HideCmd" would be a good 
  2135. approach if you wish non-technical people to maintain the source (or maybe 
  2136. while you get used to PPWIZARD and test it out). 
  2137.  
  2138. tories and deleting obsolete files or directories. If you use WINDOWS I have a 
  2139. free self installing download that makes it extremely easy to setup (unlike the 
  2140. official download...). 
  2141.  
  2142.  
  2143. ΓòÉΓòÉΓòÉ 5.9. /CopyRight ΓòÉΓòÉΓòÉ
  2144.  
  2145. Switch /CopyRight[:YesOrNo] 
  2146.  
  2147. This is a PPWIZARD command line switch. You can set up your own default 
  2148. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2149.  
  2150. By default a 3 line copyright message is displayed, this allows you to turn the 
  2151. message off. 
  2152.  
  2153. Note that on error or debug mode being on it is output anyway. 
  2154.  
  2155. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  2156. one of the following values is expected: 
  2157.  
  2158.          Y 
  2159.          N 
  2160.          YES 
  2161.          NO 
  2162.  
  2163.  
  2164. ΓòÉΓòÉΓòÉ 5.10. /CrLf ΓòÉΓòÉΓòÉ
  2165.  
  2166. Switch /CrLf[:YesOrNo] 
  2167.  
  2168. This is a PPWIZARD command line switch. You can set up your own default 
  2169. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2170.  
  2171. This switch can be used to vary the line termination characters. These are 
  2172. initialized to newline on unix and carriage return plus linefeed elsewhere. 
  2173.  
  2174. You can "compress" html on OS/2 and Windows systems a bit more by removing the 
  2175. carriage return as html browsers don't need them, this way you'd save one byte 
  2176. per line. 
  2177.  
  2178. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  2179. one of the following values is expected: 
  2180.  
  2181.          Y 
  2182.          N 
  2183.          YES 
  2184.          NO 
  2185.  
  2186.  
  2187. ΓòÉΓòÉΓòÉ 5.11. /Debug ΓòÉΓòÉΓòÉ
  2188.  
  2189. Switch /Debug 
  2190.  
  2191. This is a PPWIZARD command line switch. You can set up your own default 
  2192. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2193.  
  2194. This option can be useful in determining what is going wrong when you don't get 
  2195. the output you expected. 
  2196.  
  2197. The output is fairly easy to understand and aims to actually teach (or help you 
  2198. to understand) certain commands (such as #import). 
  2199.  
  2200. This switch is handy if you really have no idea where something is going wrong, 
  2201. if you have an idea of where the fault lies then it is much smarter to add 
  2202. #debug commands where required so as to speed up ppwizard execution and reduce 
  2203. the volume of output. Another way of reducing debug output is via the 
  2204. DebugLevel option. 
  2205.  
  2206. To get the maximum output use the switch as early as possible on the command 
  2207. line. 
  2208.  
  2209. If you wish to report a problem with ppwizard then please use this switch and 
  2210. send the output zipped along with any other details. 
  2211.  
  2212. Note that if this command line switch is used you can no longer turn debug mode 
  2213. on and off with the #debug command. 
  2214.  
  2215. The following switches are also simulated: 
  2216.  
  2217.          /INFO 
  2218.          /COLOR:N 
  2219.          /BEEP:N 
  2220.  
  2221.  
  2222. ΓòÉΓòÉΓòÉ 5.12. /DebugChars ΓòÉΓòÉΓòÉ
  2223.  
  2224. Switch /DebugChars:List 
  2225.  
  2226. This is a PPWIZARD command line switch. You can set up your own default 
  2227. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2228.  
  2229. This switch allows you to modify the following debug 'markers': 
  2230.  
  2231.        1. Left Quote 
  2232.           This allows you to change the way ppwizard displays a left "quote" in 
  2233.           debug mode. 
  2234.  
  2235.        2. Right Quote 
  2236.           This allows you to change the way ppwizard displays a right "quote" 
  2237.           in debug mode. 
  2238.  
  2239.        3. New Line 
  2240.           This allows you to change the way ppwizard displays a new line 
  2241.           character. 
  2242.  
  2243.  If the supplied list is empty then the defaults are restored otherwise it 
  2244.  specifies the values for as many comma seperated items as are supplied in the 
  2245.  list (items assigned in the order shown above). 
  2246.  
  2247.  An item can be: 
  2248.  
  2249.          A value of "-1" means use an empty string (no characters). 
  2250.  
  2251.          A decimal number is the ASCII code of the single character you wish. 
  2252.  
  2253.          Anything else is a character or characters that you wish. This can of 
  2254.           course include normal command line hexadecimal codes. 
  2255.  
  2256.  This switch can be handy as the default characters could easily be misread as 
  2257.  normal characters. If your viewer supports some of the extended characters 
  2258.  (below the space or above ASCII 127) then this can make debug output much 
  2259.  easier to read. 
  2260.  
  2261.  Display List In Your Viewer 
  2262.  
  2263.  The following code allows you to create a list of possible codes for you to 
  2264.  examine in the particular viewer that you will be using to look for good 
  2265.  distinct characters. These will/may have to be changed if you change your 
  2266.  viewer. 
  2267.  
  2268.  Just cut and paste the following: 
  2269.  
  2270.       #define    DisplayX  call Say left(d2c(x),6) || left(x,9) || '{x' || d2x(x) || '}'
  2271.       #DefineRexx ''
  2272.          ;--- Title ---------------------------------------------------------------
  2273.          call Say '';
  2274.          call Say 'CHAR  DECIMAL  HEX STRING'
  2275.          call Say '~~~~  ~~~~~~~  ~~~~~~~~~~'
  2276.  
  2277.          ;--- Do all but ASCII code 0 and 9, 10,13 --------------------------------
  2278.          do  x = 1 to 255
  2279.              if  x <> 9 & x <> 10 & x <> 13 then
  2280.              do
  2281.                  <$DisplayX>
  2282.              end;
  2283.          end;
  2284.  
  2285.          ;--- Now do ASCII 0 (some editors/viewers will NOT HANDLE THIS!) ---------
  2286.          x = 0; <$DisplayX>
  2287.          call Say '';
  2288.       #DefineRexx
  2289.  
  2290.  EXAMPLE 
  2291.  
  2292.  The following characters look good in the version of notepad I'm using. 
  2293.  
  2294.       PPWIZARD /DebugChars:187,171,165
  2295.  
  2296.  
  2297. ΓòÉΓòÉΓòÉ 5.13. /DebugCols ΓòÉΓòÉΓòÉ
  2298.  
  2299. Switch /DebugCols:0OrMaxNumberCols 
  2300.  
  2301. This is a PPWIZARD command line switch. You can set up your own default 
  2302. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2303.  
  2304. PPWIZARD can output some extremely long lines when debug is on (/Debug used 
  2305. etc). This switch allows you to set the longest line allowed. A line if 
  2306. truncated will actually be a bit longer as the fact that a line is truncated if 
  2307. too long is appended to the end of the line. 
  2308.  
  2309. If "0" is passed then there is no limit on the line length otherwise it must be 
  2310. a positive value. 
  2311.  
  2312.  
  2313. ΓòÉΓòÉΓòÉ 5.14. /DebugTime ΓòÉΓòÉΓòÉ
  2314.  
  2315. Switch /DebugTime[:NoOrFormat] 
  2316.  
  2317. This is a PPWIZARD command line switch. You can set up your own default 
  2318. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2319.  
  2320. By default ppwizard outputs the elapsed time (short display format) at the 
  2321. start of any debug line it outputs. This option allows you to select a longer 
  2322. format (HH:MM:SS.99) or turn off time generation altogether. 
  2323.  
  2324. Outputting the time can help you identify areas of code that may be taking 
  2325. longer than you'd expect to execute. 
  2326.  
  2327. The parameter should be one of the following values: 
  2328.  
  2329.          N or NO 
  2330.  
  2331.          L or LONG 
  2332.  
  2333.          S or SHORT 
  2334.  
  2335.  Note that ppwizard is optimised for fast execution with debug turned off, and 
  2336.  in fact may perform extra work when debug is on (on the assumption that 
  2337.  execution time is not an issue). For these reasons you should use the timings 
  2338.  you obtain as a guide only. 
  2339.  
  2340.  Note that a regina bug (in versions less than 2.0) prevents this from working 
  2341.  correctly at this time. 
  2342.  
  2343.  
  2344. ΓòÉΓòÉΓòÉ 5.15. /Define ΓòÉΓòÉΓòÉ
  2345.  
  2346. Switch /Define:Variable=Contents 
  2347.  
  2348. This is a PPWIZARD command line switch. You can set up your own default 
  2349. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2350.  
  2351. This command sets variables (like #define), but from the command line. This 
  2352. would typically be done to pass information to the script via the command line 
  2353. (possibly version number information or similar) removing the requirement to 
  2354. edit your source code. 
  2355.  
  2356. You can set as many variables as you wish by using the switch once for each 
  2357. variable. 
  2358.  
  2359. If the contents needs to include a space you should use "<?Space>" instead. 
  2360.  
  2361. I recommend that if you use this switch you also ensure that you are also using 
  2362. the *CmdLine" dependancy type so that if you change the value of the switch 
  2363. then a rebuild will occur (look at generated dependancy files if unsure). 
  2364.  
  2365. EXAMPLE 
  2366.  
  2367. Define 2 variables 
  2368.  
  2369.     ppwizard 1.in /output:out\*.out /CrLf /Define:OpSys=OS/2
  2370.  
  2371. In your code you could do: 
  2372.  
  2373.     #if '<$OpSys>' = 'OS/2'
  2374.         ...
  2375.     #elseif
  2376.         ...
  2377.     #endif
  2378.  
  2379.  
  2380. ΓòÉΓòÉΓòÉ 5.16. /DeleteOnError ΓòÉΓòÉΓòÉ
  2381.  
  2382. Switch /DeleteOnError[:YesOrNo] 
  2383.  
  2384. This is a PPWIZARD command line switch. You can set up your own default 
  2385. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2386.  
  2387. By default PPWIZARD deletes any generated files when an error occurs. This 
  2388. makes it more friendly in normal MAKE files which will then correctly restart 
  2389. the build process. You may wish to promote warnings to errors using the 
  2390. "Warnings" option. 
  2391.  
  2392. If not disabled, PPWIZARD will on error delete all files that it knows about, 
  2393. so in some cases it relies on you having correctly indicated output 
  2394. dependancies with the #DependsOn command or AddOutputFileToDependancyList() 
  2395. routine. PPWIZARD will ignore file deletion errors (what can it do?). 
  2396.  
  2397.  
  2398. ΓòÉΓòÉΓòÉ 5.17. /DeletePrev ΓòÉΓòÉΓòÉ
  2399.  
  2400. Switch /DeletePrev[:YesOrNo] 
  2401.  
  2402. This is a PPWIZARD command line switch. You can set up your own default 
  2403. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2404.  
  2405. By default PPWIZARD deletes any files generated on a previous build before 
  2406. starting the next build. The build will fail if a file can't be deleted. 
  2407.  
  2408. This switch is useful where a single input file can produce many output files. 
  2409. In these cases obsolete files can easily build up in the output directories. 
  2410.  
  2411. The deletion process uses the dependancy file built by the previous build so 
  2412. you must also be using the "/DependsOn" switch for older files to be deleted. 
  2413.  
  2414. If you were to rely on this switch deleting older files then you would also 
  2415. wish to use the "/DeleteOnError" switch. 
  2416.  
  2417. Obviously this process is not perfect, if the machine traps and reboots during 
  2418. a build nothing will delete those files that were generated. Also the complete 
  2419. deletion of a obsolete input file does not cause the deletion of the associated 
  2420. output files (yet)... 
  2421.  
  2422. To cover all bases you could generate into a unique directory (or generate 
  2423. distinctive filenames) for those processes that generate multiple files and use 
  2424. a BEFORE "/Hook" switch to clean up the directory where a rebuild is required. 
  2425.  
  2426. WARNING 
  2427.  
  2428. I have still not figured out a clean/easy way of deleting obsolete dependancy 
  2429. and output files where the input file is removed. When I do so this switch is 
  2430. likely to be affected (possibly different parameters or removed). 
  2431.  
  2432.  
  2433. ΓòÉΓòÉΓòÉ 5.18. /DependsOn ΓòÉΓòÉΓòÉ
  2434.  
  2435. Switch /DependsOn:[-]EditMask 
  2436.  
  2437. This is a PPWIZARD command line switch. You can set up your own default 
  2438. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2439.  
  2440. This option requires a parameter which controls how the "InputFile" parameter 
  2441. is transformed into the name of a dependancy file.  The default is that there 
  2442. is no dependancy file (therefore dependancies are not checked).  If you use 
  2443. dependancy files then the output is only built if required (a source file has 
  2444. changed). 
  2445.  
  2446. Unless you preceeded the EditMask parameter with a '-' the dependancy checking 
  2447. progress is displayed. 
  2448.  
  2449. PPWIZARD knows how to create a complete dependancy file unless you access files 
  2450. directly (via rexx with "linein()", "lineout(), "charin()" or similar 
  2451. functions). If you do directly access a file you will need to help ppwizard by 
  2452. using the #DependsOn command or the AddInputFileToDependancyList() or 
  2453. AddOutputFileToDependancyList() rexx functions. 
  2454.  
  2455. An edit mask is basically much like a file (with path if required) and will 
  2456. contain zero or one special characters as follows: 
  2457.  
  2458.        1. *.* or {$SHORT} 
  2459.           This gets replaced with the short filename (no path) of the current 
  2460.           input file.
  2461.  
  2462.        2. * or {$BASE} 
  2463.           This gets replaced with the short filename (less path and extension) 
  2464.           of the current input file.
  2465.  
  2466.        3. {$FULL} 
  2467.           This gets replaced with the full filename (with path) of the current 
  2468.           input file.
  2469.  
  2470.        4. ? or {$PATH} 
  2471.           This gets replaced with the path (including terminating slash) of the 
  2472.           current input file. This is most likely to be of use if you want to 
  2473.           position generated files relative to the input file and your mask 
  2474.           scans subdirectories. For example "?OUT\*.HTM".
  2475.  
  2476.        5. {$path} 
  2477.           This allows you to set up a separate tree for generated filenames, 
  2478.           the input mask and file are examined and the relative path extracted, 
  2479.           the result is either blank ('') or a relative path that ends with a 
  2480.           path separator. Note for this to work the input mask must either use 
  2481.           an absolute path, begin with '.' or '..' followed by slash or not 
  2482.           have a path attached at all otherwise ppwizard will abort. It would 
  2483.           be pointless to use this sort of path unless subdirectories are being 
  2484.           scanned. You may wish to investigate the /BaseDir switch.
  2485.  
  2486.  Note that unix type operating systems will probably have problems with "$path" 
  2487.  etc (to unix this means replace with the "path" environment variable's 
  2488.  contents). You need to hide or escape the dollar sign, so use either 
  2489.  "{x24}path" or "\$path" instead.
  2490.  
  2491.  The "EditMask" can be absolute or relative (your exact circumstances will 
  2492.  determine your choice). 
  2493.  
  2494.  Note that resultant relative filenames are always relative to the current 
  2495.  directory. 
  2496.  
  2497.  While you control the case of the mask you can't control the case of the part 
  2498.  that replaces the '*'.  What you can do is ensure the whole name is either in 
  2499.  upper or lower case with the /FileNames switch. 
  2500.  
  2501.  This switch can be used any number of times and will affect all input masks 
  2502.  that follow. For backwards compatability, if an input mask is found before 
  2503.  this switch then the very last instance of this switch is used for these. 
  2504.  
  2505.  EXAMPLE 
  2506.  
  2507.  In the following example the command will check/create a file called 
  2508.  "OUT\DEPEND\IN.DEP": 
  2509.  
  2510.       +-[ MAKEIT.CMD ]------------------------------------------------+
  2511.       | @echo off                                                     |
  2512.       | ppwizard IN.IT /Output:OUT\*.html /DependsOn:OUT\DEPEND\*.DEP |
  2513.       | if errorlevel 1 echo ERROR: Command failed!                   |
  2514.       +---------------------------------------------------------------+
  2515.  
  2516.  
  2517. ΓòÉΓòÉΓòÉ 5.19. /DependsOnComplete ΓòÉΓòÉΓòÉ
  2518.  
  2519. Switch /DependsOnComplete[:YesOrNo] 
  2520.  
  2521. This is a PPWIZARD command line switch. You can set up your own default 
  2522. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2523.  
  2524. This switch alters the way "/DependsOn" works. 
  2525.  
  2526. Normally ppwizard is very strict in its input dependancy checking in that it 
  2527. puts itself and any spelling dictionaries used in the list as well as checking 
  2528. command line switches. This means that when one of these items changes 
  2529. everything gets remade. While the safest option is to leave it on you may wish 
  2530. to turn it off. 
  2531.  
  2532. Note that this switch controls the building of the dependancy file. Existing 
  2533. dependancy files will need to rebuild at least once under the new setting for 
  2534. everything to work as you wish, for this reason you may wish to delete any 
  2535. existing dependancy files when you change the setting. 
  2536.  
  2537. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  2538. one of the following values is expected: 
  2539.  
  2540.          Y 
  2541.          N 
  2542.          YES 
  2543.          NO 
  2544.  
  2545.  
  2546. ΓòÉΓòÉΓòÉ 5.20. /DependsOnWarnings ΓòÉΓòÉΓòÉ
  2547.  
  2548. Switch /DependsOnWarnings[:YesOrNo] 
  2549.  
  2550. This is a PPWIZARD command line switch. You can set up your own default 
  2551. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2552.  
  2553. This switch alters the way "/DependsOn" works. 
  2554.  
  2555. By default ppwizard will not generate the dependancy file if warnings are 
  2556. generated. Warnings are considered to be abnormal conditions which are not 
  2557. serious enough to be considered to be an error. You are expected to remove or 
  2558. prevent the warnings. 
  2559.  
  2560. By using this switch and specifying "NO" you are indicating that the dependancy 
  2561. file should be generated even if warnings are generated. 
  2562.  
  2563. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  2564. one of the following values is expected: 
  2565.  
  2566.          Y 
  2567.          N 
  2568.          YES 
  2569.          NO 
  2570.  
  2571.  
  2572. ΓòÉΓòÉΓòÉ 5.21. /DropFiles ΓòÉΓòÉΓòÉ
  2573.  
  2574. Switch /DropFiles 
  2575.  
  2576. This is a PPWIZARD command line switch. You can set up your own default 
  2577. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2578.  
  2579. This switch simply tells PPWIZARD to forget any filemasks it has been told 
  2580. about. 
  2581.  
  2582. One reason for using in might be that you have set up a project containing your 
  2583. favorite options and a default mask (lets say "*.IT"), if you wished to use the 
  2584. project file but not process "*.IT" then this flag can be used as shown in the 
  2585. example below: 
  2586.  
  2587.     ppwizard @MyProj /DropFiles some*.it
  2588.  
  2589.  
  2590. ΓòÉΓòÉΓòÉ 5.22. /Exclude ΓòÉΓòÉΓòÉ
  2591.  
  2592. Switch /Exclude:FileMask 
  2593.  
  2594. This is a PPWIZARD command line switch. You can set up your own default 
  2595. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2596.  
  2597. Sometimes you may wish to process most files with a few exceptions, this switch 
  2598. allows you to specify those exceptions.  The switch may be used as many times 
  2599. as required. 
  2600.  
  2601.     ppwizard *.IT /Exclude:TEST*.IT /Exclude:TRY?.IT /Output:OUT\*.html
  2602.  
  2603.  
  2604. ΓòÉΓòÉΓòÉ 5.23. /Exec ΓòÉΓòÉΓòÉ
  2605.  
  2606. Switch /Exec:[{RcTest}][!]Command 
  2607.  
  2608. This is a PPWIZARD command line switch. You can set up your own default 
  2609. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2610.  
  2611. This switch allows you to specify a command which will be executed immediately. 
  2612.  
  2613. Normally the command output is hidden and captured if in debug mode. To see the 
  2614. output preceed the command with the '!' character. 
  2615.  
  2616. If "RcTest" is not supplied then the return code is ignored otherwise it is a 
  2617. rexx expression where the rexx variable "CmdRc" holds the commands return code. 
  2618. A boolean result is expected with TRUE meaning the validation was successful. 
  2619.  
  2620.  
  2621. ΓòÉΓòÉΓòÉ 5.24. /ErrorFile ΓòÉΓòÉΓòÉ
  2622.  
  2623. Switch /ErrorFile:[+]FileName 
  2624.  
  2625. This is a PPWIZARD command line switch. You can set up your own default 
  2626. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2627.  
  2628. By default ppwizard duplicates any displayed error message to a file called 
  2629. "PPWIZARD.$$E" in the current directory. Again by default this file is not 
  2630. deleted when ppwizard starts but is appended to as required. This facility is 
  2631. very useful for people who don't like the command prompt and use windows 
  2632. explorer or similar (as it can be difficult tell what caused a build failure). 
  2633.  
  2634. You can turn the error file generation off or change the filename, the 
  2635. directory it gets created in or whether or not it gets deleted or appended to. 
  2636.  
  2637. The environment variable "PPWIZARD_ERRORFILE" is an alternative way to set the 
  2638. filename. It takes the desired filename (not a file mask). If the filename 
  2639. begins with "+" then the file is appended to and not deleted every time 
  2640. ppwizard starts. 
  2641.  
  2642. If no parameter is supplied on this switch then error file generation is turned 
  2643. off otherwise the format is exactly the same as that described for the 
  2644. environment variable. 
  2645.  
  2646. Note that this switch can only take effect from the time that ppwizard is 
  2647. processing the command line and has seen the switch, so it can not handle any 
  2648. errors that occur before this. You may wish to use the environment variable to 
  2649. set it and in any case use this switch as early as possible on the command 
  2650. line. 
  2651.  
  2652. Another thing to keep in mind is that output to the file only begins after 
  2653. ppwizard has detected an error so some "context" information may be lost in 
  2654. which case you should have a look at the /ConsoleFile switch as well. 
  2655.  
  2656. EXAMPLE 
  2657.  
  2658. In the following example we use the switch to specify a new name and directory 
  2659. for the error file and we don't want to keep appending to it: 
  2660.  
  2661.     ppwizard *.IT /ErrorFile:out\PPWIZARD.ERR /Output:OUT\*.html
  2662.  
  2663. This shows how the error file generation can be turned off: 
  2664.  
  2665.     ppwizard *.IT /ErrorFile /Output:OUT\*.html
  2666.  
  2667.  
  2668. ΓòÉΓòÉΓòÉ 5.25. /FileNames ΓòÉΓòÉΓòÉ
  2669.  
  2670. Switch /FileNames:TranslateType 
  2671.  
  2672. This is a PPWIZARD command line switch. You can set up your own default 
  2673. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2674.  
  2675. Normally the case of output filenames are not modified, you can override this 
  2676. behaviour with this command line switch.  It requires either "Upper" or "Lower" 
  2677. as a parameter. 
  2678.  
  2679.  
  2680. ΓòÉΓòÉΓòÉ 5.26. /FilterInput ΓòÉΓòÉΓòÉ
  2681.  
  2682. Switch /FilterInput:RexxCmdFile 
  2683.  
  2684. This is a PPWIZARD command line switch. You can set up your own default 
  2685. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2686.  
  2687. This will probably be a rarely used option.  This switch allows you to 
  2688. translate file input a line at a time.  The mechanism provides the filter 
  2689. enough information to perform complex processing (in case required).  Your 
  2690. filter routine will return the possibly changed line or lines. 
  2691.  
  2692. In most cases it would probably be easier to write a translation procedure as a 
  2693. separate step before PPWIZARD is invoked (however sometimes this may not be 
  2694. practical). 
  2695.  
  2696. The rexx filter code you identify will be passed the following arguments: 
  2697.  
  2698.        1. The literal 'I' indicates that input is being filtered. 
  2699.  
  2700.        2. The line as read by rexx (still has comments and all whitespace). 
  2701.  
  2702.        3. The name of the file where the line came from. 
  2703.  
  2704.        4. The line number of the source file being processed (first line is 1). 
  2705.  
  2706.        5. The overall input line number (counter). 
  2707.  
  2708.        6. The newline character you should use if returning more than one line. 
  2709.  
  2710.  The following environment variables are also available for use: 
  2711.  
  2712.        1. PPWIZARD_VER_II 
  2713.           This variable contains the version number of the interface used by 
  2714.           this program.  This version number will only change when PPWIZARD has 
  2715.           been modified in such a way that existing input filters could break. 
  2716.           It is recommended that you validate the interface in your filter. 
  2717.  
  2718.        2. PPWIZARD_DEBUG 
  2719.           This variable tells you the current debug state ('Y' means on).  This 
  2720.           can be modified by the #debug command or the "/debug" command line 
  2721.           switch. 
  2722.  
  2723.        3. Your Own Variables 
  2724.           You can create your own state variables in the environment. 
  2725.  
  2726.  I have a need where each input line is encrypted to prevent tampering by 
  2727.  users, the source is divided over many header files. For a number of reasons I 
  2728.  do not wish to perform a separate step to get the files in the clear.  This 
  2729.  switch is my generic solution. 
  2730.  
  2731.  WHAT YOU RETURN 
  2732.  
  2733.        1. You may modify the passed line in any way you wish and return the 
  2734.           result. 
  2735.  
  2736.        2. You may pass back more than one line by separating the lines with the 
  2737.           passed newline character.  This allows you to insert macros or 
  2738.           #include instructions. 
  2739.  
  2740.        3. You may drop a line altogether by returning the string value 
  2741.           "d2c(0)". 
  2742.  
  2743.        4. You may indicate an error by returning "d2c(0)" followed the error 
  2744.           message, processing will stop. 
  2745.  
  2746.  EXAMPLE OF INPUT FILTER 
  2747.  
  2748.   /************************************************/
  2749.   /* Stupid non-useful example of an input filter */
  2750.   /************************************************/
  2751.  
  2752.   /*--- Get ALL parameters ----------------------------------------------------*/
  2753.   FilterType   = arg(1);
  2754.   TheLine      = arg(2);
  2755.   FromFile     = arg(3);
  2756.   FromFileLine = arg(4);
  2757.   TotalLine    = arg(5);
  2758.   NewLine      = arg(6);
  2759.  
  2760.   /*--- Check ONCE if on correct interface ------------------------------------*/
  2761.   if  TotalLine = 1 then
  2762.   do
  2763.      /*--- Filter written to interface version "98.131" --------------------------*/
  2764.      WrittenToFilterVer = "98.131";
  2765.      CallersVer         = GetEnv("PPWIZARD_VER_II");
  2766.      if  CallersVer <> WrittenToFilterVer then
  2767.          return(d2c(0) || 'FILTERIN: Interface written to version ' || WrittenToFilterVer || ' (found ' || CallersVer || ')' );
  2768.   end;
  2769.  
  2770.   /*--- Get current debug state (output input line if debug is on) ------------*/
  2771.   DebugOn = GetEnv("PPWIZARD_DEBUG");
  2772.   if DebugOn = 'Y' then
  2773.      say 'FILTERIN: #' || TotalLine || ' -> ' || TheLine;
  2774.  
  2775.   /*--- Process the input -----------------------------------------------------*/
  2776.   if  TotalLine = 1 then
  2777.   do
  2778.      /*--- We wish to drop the 1st line ---------------------------------------*/
  2779.      if  DebugOn = 'Y' then
  2780.          say '          We are dropping this line';
  2781.       return(d2c(0));
  2782.   end;
  2783.   else
  2784.   do
  2785.      /*--- Now either insert a line (if 4th) or return line unchanged ---------*/
  2786.      if  TotalLine = 4 then
  2787.          return(TheLine || NewLine || 'This line was inserted after the 4th line input line!');
  2788.      else
  2789.          return(TheLine);
  2790.   end;
  2791.  
  2792.  
  2793.   /*===========================================================================*/
  2794.   GetEnv:
  2795.   /*                                                                           */
  2796.   /* arg(1) : Name of environment variable.                                    */
  2797.   /*===========================================================================*/
  2798.      return( value(arg(1),,'OS2ENVIRONMENT') );
  2799.  
  2800.  
  2801. ΓòÉΓòÉΓòÉ 5.27. /FilterOutput ΓòÉΓòÉΓòÉ
  2802.  
  2803. Switch /FilterOutput:RexxCmdFile 
  2804.  
  2805. This is a PPWIZARD command line switch. You can set up your own default 
  2806. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2807.  
  2808. This will probably be a rarely used option.  This switch allows you to 
  2809. translate all generated lines a line at a time.  The mechanism provides the 
  2810. filter enough information to perform complex processing (in case required). 
  2811. Your filter program actually writes all output lines. 
  2812.  
  2813. In most cases it would probably be easier to write a translation procedure as a 
  2814. separate step after PPWIZARD has completed (however sometimes this may not be 
  2815. practical). 
  2816.  
  2817. The rexx filter code you identify will be passed the following arguments: 
  2818.  
  2819.        1. The literal 'O' indicates that output is being filtered. 
  2820.  
  2821.        2. The generated line without terminating newline. 
  2822.  
  2823.        3. The name of the output file. 
  2824.  
  2825.        4. The number of lines already generated to the file (starts at 0). 
  2826.  
  2827.        5. The overall number of lines generated. 
  2828.  
  2829.        6. The newline character(s) that need to terminate each line that you 
  2830.           write.  The value of the newline may change if /CrLf is used. 
  2831.  
  2832.  The following environment variables are also available for use: 
  2833.  
  2834.        1. PPWIZARD_VER_OI 
  2835.           This variable contains the version number of the interface used by 
  2836.           this program.  This version number will only change when PPWIZARD has 
  2837.           been modified in such a way that existing output filters could break. 
  2838.           It is recommended that you validate the interface in your filter. 
  2839.  
  2840.        2. PPWIZARD_DEBUG 
  2841.           This variable tells you the current debug state ('Y' means on).  This 
  2842.           can be modified by the #debug command or the "/debug" command line 
  2843.           switch. 
  2844.  
  2845.        3. Your Own Variables 
  2846.           The filter program can create its own state variables in the 
  2847.           environment, this is demonstrated in the example further on.  You can 
  2848.           also set environment variables with the built in SetEnv routine. 
  2849.  
  2850.  WHAT YOU RETURN 
  2851.  
  2852.        1. If successful you should return the string "OK:" followed by the 
  2853.           number of lines you wrote to the output file.  For example you would 
  2854.           return "OK:0" if you dropped the passed line. 
  2855.  
  2856.        2. Any string that does not begin with "OK:" indicates an error. The 
  2857.           message will be displayed and processing will stop. 
  2858.  
  2859.  EXAMPLE OF OUTPUT FILTER 
  2860.  
  2861.   /*************************************************/
  2862.   /* Stupid non-useful example of an output filter */
  2863.   /*************************************************/
  2864.  
  2865.   /*--- Get ALL parameters ----------------------------------------------------*/
  2866.   FilterType   = arg(1);
  2867.   TheLine      = arg(2);
  2868.   ToFile       = arg(3);
  2869.   ToFileLine   = arg(4);                                     /* Written so far */
  2870.   TotalLine    = arg(5);                                     /* Written so far */
  2871.   NewLine      = arg(6);
  2872.  
  2873.   /*--- Check "ONCE" if on correct interface (Actually checked twice) ---------*/
  2874.   if  TotalLine = 0 then
  2875.   do
  2876.      /*--- Filter written to interface version "98.132" -----------------------*/
  2877.      WrittenToFilterVer = "98.132";
  2878.      CallersVer         = GetEnv("PPWIZARD_VER_OI");
  2879.      if  CallersVer <> WrittenToFilterVer then
  2880.          return( 'FILTEROUT: Interface written to version ' || WrittenToFilterVer || ' (found ' || CallersVer || ')' );
  2881.   end;
  2882.  
  2883.   /*--- Get current debug state (output input line if debug is on) ------------*/
  2884.   DebugOn = GetEnv("PPWIZARD_DEBUG");
  2885.   if DebugOn = 'Y' then
  2886.      say 'FILTEROUT: #' || TotalLine+1 || ' -> ' || TheLine;
  2887.  
  2888.   /*--- If first line drop (this is complicated by line counters not changing!)*/
  2889.   if  TotalLine = 0 then
  2890.   do
  2891.      /*--- Only drop the first "first" file! ----------------------------------*/
  2892.      if  GetEnv('FiltOut_0') = '' then
  2893.      do
  2894.          /*--- We wish to drop the 1st line -----------------------------------*/
  2895.          if  DebugOn = 'Y' then
  2896.              say '          We are dropping the first line of output';
  2897.          call SetEnv 'FiltOut_0', 'Line 0 dropped';
  2898.          return("OK:0");
  2899.      end;
  2900.   end;
  2901.  
  2902.   /*--- All lines reversed (except inserted 5th) ------------------------------*/
  2903.   NumberOfLines = 1;
  2904.   ToWrite       = reverse(TheLine);
  2905.   if  TotalLine = 3 then
  2906.   do
  2907.      /*--- We are inserting a line (generating 2) -----------------------------*/
  2908.      NumberOfLines = 2;
  2909.      ToWrite       = ToWrite || NewLine || 'This line was inserted after the 4th output line line!';
  2910.   end;
  2911.  
  2912.   /*--- Output the data -------------------------------------------------------*/
  2913.   if  0 <> charout(ToFile, ToWrite || NewLine) then
  2914.      return('Write to "' || ToFile || '" failed!');
  2915.   else
  2916.      return("OK:" || NumberOfLines);
  2917.  
  2918.  
  2919.  
  2920.  
  2921.   /*===========================================================================*/
  2922.   GetEnv:
  2923.   /*                                                                           */
  2924.   /* arg(1) : Name of environment variable.                                    */
  2925.   /*===========================================================================*/
  2926.      return( value(arg(1),,'OS2ENVIRONMENT') );
  2927.  
  2928.  
  2929.  
  2930.  
  2931.   /*===========================================================================*/
  2932.   SetEnv:
  2933.   /*                                                                           */
  2934.   /* arg(1) : Name of environment variable.                                    */
  2935.   /* arg(2) : New Value.                                                       */
  2936.   /*                                                                           */
  2937.   /* Returns original value of the environment variable.                       */
  2938.   /*===========================================================================*/
  2939.      return( value(arg(1),arg(2),'OS2ENVIRONMENT') );
  2940.  
  2941.  
  2942. ΓòÉΓòÉΓòÉ 5.28. /GetEnv ΓòÉΓòÉΓòÉ
  2943.  
  2944. Switch /GetEnv:EnvVarName 
  2945.  
  2946. This is a PPWIZARD command line switch. You can set up your own default 
  2947. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2948.  
  2949. This allows you to specify an environment variable which must exist and whose 
  2950. value is more PPWIZARD command line parameters. 
  2951.  
  2952. This switch could be used to handle long command line, it effectively allows 
  2953. you to have an infinitely long command line since the included contents can 
  2954. itself refer to other environment variables. 
  2955.  
  2956.  
  2957. ΓòÉΓòÉΓòÉ 5.29. /HideCmd ΓòÉΓòÉΓòÉ
  2958.  
  2959. Switch /HideCmd:HideTemplate 
  2960.  
  2961. This is a PPWIZARD command line switch. You can set up your own default 
  2962. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  2963.  
  2964. This allows you to hide ppwizard commands, macros references or in fact 
  2965. anything between start and end tags that you specify. 
  2966.  
  2967. This could be useful for a number of reasons but probably the most common would 
  2968. be to hide ppwizard tags from a WYSIWYG html editor or browser. This would 
  2969. allow you to view the template of the web page without distractions (the 
  2970. browser will not display comments!). 
  2971.  
  2972. The "HideTemplate" indicates both the start and end markers with "{?}" marking 
  2973. the position of the hidden command, exceptions are: 
  2974.  
  2975.        1. HTML[] 
  2976.           This is shorthand for "<!--[{?}]-->". This is basically HTML comments 
  2977.           with extra square brackets. 
  2978.  
  2979.  I highly recommend that you do not try to use the SSI format as this can only 
  2980.  confuse people. 
  2981.  
  2982.  Example - Use of switch 
  2983.  
  2984.  In this case we wish to hide all ppwizard items within "<%" and "%>" tags, the 
  2985.  curley codes are used so as to be able to safely specify the "<" and ">" 
  2986.  characters (redirection characters in most operating systems) on the command 
  2987.  line. 
  2988.  
  2989.       /HideCmd:{x3C}%{?}%{x3E}
  2990.  
  2991.  To an ASP/JSP friendly GUI tool ppwizard commands would be handled better. 
  2992.  
  2993.  Example 
  2994.  
  2995.  In the following example "HTML[]" was used for a template: 
  2996.  
  2997.       <!--[#define X Value4X]-->
  2998.  
  2999.       <P>1<!--[<?Hash>]-->2<!--[<?Hash>]-->3<!--[<?Hash>]-->4<!--[<?Hash>]-->5
  3000.  
  3001.  
  3002. ΓòÉΓòÉΓòÉ 5.30. /Hook ΓòÉΓòÉΓòÉ
  3003.  
  3004. Switch /Hook[:When[;RexxFile]] 
  3005.  
  3006. This is a PPWIZARD command line switch. You can set up your own default 
  3007. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  3008.  
  3009. This switch allows you to call external Rexx code to perform processing at 
  3010. specific times. 
  3011.  
  3012. On success all hooks return a string which begins with "OK:", otherwise 
  3013. ppwizard treats the return code as an error and aborts processing. Some hooks 
  3014. allow you to pass information back to ppwizard (for example warning hooks can 
  3015. return "OK:IGNORE"). 
  3016.  
  3017. The rexx code for all hook types always gets passed these parameters: 
  3018.  
  3019.        1. Interface Version Number 
  3020.           I will modify this value if you need to do anything to get your hook 
  3021.           code running again. I recommend you check this value! 
  3022.  
  3023.        2. Source Location 
  3024.           This value will contain the current location in the source that you 
  3025.           are processing or "" if not processing any input file. It is intended 
  3026.           for display purposes only, do not assume any specific format as it 
  3027.           may change in the future. 
  3028.  
  3029.        3. When Code 
  3030.           The reason this hook was called (as described below). If you wish, 
  3031.           the same rexx code can be called for all hooks you process. In any 
  3032.           case I recommend that the value be validated in case someone uses it 
  3033.           incorrectly. 
  3034.  
  3035.  If no parameter is supplied on the "/HOOK" switch then all hooks are turned 
  3036.  off, otherwise the parameter is broken up into 2 components as follows: 
  3037.  
  3038.        1. When Code 
  3039.           This parameter if empty indicates that all hooks are being adjusted, 
  3040.           otherwise lists the hooks (seperated by ",") as follows: 
  3041.  
  3042.               GETFILELIST 
  3043.                This hook  allows you to create your own mask handler, this lets 
  3044.                you determine what the mask means, for example you may only wish 
  3045.                to process files that match the mask and were modified today. 
  3046.  
  3047.                Extra parameters are: 
  3048.  
  3049.                  a. File Mask Location 
  3050.                     This is any drive or path component of the file mask. 
  3051.  
  3052.                  b. File Mask Name 
  3053.                     This is the file mask less any drive or path component. 
  3054.                     Combining this with the location will rebuild the original 
  3055.                     mask. 
  3056.  
  3057.                  c. Scan Subdirectories 
  3058.                     Either 'Y' or 'N', did user preceed filemask with '+'? You 
  3059.                     can ignore this if you wish, after all you have full 
  3060.                     control in how you evaluate the filemask. 
  3061.  
  3062.                  d. Output File 
  3063.                     This is the name of the output file into which you are 
  3064.                     expected to place the full names of files to be processed 
  3065.                     (one per line). Blank lines are ignored but all other lines 
  3066.                     are not and leading and trailing whitespace is not removed. 
  3067.  
  3068.               BEFORE 
  3069.                This hook is called just before a build is started. 
  3070.  
  3071.                Extra parameters are: 
  3072.  
  3073.                  a. PPWH_INPUT 
  3074.                      Contains "" or the full name of the base input file.
  3075.  
  3076.                  b. PPWH_OUTPUT 
  3077.                      Contains "" or the name of the base output file.
  3078.  
  3079.                  c. PPWH_TEMPLATE 
  3080.                      Contains "" or the name of any template file being used. 
  3081.  
  3082.               AFTER 
  3083.                This hook is called after a build completes. 
  3084.  
  3085.                Extra parameters are: 
  3086.  
  3087.                  a. PPWH_INPUT 
  3088.                      Contains "" or the full name of the base input file.
  3089.  
  3090.                  b. PPWH_OUTPUT 
  3091.                      Contains "" or the name of the base output file.
  3092.  
  3093.                  c. PPWH_TEMPLATE 
  3094.                      Contains "" or the name of any template file being used. 
  3095.  
  3096.               WARNING 
  3097.                This hook is called for each warning that is not being ignored. 
  3098.  
  3099.                Extra parameters are: 
  3100.  
  3101.                  a. PPWH_INPUT 
  3102.                      Contains "" or the full name of the base input file.
  3103.  
  3104.                  b. PPWH_OUTPUT 
  3105.                      Contains "" or the name of the base output file.
  3106.  
  3107.                  c. PPWH_TEMPLATE 
  3108.                      Contains "" or the name of any template file being used. 
  3109.  
  3110.                  d. Warning Message Text 
  3111.                     This contains the text of the message. If you wish to cause 
  3112.                     ppwizard to completely ignore the warning then you should 
  3113.                     return "OK:IGNORE". To ignore a message but still increment 
  3114.                     the warning counter then return "OK:IGNORE+". 
  3115.  
  3116.               ERROR 
  3117.                This hook is called when an error occurs. 
  3118.  
  3119.                Extra parameters are: 
  3120.  
  3121.                  a. PPWH_INPUT 
  3122.                      Contains "" or the full name of the base input file.
  3123.  
  3124.                  b. PPWH_OUTPUT 
  3125.                      Contains "" or the name of the base output file.
  3126.  
  3127.                  c. PPWH_TEMPLATE 
  3128.                      Contains "" or the name of any template file being used. 
  3129.  
  3130.                  d. Number of lines 
  3131.                     This contains the number of lines, each one is in it's own 
  3132.                     environment variable. 
  3133.  
  3134.                     Each line can be found in the PPWH_ERROR? environment 
  3135.                     variable (where '?' is the line number). 
  3136.  
  3137.  Do not return anything but "OK:" otherwise you won't get the "see" the 
  3138.  original error text. 
  3139.  
  3140.  Note that you can specify any abbreviation of the above on the /hook switch, 
  3141.  so for example "a" is the same as "after". 
  3142.  
  3143.        2. RexxFile 
  3144.           This is the name of the rexx program that will be called to handle 
  3145.           the hooks you have indicated. If not supplied then the hooks 
  3146.           indicated are turned off. 
  3147.  
  3148.  Example Switches 
  3149.  
  3150.          REM *** CALL SAME HOOK for before, after and warnings ***
  3151.          /Hook:after,before,warning;hook.cmd
  3152.  
  3153.          REM *** CALL MULTI HOOKS for before, after and warnings ***
  3154.          /Hook:before;hookb.cmd /Hook:after;hooka.cmd /Hook:warning;hookw.cmd
  3155.  
  3156.          REM *** Reset some hooks ***
  3157.          /Hook:bef,a
  3158.  
  3159.          REM *** Reset all hooks ***
  3160.          /Hook
  3161.  
  3162.  Example - File Mask Handler 
  3163.  
  3164.  The example shows how "dir" could be used, unix people could use either "ls" 
  3165.  or "find" with appropriate switches to generate a list of files. In any case 
  3166.  the processing can be as complex or as simple as you wish. 
  3167.  
  3168.       /*---------------------------------------------------------------------------
  3169.       ;    MODULE NAME:   LISTFILE.CMD
  3170.       ;
  3171.       ;        $Author:   USER "Dennis"  $
  3172.       ;      $Revision:   1.0  $
  3173.       ;          $Date:   30 Mar 2001 18:05:30  $
  3174.       ;       $Logfile:   C:/DBAREIS/Projects.PVCS/MultiOs/PPWIZARD/listfile.cmd.pvcs  $
  3175.       ;
  3176.       ;    DESCRIPTION:   Simple hook file to demonstrate for a "GETFILELIST"
  3177.       ;                   hook works.
  3178.       ;
  3179.       ;                   Hook code would generally tend to be operating system
  3180.       ;                   specific.  This code was tested under OS/2 and would
  3181.       ;                   probably require MINOR changes to work elsewhere.
  3182.       ;----------------------------------------------------------------------------*/
  3183.  
  3184.       /*--- I highly recommend use of trap handlers for ALL rexx code -------------*/
  3185.       signal on NOVALUE name RexxTrapUninitializedVariable;
  3186.       signal on SYNTAX  name RexxTrapSyntaxError;
  3187.  
  3188.       /*--- Get parameters --------------------------------------------------------*/
  3189.       InterfaceVersion   = arg(1);
  3190.       InterfaceType      = arg(3);
  3191.       FileMaskLocn       = arg(4);
  3192.       FileMaskName       = arg(5);
  3193.       ScanSubdirectories = arg(6);    /* You can ignore if you wish (you might have your own way of flagging it) */
  3194.       OutputFile         = arg(7);
  3195.  
  3196.       /*--- Get shortname of this routine -----------------------------------------*/
  3197.       parse source . . RexxId;
  3198.       S1Pos    = lastpos('/', RexxId);
  3199.       S2Pos    = lastpos('\', RexxId);
  3200.       SlashPos = max(S1Pos, S2Pos);
  3201.       if SlashPos <> 0 then
  3202.          RexxId = substr(RexxId, SlashPos+1);
  3203.  
  3204.       /*--- Say what is going on --------------------------------------------------*/
  3205.       if GetEnv("PPWIZARD_DEBUG") = 'Y' then
  3206.       do
  3207.          /*--- Debug is on! -------------------------------------------------------*/
  3208.          say '';
  3209.          call SayIt 'arg(1) = Interface Version   = "' || InterfaceVersion   || '"';
  3210.          call SayIt 'arg(2) = Mask Location       = "' || FileMaskLocn       || '"';
  3211.          call SayIt 'arg(3) = Mask less Location  = "' || FileMaskName       || '"';
  3212.          call SayIt 'arg(4) = Scan Subdirs = Y|N  = "' || ScanSubdirectories || '"';
  3213.          call SayIt 'arg(5) = Temp File to create = "' || OutputFile         || '"';
  3214.       end;
  3215.  
  3216.       /*--- This code only designed to handle a single interface! -----------------*/
  3217.       ExpectedInterfaceVersion = '00.050';
  3218.       if InterfaceVersion <> ExpectedInterfaceVersion then
  3219.          Die('Unsupported Interface of "' || InterfaceVersion || '", Expected "' || ExpectedInterfaceVersion || '"');
  3220.  
  3221.       /*--- This code only designed to handle a single hook type! -----------------*/
  3222.       ExpectedInterfaceType = 'GETFILELIST';
  3223.       if InterfaceType <> ExpectedInterfaceType then
  3224.          Die('Unsupported Interface of "' || InterfaceType || '", Expected "' || ExpectedInterfaceType || '"');
  3225.  
  3226.       /*--- Want to scan subdirectories as well? (you can ignore this flag) -------*/
  3227.       if ScanSubdirectories = 'Y' then
  3228.          Subdir = ' /S'
  3229.       else
  3230.          Subdir = ''
  3231.  
  3232.       /*--- Get a list using "dir" (could be "ls" or "find" in unix) --------------*/
  3233.       Executing = '@dir "' || FileMaskLocn || FileMaskName || '" /F' || Subdir || ' > ' || OutputFile;
  3234.       if GetEnv("PPWIZARD_DEBUG") = 'Y' then
  3235.          call SayIt 'Executing: ' || Executing;
  3236.       Executing;
  3237.  
  3238.       /*--- Did the 'dir' command fail --------------------------------------------*/
  3239.       if Rc <> 0 then
  3240.          Die('"dir" returned a return code of ' || Rc);
  3241.  
  3242.       /*--- All OK ----------------------------------------------------------------*/
  3243.       exit('OK:');
  3244.  
  3245.  
  3246.  
  3247.       /*===========================================================================*/
  3248.       SayIt:
  3249.       /*===========================================================================*/
  3250.          say RexxId || ' : ' || arg(1);
  3251.          return;
  3252.  
  3253.  
  3254.       /*===========================================================================*/
  3255.       GetEnv:                                            /* OS/2 specific function */
  3256.       /*===========================================================================*/
  3257.          return( value(arg(1),,'OS2ENVIRONMENT') );
  3258.  
  3259.  
  3260.       /*===========================================================================*/
  3261.       Die:
  3262.       /*===========================================================================*/
  3263.          /*--- Return with error --------------------------------------------------*/
  3264.          ErrorLine = SIGL;
  3265.          call SayIt 'ERROR(Line ' || ErrorLine || ') - ' || arg(1);
  3266.          exit(arg(1));
  3267.  
  3268.  
  3269.       /*===========================================================================*/
  3270.       CommonTrapHandler:
  3271.       /*                                                                           */
  3272.       /* arg(1) = Failing Line                                                     */
  3273.       /* arg(2) = Type of trap (heading to be underlined)                          */
  3274.       /* arg(3) = Trap specific Title  (text description)                          */
  3275.       /* arg(4) = Trap specific Text                                               */
  3276.       /*===========================================================================*/
  3277.          /*--- Work out some details based on passed info -------------------------*/
  3278.          FailingLine     = arg(1);
  3279.          TrapHeading     = 'BUG: ' || arg(2);
  3280.          TextDescription = arg(3);
  3281.          Text            = arg(4);
  3282.  
  3283.          /*--- Work out name of THIS rexx procedure -------------------------------*/
  3284.          parse source . . SourceFileName;
  3285.  
  3286.          /*--- Display details of the failing rexx code ---------------------------*/
  3287.          say '';
  3288.          call SayIt copies('=+', 39);
  3289.          call SayIt TrapHeading;
  3290.          call SayIt copies('~', length(TrapHeading));
  3291.          call SayIt substr(TextDescription, 1 , 16) || ': ' || Text;
  3292.          call SayIt 'Failing Module  : ' || SourceFileName;
  3293.          call SayIt 'Failing Line #  : ' || FailingLine;
  3294.          call SayIt 'Failing Command : ' || strip(SourceLine(FailingLine));
  3295.          call SayIt copies('=+', 39);
  3296.  
  3297.          /*--- We won't let a failure in one subprocedure stop others working -----*/
  3298.          exit(TrapHeading || ' on line ' || FailingLine || ', ' || TextDescription || ': ' || Text);
  3299.  
  3300.  
  3301.       /*===========================================================================*/
  3302.       RexxTrapUninitializedVariable:
  3303.       /*===========================================================================*/
  3304.          /*--- Process the trap (it never returns) --------------------------------*/
  3305.          ReginaBug = SIGL;
  3306.          call CommonTrapHandler ReginaBug, 'NoValue Abort!', 'Unknown Variable', condition('D');
  3307.  
  3308.       /*===========================================================================*/
  3309.       RexxTrapSyntaxError:
  3310.       /*===========================================================================*/
  3311.          /*--- Process the trap (it never returns) --------------------------------*/
  3312.          ReginaBug = SIGL;
  3313.          call CommonTrapHandler ReginaBug, 'Syntax Error!', 'Reason', errortext(Rc);
  3314.  
  3315.  
  3316.  
  3317.  Example HOOK file [HOOK.CMD] 
  3318.  
  3319.  This example shows how one rexx procedure can handle many hook types (as well 
  3320.  as how to write a number of different hook types). 
  3321.  
  3322.   /*---------------------------------------------------------------------------
  3323.   ;    MODULE NAME:   HOOK.CMD
  3324.   ;
  3325.   ;        $Author:   USER "Dennis"  $
  3326.   ;      $Revision:   1.0  $
  3327.   ;          $Date:   30 Mar 2001 18:05:28  $
  3328.   ;       $Logfile:   C:/DBAREIS/Projects.PVCS/MultiOs/PPWIZARD/hook.cmd.pvcs  $
  3329.   ;
  3330.   ;    DESCRIPTION:   Simple example hook file.
  3331.   ;
  3332.   ;
  3333.   ;           NOTE:   This is an example skeleton only
  3334.   ;
  3335.   ;                   There is no requirement that all hooks use the same
  3336.   ;                   rexx procedure, they can each use their own if you
  3337.   ;                   wish.
  3338.   ;
  3339.   ;                   Trap Handlers are very simplistic
  3340.   ;
  3341.   ;                   Do not assume specific format for location = arg(2)
  3342.   ;
  3343.   ;                   filespec() is only available on OS/2! That is MINOR
  3344.   ;                   changes will be required to run on other operating
  3345.   ;                   systems.
  3346.   ;----------------------------------------------------------------------------*/
  3347.  
  3348.   /*--- I highly recommend use of trap handlers for ALL rexx code -------------*/
  3349.   signal on NOVALUE name RexxTrapUninitializedVariable;
  3350.   signal on SYNTAX  name RexxTrapSyntaxError;
  3351.  
  3352.   /*--- Get parameters --------------------------------------------------------*/
  3353.   InterfaceVersion   = arg(1);  /* Both ends must know exactly how things passed! */
  3354.   Location           = arg(2);  /* Location in source file                        */
  3355.   HookType           = arg(3);  /* What hook type do we want processed?           */
  3356.   InputFile          = arg(4);
  3357.   OutputFile         = arg(5);
  3358.   TemplateFile       = arg(6);
  3359.   WarningText        = arg(7);
  3360.   ErrorLineCount     = arg(7);
  3361.  
  3362.   /*--- Get shortname of this routine -----------------------------------------*/
  3363.   parse source . . RexxId;
  3364.   S1Pos    = lastpos('/', RexxId);
  3365.   S2Pos    = lastpos('\', RexxId);
  3366.   SlashPos = max(S1Pos, S2Pos);
  3367.   if SlashPos <> 0 then
  3368.      RexxId = substr(RexxId, SlashPos+1);
  3369.  
  3370.   /*--- Display "parameters" (if user has debug mode on) ----------------------*/
  3371.   if GetEnv("PPWIZARD_DEBUG") = 'Y' then
  3372.   do
  3373.      /*--- Debug mode is on ---------------------------------------------------*/
  3374.      call SayIt 'Hook Type    = "' || HookType                || '"';
  3375.      if  Location <> '' then
  3376.          call SayIt 'Source Locn  = "' || Location            || '"';
  3377.      call SayIt 'InputFile    = "' || InputFile   || '"';
  3378.      call SayIt 'TemplateFile = "' || TemplateFile || '"';
  3379.      call SayIt 'OutputFile   = "' || OutputFile  || '"';
  3380.   end;
  3381.  
  3382.   /*--- Lets set up default OK parm (return code) -----------------------------*/
  3383.   OkParm = '';
  3384.  
  3385.   /*--- Do hook specific processing -------------------------------------------*/
  3386.   select
  3387.      /*++++++++++++++++++++++++++++++++*/
  3388.      when HookType = "WARNING" then
  3389.      /*++++++++++++++++++++++++++++++++*/
  3390.      do
  3391.          /*--- Display if in debug mode ---------------------------------------*/
  3392.          if  GetEnv("PPWIZARD_DEBUG") = 'Y' then
  3393.              call SayIt 'WARNING = "' || WarningText  || '"';
  3394.  
  3395.          /*--- Log to file ----------------------------------------------------*/
  3396.  
  3397.          /*--- Tell caller to ignore ------------------------------------------*/
  3398.          OkParm = "IGNORE";
  3399.      end;
  3400.      /*++++++++++++++++++++++++++++++++*/
  3401.      when HookType = "ERROR" then
  3402.      /*++++++++++++++++++++++++++++++++*/
  3403.      do
  3404.          /*--- Display if in debug mode ---------------------------------------*/
  3405.          if  GetEnv("PPWIZARD_DEBUG") = 'Y' then
  3406.          do
  3407.              /*--- Display Each line ------------------------------------------*/
  3408.              do Line = 1 to ErrorLineCount
  3409.                 call SayIt 'ERROR TEXT  = "' || GetEnv("PPWH_ERROR" || Line)   || '"';
  3410.              end;
  3411.          end;
  3412.  
  3413.          /*--- Log to file ----------------------------------------------------*/
  3414.      end;
  3415.      /*++++++++++++++++++++++++++++++++*/
  3416.      otherwise
  3417.      /*++++++++++++++++++++++++++++++++*/
  3418.          nop;
  3419.   end;
  3420.  
  3421.   /*--- Say OK ----------------------------------------------------------------*/
  3422.   exit("OK:" || OkParm);
  3423.  
  3424.  
  3425.  
  3426.  
  3427.   /*===========================================================================*/
  3428.   SayIt:
  3429.   /*===========================================================================*/
  3430.      say RexxId || ' : ' || arg(1);
  3431.      return;
  3432.  
  3433.  
  3434.   /*===========================================================================*/
  3435.   GetEnv:
  3436.   /*                                                                           */
  3437.   /* arg(1) : Name of environment variable.                                    */
  3438.   /*===========================================================================*/
  3439.      return( value(arg(1),,'OS2ENVIRONMENT') );
  3440.  
  3441.  
  3442.  
  3443.   /*===========================================================================*/
  3444.   CommonTrapHandler:
  3445.   /*                                                                           */
  3446.   /* arg(1) = Failing Line                                                     */
  3447.   /* arg(2) = Type of trap (heading to be underlined)                          */
  3448.   /* arg(3) = Trap specific Title  (text description)                          */
  3449.   /* arg(4) = Trap specific Text                                               */
  3450.   /*===========================================================================*/
  3451.      /*--- Work out some details based on passed info -------------------------*/
  3452.      FailingLine     = arg(1);
  3453.      TrapHeading     = 'BUG: ' || arg(2);
  3454.      TextDescription = arg(3);
  3455.      Text            = arg(4);
  3456.  
  3457.      /*--- Work out name of THIS rexx procedure -------------------------------*/
  3458.      parse source . . SourceFileName;
  3459.  
  3460.      /*--- Display details of the failing rexx code ---------------------------*/
  3461.      say '';
  3462.      call SayIt copies('=+', 39);
  3463.      call SayIt TrapHeading;
  3464.      call SayIt copies('~', length(TrapHeading));
  3465.      call SayIt substr(TextDescription, 1 , 16) || ': ' || Text;
  3466.      call SayIt 'Failing Module  : ' || SourceFileName;
  3467.      call SayIt 'Failing Line #  : ' || FailingLine;
  3468.      call SayIt 'Failing Command : ' || strip(SourceLine(FailingLine));
  3469.      call SayIt copies('=+', 39);
  3470.  
  3471.      /*--- We won't let a failure in one subprocedure stop others working -----*/
  3472.      exit(TrapHeading || ' on line ' || FailingLine || ', ' || TextDescription || ': ' || Text);
  3473.  
  3474.  
  3475.   /*===========================================================================*/
  3476.   RexxTrapUninitializedVariable:
  3477.   /*===========================================================================*/
  3478.      /*--- Process the trap (it never returns) --------------------------------*/
  3479.      ReginaBug = SIGL;
  3480.      call CommonTrapHandler ReginaBug, 'NoValue Abort!', 'Unknown Variable', condition('D');
  3481.  
  3482.   /*===========================================================================*/
  3483.   RexxTrapSyntaxError:
  3484.   /*===========================================================================*/
  3485.      /*--- Process the trap (it never returns) --------------------------------*/
  3486.      ReginaBug = SIGL;
  3487.      call CommonTrapHandler ReginaBug, 'Syntax Error!', 'Reason', errortext(Rc);
  3488.  
  3489.  
  3490. ΓòÉΓòÉΓòÉ 5.31. /HTML ΓòÉΓòÉΓòÉ
  3491.  
  3492. Switch /HTML 
  3493.  
  3494. This is a PPWIZARD command line switch. You can set up your own default 
  3495. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  3496.  
  3497. This switch should rarely be required as html mode is the default mode unless 
  3498. all input files end in the extension ".X" (its use is recommended for rexx 
  3499. source code). 
  3500.  
  3501. On non unix operating systems lines end with carriage return followed by 
  3502. linefeed, with the internet unix has finally won (it only requires lines to 
  3503. terminate with a linefeed).  Web servers and browsers do not require the 
  3504. carriage return (which they ignore).  You can save an extra one character per 
  3505. line with use of the /CRLF switch. 
  3506.  
  3507. This switch can be used any number of times and will affect all input masks 
  3508. that follow. It also becomes the default mode for all files produced via the 
  3509. #Output command. For backwards compatability, if an input mask is found before 
  3510. any processing mode switch then the last instance of a processing mode switch 
  3511. is used these. 
  3512.  
  3513.  
  3514. ΓòÉΓòÉΓòÉ 5.32. /HtmlGenerator ΓòÉΓòÉΓòÉ
  3515.  
  3516. Switch /HtmlGenerator:Contents 
  3517.  
  3518. This is a PPWIZARD command line switch. You can set up your own default 
  3519. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  3520.  
  3521. By default when generating HTML, ppwizard will try to insert a meta tag similar 
  3522. to the following in the "HEAD" section: 
  3523.  
  3524.     <META NAME="GENERATOR" CONTENT="PPWIZARD version 99.231 on OS/2, FREE tool for OS/2, Windows, DOS and UNIX by Dennis Bareis (http://www.labyrinth.net.au/~dbareis/ppwizard.htm)">
  3525.  
  3526. You can turn off the generation of the tags altogether by specifying an empty 
  3527. value or you can supply alternative line(s). 
  3528.  
  3529. PPWIZARD is supplied as freeware and I would appreciate it if you at least 
  3530. mention PPWIZARD and its homepage in the pages that you generate (either in 
  3531. meta tags or comments). The switch is mainly supplied so that you can add your 
  3532. own details if you wish. 
  3533.  
  3534. If you wish to specify your own generator contents (or refer to ppwizard 
  3535. details in HTML comments) you can make use of these variables (on the command 
  3536. line replace '<' with '{x3C}' and '>' with '{x3E}') : 
  3537.  
  3538.        1. <?PpwizardAuthor> 
  3539.        2. <?PpwizardAuthorEmail> 
  3540.        3. <?PpwizardAuthorHomePage> 
  3541.        4. <?PpwizardHomePage> 
  3542.  
  3543.  The value you wish to give this switch is probably so large that you would 
  3544.  normally need to use the /GetEnv switch to get the information out of an 
  3545.  environment variable. 
  3546.  
  3547.  
  3548. ΓòÉΓòÉΓòÉ 5.33. /Inc2Cache ΓòÉΓòÉΓòÉ
  3549.  
  3550. Switch /Inc2Cache[:YesOrNo] 
  3551.  
  3552. This is a PPWIZARD command line switch. You can set up your own default 
  3553. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  3554.  
  3555. This switch can be used to override the way PPWIZARD includes files. This would 
  3556. not normally be required as PPWIZARD is likely to choose a good way. 
  3557.  
  3558. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  3559. one of the following values is expected: 
  3560.  
  3561.          Y 
  3562.          N 
  3563.          YES 
  3564.          NO 
  3565.  
  3566.  Warning 
  3567.  
  3568.  Loading the files to cache will of course require more memory than you'd 
  3569.  otherwise require. 
  3570.  
  3571.  
  3572. ΓòÉΓòÉΓòÉ 5.34. /IncludePath ΓòÉΓòÉΓòÉ
  3573.  
  3574. Switch /IncludePath[:PathList] 
  3575.  
  3576. This is a PPWIZARD command line switch. You can set up your own default 
  3577. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  3578.  
  3579. When ppwizard looks for a file (such as when it encounters a #include command) 
  3580. it searches in certain locations. This switch allows you to specify your own 
  3581. locations which will be searched before ppwizard looks in the standard ones. 
  3582.  
  3583. If you don't supply a parameter ppwizard will forget (drop) any locations you 
  3584. have previously specified otherwise you are supplying a a list of items 
  3585. separated by ";" (or colon for unix). If the item begins with a "*" character 
  3586. then what follows is the name of an environment variable whose contents should 
  3587. be searched otherwise it specifies a directory. 
  3588.  
  3589. It is a common requirement that the current directory be searched first if you 
  3590. need this to be searched before your supplied paths then you need to tell 
  3591. ppwizard this! 
  3592.  
  3593. Example 
  3594.  
  3595.     ppwizard.rex 1.in /IncludePath /IncludePath:.;c:\second;c:\third /IncludePath:c:\fourth
  3596.  
  3597.  
  3598. ΓòÉΓòÉΓòÉ 5.35. /Info ΓòÉΓòÉΓòÉ
  3599.  
  3600. Switch /Info[:YesOrNo] 
  3601.  
  3602. This is a PPWIZARD command line switch. You can set up your own default 
  3603. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  3604.  
  3605. By default important informational messages may be output, these could be 
  3606. considered as similar to a warning but not as severe. They inform you of 
  3607. situations that are unusual but may be perfectly OK in your environment. This 
  3608. switch allows you to turn these messages off. 
  3609.  
  3610. It is recommended that you do not turn them off. 
  3611.  
  3612. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  3613. one of the following values is expected: 
  3614.  
  3615.          Y 
  3616.          N 
  3617.          YES 
  3618.          NO 
  3619.  
  3620.  
  3621. ΓòÉΓòÉΓòÉ 5.36. /List ΓòÉΓòÉΓòÉ
  3622.  
  3623. Switch /List[:ListFileName] 
  3624.  
  3625. This is a PPWIZARD command line switch. You can set up your own default 
  3626. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  3627.  
  3628. This switch allows you to pass a file containing a list of ppwizard switches 
  3629. and/or file masks (possibly produced by a /hook hook) to ppwizard. 
  3630.  
  3631. Inline comments are removed (these begin with ';;'). Blank lines or lines 
  3632. beginning with ';' are ignored. 
  3633.  
  3634. Each line must contain one and only one file mask or ppwizard option. Leading 
  3635. and trailing spaces are removed all others are replaced with '{x20}' as it is 
  3636. assumed they are required. 
  3637.  
  3638. One of the advantages of using a list file to hold options is that you do not 
  3639. have any problems with the operating system's command line processing getting 
  3640. in the way, for example you can use redirection characters such as '>' without 
  3641. problems. 
  3642.  
  3643. Note that ppwizard will automatically read in any file named "ppwizard.ppw" 
  3644. (default project file) using this mechanism. This makes it much simpler to use 
  3645. ppwizard via a graphical interface (such as Window's explorer) while also 
  3646. making it easier to use from the command line. 
  3647.  
  3648. Te list file can of course load other definitions from environment variables or 
  3649. other list or project files if required. 
  3650.  
  3651. The main difference between the "/list" switch and using "@" to indicate a 
  3652. project file is that with the "/list" switch you specify where the file is and 
  3653. with project commands such as "@all" ppwizard will look for a file called 
  3654. "all.ppw" in certain locations (current and ppwizard directories). 
  3655.  
  3656. Example Of LIST File 
  3657.  
  3658. ;-----------------------------------------------------------------------
  3659. ;--- This file builds HTML for all "*.IT" files in current directory ---
  3660. ;-----------------------------------------------------------------------
  3661.  
  3662. *.IT                       ;;Only build files matching this mask
  3663. /DependsOn:DEP\*.DEP       ;;Only rebuild files that need it (new or modified)
  3664. /Output:OUT\*.htm          ;;I like files generated into the "out" directory and with the ".htm" extn
  3665.  
  3666.  
  3667. ΓòÉΓòÉΓòÉ 5.37. /Making ΓòÉΓòÉΓòÉ
  3668.  
  3669. Switch /Making:MakingTextSpec 
  3670.  
  3671. This is a PPWIZARD command line switch. You can set up your own default 
  3672. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  3673.  
  3674. When PPWIZARD is making a file it normally displays text similar to 
  3675. "Making - this.htm", this switch allows you to modify what is displayed. 
  3676.  
  3677. You can specify text for each of the possible processing modes (COPY, HTML, 
  3678. OTHER and REXX). 
  3679.  
  3680. The "MakingTextSpec" parameter is of the format "/Mode/Text" (the text if blank 
  3681. reverts to default). 
  3682.  
  3683. The Text may contain the following special text: 
  3684.  
  3685.          {ID} - Input file directory 
  3686.          {IS} - Short input filename 
  3687.          {IL} - Long input filename (absolute) 
  3688.          {OD} - Output file directory 
  3689.          {OS} - Short output filename 
  3690.          {OL} - Long output filename (may be relative) 
  3691.          {PM} - Processing Mode 
  3692.  
  3693.  Example 
  3694.  
  3695.  The following sets up the "making" text for the rexx processing mode. 
  3696.  
  3697.       ppwizard /making:/REXX/We{x20}are{x20}making{x20}REXX{x20}CODE{x20}-{x20}{OL}
  3698.  
  3699.  This is doing exactly the same thing: 
  3700.  
  3701.       ppwizard ~/making:/REXX/We are making REXX CODE - {OL}~
  3702.  
  3703.  
  3704. ΓòÉΓòÉΓòÉ 5.38. /OnERROR ΓòÉΓòÉΓòÉ
  3705.  
  3706. Switch /OnERROR[:FailedCommandLine] 
  3707.  
  3708. This is a PPWIZARD command line switch. You can set up your own default 
  3709. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  3710.  
  3711. The "FailedCommandLine" if non-blank specifies the command line of a command 
  3712. which is to be executed if ppwizard fails for any reason. 
  3713.  
  3714. A typical use for this would be to display the output in a viewer or editor. 
  3715. This could be very handy if you wish to work in a GUI (graphical) environment 
  3716. such as Windows Explorer or the OS/2 WPS. 
  3717.  
  3718. The /OnOk switch is closely related to this one. 
  3719.  
  3720. Some Command Parameters 
  3721.  
  3722. The command may contain the following strings: 
  3723.  
  3724.          {ConsoleFile} 
  3725.           The name of any console file or "". A console file can be specified 
  3726.           with the /ConsoleFile switch. 
  3727.  
  3728.          {ErrorFile} 
  3729.           The name of any error file or "". An error file can be specified with 
  3730.           the /ErrorFile switch. 
  3731.  
  3732.  Example 
  3733.  
  3734.       set ppwizard_errorfile=out\1.$$E
  3735.       set ppwizard_consolefile=+out\1.$$C
  3736.       regina out\ppwizard.rex 1.in /OnOK:notepad{x20}{ConsoleFile} /OnERROR:notepad{x20}{ErrorFile} /output:out\1.htm /debug  >nul 2>&1
  3737.  
  3738.  
  3739. ΓòÉΓòÉΓòÉ 5.39. /OnOK ΓòÉΓòÉΓòÉ
  3740.  
  3741. Switch /OnOK[:OkCommandLine] 
  3742.  
  3743. This is a PPWIZARD command line switch. You can set up your own default 
  3744. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  3745.  
  3746. The "OkCommandLine" if non-blank specifies the command line of a command which 
  3747. is to be executed if ppwizard successfully completes. 
  3748.  
  3749. A typical use for this would be to display the output in a viewer or editor. 
  3750. This could be very handy if you wish to work in a GUI (graphical) environment 
  3751. such as Windows Explorer or the OS/2 WPS. 
  3752.  
  3753. See the /OnError switch for an example and more information about some 
  3754. parameters you can use. 
  3755.  
  3756.  
  3757. ΓòÉΓòÉΓòÉ 5.40. /Other ΓòÉΓòÉΓòÉ
  3758.  
  3759. Switch /Other 
  3760.  
  3761. This is a PPWIZARD command line switch. You can set up your own default 
  3762. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  3763.  
  3764. This switch indicates that the input is not one of the types specifically 
  3765. supported such as HTML or REXX.  It turns of any funny stuff while in #AsIs 
  3766. Mode. 
  3767.  
  3768. This switch can be used any number of times and will affect all input masks 
  3769. that follow. It also becomes the default mode for all files produced via the 
  3770. #Output command. For backwards compatability, if an input mask is found before 
  3771. any processing mode switch then the last instance of a processing mode switch 
  3772. is used these. 
  3773.  
  3774.  
  3775. ΓòÉΓòÉΓòÉ 5.41. /Option ΓòÉΓòÉΓòÉ
  3776.  
  3777. Switch /Option:OptionParameters 
  3778.  
  3779. This is a PPWIZARD command line switch. You can set up your own default 
  3780. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  3781.  
  3782. The "OptionParameters" is basically anything that is acceptable on the #option 
  3783. command. 
  3784.  
  3785. When PPWIZARD starts it sets up a default value for each option. This switch 
  3786. allows you to modify the value to suit your needs. 
  3787.  
  3788. Warning 
  3789.  
  3790. You may need to be careful about some of the characters used on a command line 
  3791. or when setting an environment variable.  For example from an OS/2 command 
  3792. prompt you can not set an environment variable to a value that contains an 
  3793. equal sign, you would need to use '{x3D}' (it's ASCII code in hexadecimal) 
  3794. instead. 
  3795.  
  3796. Example 
  3797.  
  3798. The following is an extract from a much larger batch file I use: 
  3799.  
  3800.        set DEBUG=/debug /option:debuglevel=/-all/
  3801.        regina.exe ppwizard.rex /option:Warnings="IPFO" PPWIZARD.D %DEBUG% /output:%MAKEHTML%\*.htm
  3802.  
  3803.  
  3804. ΓòÉΓòÉΓòÉ 5.42. /Output ΓòÉΓòÉΓòÉ
  3805.  
  3806. Switch /Output:EditMask 
  3807.  
  3808. This is a PPWIZARD command line switch. You can set up your own default 
  3809. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  3810.  
  3811. This parameter controls how the "InputFile" parameter is transformed to 
  3812. generate the correct name for the generated output file. 
  3813.  
  3814. An edit mask is basically much like a file (with path if required) and will 
  3815. contain zero or one special characters as follows: 
  3816.  
  3817.        1. *.* or {$SHORT} 
  3818.           This gets replaced with the short filename (no path) of the current 
  3819.           input file.
  3820.  
  3821.        2. * or {$BASE} 
  3822.           This gets replaced with the short filename (less path and extension) 
  3823.           of the current input file.
  3824.  
  3825.        3. {$FULL} 
  3826.           This gets replaced with the full filename (with path) of the current 
  3827.           input file.
  3828.  
  3829.        4. ? or {$PATH} 
  3830.           This gets replaced with the path (including terminating slash) of the 
  3831.           current input file. This is most likely to be of use if you want to 
  3832.           position generated files relative to the input file and your mask 
  3833.           scans subdirectories. For example "?OUT\*.HTM".
  3834.  
  3835.        5. {$path} 
  3836.           This allows you to set up a separate tree for generated filenames, 
  3837.           the input mask and file are examined and the relative path extracted, 
  3838.           the result is either blank ('') or a relative path that ends with a 
  3839.           path separator. Note for this to work the input mask must either use 
  3840.           an absolute path, begin with '.' or '..' followed by slash or not 
  3841.           have a path attached at all otherwise ppwizard will abort. It would 
  3842.           be pointless to use this sort of path unless subdirectories are being 
  3843.           scanned. You may wish to investigate the /BaseDir switch.
  3844.  
  3845.  Note that unix type operating systems will probably have problems with "$path" 
  3846.  etc (to unix this means replace with the "path" environment variable's 
  3847.  contents). You need to hide or escape the dollar sign, so use either 
  3848.  "{x24}path" or "\$path" instead.
  3849.  
  3850.  The "EditMask" can be absolute or relative (your exact circumstances will 
  3851.  determine your choice). 
  3852.  
  3853.  Note that resultant relative filenames are always relative to the current 
  3854.  directory. 
  3855.  
  3856.  While you control the case of the mask you can't control the case of the part 
  3857.  that replaces the '*'.  What you can do is ensure the whole name is either in 
  3858.  upper or lower case with the /FileNames switch. 
  3859.  
  3860.  The default mask is "*.htm".  I place all my output into a separate "OUT" 
  3861.  directory and use "/Output:OUT\*.htm" instead. 
  3862.  
  3863.  This switch can be used any number of times and will affect all input masks 
  3864.  that follow. For backwards compatability, if an input mask is found before 
  3865.  this switch then the very last instance of this switch is used for these. 
  3866.  
  3867.  
  3868. ΓòÉΓòÉΓòÉ 5.43. /OutHeader ΓòÉΓòÉΓòÉ
  3869.  
  3870. Switch /OutHeader:Spec 
  3871.  
  3872. This is a PPWIZARD command line switch. You can set up your own default 
  3873. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  3874.  
  3875. For some output extensions or file types PPWIZARD automatically outputs a 
  3876. header at the start of the file. You can turn this off, on, or tweek the output 
  3877. using this switch. 
  3878.  
  3879. The first and last characters of the "Spec" defines the delimiter being used to 
  3880. delimit the following values: 
  3881.  
  3882.        1. Extension 
  3883.           The extension (without a dot) that you are modifying the header for. 
  3884.           Specify this in UPPER case unless the case is significant (as it 
  3885.           would be in Unix). You can also use "*" to apply this rule to all 
  3886.           files that don't have a specific rule. 
  3887.  
  3888.        2. Start of Comment Block 
  3889.           The line that begins the comments. 
  3890.  
  3891.        3. Start of Middle Lines 
  3892.           The characters that begin a line between the start and end lines. 
  3893.  
  3894.        4. End of Comment Block 
  3895.           The line that ends the comments. 
  3896.  
  3897.  Note that if the last 3 values (start/middle/end) are empty or missing then 
  3898.  the comment is turned off. 
  3899.  
  3900.  If the start value starts with '@' and there is no middle or end then this 
  3901.  indicates that a file should be read to create a header. The included header 
  3902.  is basically just like any other included file but I recommend that its only 
  3903.  task be to take care of the header. If your header file included conditional 
  3904.  generation of the header based on the extension of the output file then it 
  3905.  could make sense to use a "*" rule. This allows you to have full control over 
  3906.  the contents of the header. 
  3907.  
  3908.  Examples 
  3909.  
  3910.  The following shows how header comments in files with the extension ".REX" can 
  3911.  be turned off: 
  3912.  
  3913.       /OutHeader:~/REX/~
  3914.  
  3915.  The following shows how header comments in files with the extension ".VBS" can 
  3916.  be specified: 
  3917.  
  3918.       /OutHeader:~$VBS$'{x20}===============$'{x20}$'{x20}===============$~
  3919.  
  3920.  The following shows how a file can be included to produce a custom header (it 
  3921.  can perform any required commands): 
  3922.  
  3923.       /OutHeader:~/VBS/@OutHeader.H/~
  3924.  
  3925.  The following is an example of what the "OutHeader.H" file could look like: 
  3926.  
  3927.       ;--- What is the extension of the output file -------------------------------
  3928.       #NextId
  3929.       #DefineRexx ''
  3930.          ;---- Get extension (if not unix then make upper case) -------------------
  3931.          @@Extn = _filespec('EXTN', '<?OutputFile>');
  3932.          #if ['<?OpSys>' <> 'UNIX']
  3933.              @@Extn = translate(@@Extn);    ;;Make upper case
  3934.          #endif
  3935.  
  3936.          ;---- Want a comment? ---
  3937.          @@Line = copies('+*', 30);
  3938.          select
  3939.              ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3940.              when @@EXTN = "HTM" | @@EXTN = "HTML" then
  3941.              ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3942.              do
  3943.                  ;--- HTML ---
  3944.                  @@WantCmt = 'Y'
  3945.                  @@Start   = '<!--<?NewLine>' || @@Line;
  3946.                  @@End     =  @@Line || '<?NewLine>-->';
  3947.                  @@Line    = ''
  3948.              end;
  3949.              ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3950.              when @@EXTN = "VBS" then
  3951.              ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3952.              do
  3953.                  ;--- VB SCRIPT ---
  3954.                  @@WantCmt = 'Y'
  3955.                  @@Start   = "'" || @@Line;
  3956.                  @@End     =  @@Start;
  3957.                  @@Line    = "'"
  3958.              end;
  3959.              ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3960.              when @@EXTN = "REX" | '<?ProcessingMode>' = 'REXX' then
  3961.              ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3962.              do
  3963.                  ;--- REXX ---
  3964.                  @@WantCmt = 'Y'
  3965.                  @@Start   = '/* ' || @@Line;
  3966.                  @@End     = ' * ' || @@Line || '*/';
  3967.                  @@Line    = ' *'
  3968.              end;
  3969.              ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3970.              otherwise
  3971.              ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3972.                  @@WantCmt = 'N'
  3973.          end
  3974.       #DefineRexx
  3975.  
  3976.  
  3977.       ;--- Exit if we don't want to generate a output header for this EXTN ---
  3978.       #if    [@@WantCmt = 'N']
  3979.              #eof 1
  3980.       #endif
  3981.  
  3982.  
  3983.       ;--- Generate the output comment ---
  3984.       <??@@Start>
  3985.       <??@@Line> Generator   : PPWIZARD version <?Version> under <?OpSysSpecific>
  3986.       <??@@Line>             : FREE tool for Windows, OS/2, DOS and UNIX by <?PpwizardAuthor> (<?PpwizardAuthorEmail>)
  3987.       <??@@Line>             : <?PpwizardHomePage>
  3988.       <??@@Line> Time        : <?CompileTime>
  3989.       <??@@Line> Input File  : <?InputFile>
  3990.       <??@@Line> Output File : <?OutputFile>
  3991.       <??@@End>
  3992.  
  3993.  
  3994. ΓòÉΓòÉΓòÉ 5.44. /Pack ΓòÉΓòÉΓòÉ
  3995.  
  3996. Switch /Pack[:YesOrNo] 
  3997.  
  3998. This is a PPWIZARD command line switch. You can set up your own default 
  3999. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  4000.  
  4001. This switch is only useful if "/rexx" is also specified.  You can get a much 
  4002. smaller generated rexx program by packing (off by default).  Packing does not 
  4003. significantly slow down processing. 
  4004.  
  4005. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  4006. one of the following values is expected: 
  4007.  
  4008.          Y 
  4009.          N 
  4010.          YES 
  4011.          NO 
  4012.  
  4013.  MORE ON PACKING 
  4014.  
  4015.  The preprocessor packs well written code (by my definition!) and can fail to 
  4016.  correctly pack code where strings are appended without the use of the "||" 
  4017.  operator (as the excess spaces will be removed).  For example the following 
  4018.  statement will not create the string you expect when packed: 
  4019.  
  4020.          BothPartsCombined = 'Value:'   TheValue;
  4021.  
  4022.  The following statement is a version of the above that will work: 
  4023.  
  4024.           BothPartsCombined = 'Value:   ' || TheValue;
  4025.  
  4026.  You can get very good results by packing but if you have got legacy code or 
  4027.  you don't wish to change (your evil ways!) you should use the "/Pack:N" 
  4028.  command line switch.  This turns off most packing (rexx comment and trailing 
  4029.  ';' removal still occurs). 
  4030.  
  4031.  If you have trouble with some parts of your code but the bulk packs well then 
  4032.  you may wish to consider leaving packing on and using the AllowPack option to 
  4033.  indicate parts of your rexx code that should not be packed. 
  4034.  
  4035.  WARNING 
  4036.  
  4037.  This has not been tested on object rexx so I don't know if it will work or not 
  4038.  (I assume it will). 
  4039.  
  4040.  
  4041. ΓòÉΓòÉΓòÉ 5.45. /Rexx ΓòÉΓòÉΓòÉ
  4042.  
  4043. Switch /Rexx 
  4044.  
  4045. This is a PPWIZARD command line switch. You can set up your own default 
  4046. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  4047.  
  4048. The input is treated as rexx source.  Rexx comments are removed from the 
  4049. source. 
  4050.  
  4051. This switch can be used any number of times and will affect all input masks 
  4052. that follow. It also becomes the default mode for all files produced via the 
  4053. #Output command. For backwards compatability, if an input mask is found before 
  4054. any processing mode switch then the last instance of a processing mode switch 
  4055. is used these. 
  4056.  
  4057. Packing of the resultant rexx code (within one generated line) occurs by 
  4058. default.  You can specify "/Pack" if you don't want this done.  Turning off 
  4059. packing will speed up the generation of rexx code but in my mind the 
  4060. compression gain from leaving it on is worth it. 
  4061.  
  4062. Other options you may wish to use are "LeaveBlankLines" & "KeepIndent". 
  4063.  
  4064. WARNING 
  4065.  
  4066. Note that if you are taking unknown code and passing it through the 
  4067. preprocessor to reduce its size you should use the "/Pack;N" option as there 
  4068. are situations where the operation of the code will be affected.  Some good and 
  4069. safe reduction in code size will still occur. 
  4070.  
  4071.  
  4072. ΓòÉΓòÉΓòÉ 5.46. /RegSyntax ΓòÉΓòÉΓòÉ
  4073.  
  4074. Switch /RegSyntax 
  4075.  
  4076. This is a PPWIZARD command line switch. You can set up your own default 
  4077. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  4078.  
  4079. This switch only has affect when generating rexx code under OS/2. 
  4080.  
  4081. PPWIZARD always checks the generated code by asking the interpreter you are 
  4082. using to validate it. The OS/2 classic (not sure about OO) rexx interpreter 
  4083. does not do as good a job as regina in detecting syntax errors. 
  4084.  
  4085. By default ppwizard will use the OS/2 version of regina to perform a second 
  4086. syntax check assuming that the first (done by OS/2's rexx) passed it. PPWIZARD 
  4087. will look for a file called "ROS2REXX.EXE" in the same directory as PPWIZARD as 
  4088. well as in the PATH. 
  4089.  
  4090. This switch allows you to either turn off the checking altogether (pass '-') or 
  4091. specify the full name of the rexx interpreter. 
  4092.  
  4093.  
  4094. ΓòÉΓòÉΓòÉ 5.47. /RedirMethod ΓòÉΓòÉΓòÉ
  4095.  
  4096. Switch /RedirMethod:Method 
  4097.  
  4098. This is a PPWIZARD command line switch. You can set up your own default 
  4099. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  4100.  
  4101. This option can be used in the very rare situation that ppwizard does not use 
  4102. the correct format for redirection of standard out and error. This is likely to 
  4103. only occur on unix operating systems. 
  4104.  
  4105. The method should contain one of the following values: 
  4106.  
  4107.          @bash 
  4108.           Redirection is performed as per Windows NT, OS/2 and most unix 
  4109.           shells, that is: 
  4110.      Command > File 2>&1 
  4111.  
  4112.          @csh 
  4113.           Redirection is perform as per 'C' shell and some versions of the bash 
  4114.           shell, that is: 
  4115.      Command >& File 
  4116.  
  4117.          Anything Else 
  4118.           Redirection is performed EXACTLY to your specification, this is a 
  4119.           catch all that probably won't be used. If you do need it please 
  4120.           contact me at "dbareis@labyrinth.net.au" and I will give it a name 
  4121.           and document it. 
  4122.  
  4123.           Basically you supply the string of characters required and any place 
  4124.           where you want the filename replaced you use "{?}". 
  4125.  
  4126.  
  4127. ΓòÉΓòÉΓòÉ 5.48. /SpellAddWord ΓòÉΓòÉΓòÉ
  4128.  
  4129. Switch /SpellAddWord:[-]NameOfAddFile 
  4130.  
  4131. This is a PPWIZARD command line switch. You can set up your own default 
  4132. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  4133.  
  4134. This option can be specified if you have used /SpellCheck (use empty dictionary 
  4135. if required) to enable spell checking. 
  4136.  
  4137. What it allows you to do is indicate which incorrect words should be added to a 
  4138. dictionary file. All words you wish to add are added to the file sorted in 
  4139. order of the number of occurances of this word so that the most frequently used 
  4140. (therefore most important) are first. 
  4141.  
  4142. You would typically manually cut and paste words from the generated file to one 
  4143. of your dictionary files. 
  4144.  
  4145. To automatically add all words to the file preceed the filename with "-". 
  4146.  
  4147.  
  4148. ΓòÉΓòÉΓòÉ 5.49. /SpellCheck ΓòÉΓòÉΓòÉ
  4149.  
  4150. Switch /SpellCheck:NameOfDictionary 
  4151.  
  4152. This is a PPWIZARD command line switch. You can set up your own default 
  4153. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  4154.  
  4155. This option loads a dictionary and turns on spell checking. The switch can be 
  4156. used any number of times to load as many dictionaries as you wish. As an 
  4157. example you might wish to set up "GLOBAL.DIC", "PROJECT.DIC" and "JUNK.DIC". 
  4158.  
  4159. You may need to set up "JUNK.DIC" to hold junk words that are not really valid 
  4160. but get picked up as words during the spell check. In interactive spell 
  4161. checking such as in Microsoft word, these junk words are the annoying ones you 
  4162. keep replying "Ignore All" to! 
  4163.  
  4164. Note that ppwizard ignores the case of words and should work for international 
  4165. languages such as German. 
  4166.  
  4167. The /SpellAddWord will help you update or create dictionaries. 
  4168.  
  4169. A dictionary file must exist and it can be empty. 
  4170.  
  4171. There are large dictionaries available (such as in isspell40.zip on hobbes) 
  4172. however this take too long to load if you are impatient like me. The extra time 
  4173. will be required to load the extra words into memory, once loaded I do not 
  4174. think it will take longer to process your files. 
  4175.  
  4176. Spell checking has 2 basic modes (you can use both together) as follows:, 
  4177.  
  4178.          You can indicate words that you frequently get wrong and ppwizard 
  4179.           will tell you when you use the word. 
  4180.  
  4181.          You can supply a list of "good" words (dictionaries) and ppwizard 
  4182.           will tell you if you use a word which is not in a dictionary. 
  4183.  
  4184.  Dictionaries 
  4185.  
  4186.  All leading whitespace on all lines is ignored as are any blank lines or lines 
  4187.  that begin with ';' (a comment). 
  4188.  
  4189.  There are two types of dictionary entries as follows: 
  4190.  
  4191.        1. A valid word. Each word occurs on its own line. The fact that we have 
  4192.           loaded at least one dictionary word (you are not required to do so) 
  4193.           means that ppwizard will try to validate (spell check) all words. 
  4194.           Note that a "word" can contain any characters and so if required 
  4195.           could be "ASD%^". 
  4196.  
  4197.        2. A '$command' as follows: 
  4198.  
  4199.               $MISTAKE 
  4200.                This command allows you to specify a word that you frequently 
  4201.                get wrong. Ppwizard will tell you if you use this word. The 
  4202.                command takes one or two parameters the first parameter is the 
  4203.                incorrectly spelt word while the second (if passed) is the word 
  4204.                correctly spelt. 
  4205.  
  4206.               $DELIMITERS 
  4207.                If you don't like the default delimiters that ppwizard uses then 
  4208.                you can specify a rexx expression which represents the 
  4209.                delimiters you wish to use. Each character you specify is 
  4210.                converted to a space and is therefore ignored. A warning is 
  4211.                generated if this command is used more than once. 
  4212.  
  4213.  Example of Dictionary 
  4214.  
  4215.       ;--- Add common mistakes ----
  4216.       $mistake seperate
  4217.  
  4218.       ;--- Specify alternate delimiters ----
  4219.       $Delimiters d2c(9) || ',.=:;<>&-%()!/~?#${}[]"'
  4220.  
  4221.       ;--- A few words ----
  4222.       THE
  4223.       CAT
  4224.       DOG
  4225.       computer.
  4226.  
  4227.  
  4228. ΓòÉΓòÉΓòÉ 5.50. /SpellShowAll ΓòÉΓòÉΓòÉ
  4229.  
  4230. Switch /SpellShowAll[:YesOrNo] 
  4231.  
  4232. This is a PPWIZARD command line switch. You can set up your own default 
  4233. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  4234.  
  4235. By default you only see a warning for the first time a word error occurs in 
  4236. each build. This switch allows you to indicate that you would like to see every 
  4237. error. 
  4238.  
  4239. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  4240. one of the following values is expected: 
  4241.  
  4242.          Y 
  4243.          N 
  4244.          YES 
  4245.          NO 
  4246.  
  4247.  
  4248. ΓòÉΓòÉΓòÉ 5.51. /Sleep ΓòÉΓòÉΓòÉ
  4249.  
  4250. Switch /Sleep:SecondsOk[,SecondsError] 
  4251.  
  4252. This is a PPWIZARD command line switch. You can set up your own default 
  4253. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  4254.  
  4255. This option can be used to pause execution for a period of time after PPWIZARD 
  4256. completes processing normally (OK) or abnormally (ERROR). Used with the 
  4257. "/DependsOn" switch in a simple batch file could be used in place of a CRON 
  4258. step to poll for data file changes. 
  4259.  
  4260. If you like the sound of this be sure to also check out the "/Template" switch. 
  4261.  
  4262. By default there is a small delay on error to allow you to see the error in 
  4263. case the ppwizard command is in a larger batch file etc. This delay is removed 
  4264. if /OnError is used (unless this "/sleep" switch has been used). 
  4265.  
  4266.  
  4267. ΓòÉΓòÉΓòÉ 5.52. /Template ΓòÉΓòÉΓòÉ
  4268.  
  4269. Switch /Template:TemplateFile 
  4270.  
  4271. This is a PPWIZARD command line switch. You can set up your own default 
  4272. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  4273.  
  4274. Normally PPWIZARD begins by reading from the input file. This switch modifies 
  4275. this behavior. 
  4276.  
  4277. If you have a set of pages which look alike you can set up a single template 
  4278. file which describes the common attributes (header/footer, look and feel, 
  4279. background colors etc) and many "data" files each of which describes the 
  4280. differences (such as the title and page text). 
  4281.  
  4282. When this switch is used the name of the "data" file is stored in the variable 
  4283. "<?TemplateDataFile>" and the file named on this switch is loaded instead. 
  4284.  
  4285. The template does not automatically load or know of the data file, it is up to 
  4286. you to perform the appropriate action which would usually be to simply include 
  4287. the "data" file using: 
  4288.  
  4289.          #include 
  4290.          #import 
  4291.  
  4292.  Example 
  4293.  
  4294.  A typical template file might begin like: 
  4295.  
  4296.       ;--- Load data file, this template specified on "/template" switch ---
  4297.       #include "<?TemplateDataFile>"
  4298.  
  4299.  
  4300. ΓòÉΓòÉΓòÉ 5.53. /UNC ΓòÉΓòÉΓòÉ
  4301.  
  4302. Switch /UNC[:YesOrNo] 
  4303.  
  4304. This is a PPWIZARD command line switch. You can set up your own default 
  4305. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  4306.  
  4307. PPWIZARD includes some code which is only in place to cover common user errors, 
  4308. this code reduces double path slashes to single. If you use UNC names this will 
  4309. interfere with them. This option allows you to turn off the slash reduction (by 
  4310. passing "Y"). 
  4311.  
  4312. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  4313. one of the following values is expected: 
  4314.  
  4315.          Y 
  4316.          N 
  4317.          YES 
  4318.          NO 
  4319.  
  4320.  
  4321. ΓòÉΓòÉΓòÉ 5.54. /Validate ΓòÉΓòÉΓòÉ
  4322.  
  4323. Switch /Validate:[{RcTest}][!]Command 
  4324.  
  4325. This is a PPWIZARD command line switch. You can set up your own default 
  4326. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  4327.  
  4328. This switch allows you to specify a command which will be executed if the 
  4329. output file is successfully generated. This will frequently be a validation 
  4330. step but ppwizard does not care what you specify on the command line or it's 
  4331. purpose. Another common use would be to use ppwizard as a preprocessor step and 
  4332. then call the program which will use it's output directly. 
  4333.  
  4334. The "#OnExit #EXEC" command can be used to do the same thing from within a 
  4335. header file. 
  4336.  
  4337. The command may contain references to macros or standard definitions. The 
  4338. string "{?}" represents the output file. 
  4339.  
  4340. Normally the command output is hidden and captured if in debug mode. To see the 
  4341. output preceed the command with the '!' character. 
  4342.  
  4343. If "RcTest" is not supplied then the return code is ignored otherwise it is a 
  4344. rexx expression where the rexx variable "CmdRc" holds the commands return code. 
  4345. A boolean result is expected with TRUE meaning the validation was successful. 
  4346.  
  4347. Under Windows 95-ME you probably can't get any decent return codes at all (due 
  4348. to major bugs in it's command processor), but even on Windows NT or 2000 be 
  4349. aware that both within the operating system itself as well as in other 3rd 
  4350. party programs there are a lot of situations where return codes can't be 
  4351. trusted (must be the monkeys fault?). 
  4352.  
  4353. Examples 
  4354.  
  4355.     ppwizard  *.it  /output:out\*.htm /validate:Doit.exe{x20}"{?}"
  4356.     ppwizard  *.it  /output:out\*.htm /validate:{CmdRc=0}MyValidate.exe{x20}/x{x20}"{?}"
  4357.  
  4358. The following example shows ppwizard creating a temporary (or intermediate) 
  4359. file which is used by another program. PPWIZARD has been used to preprocess the 
  4360. file so the second program has the advantage of being able to make use of all 
  4361. ppwizard features such as file inclusion, macros and conditional generation: 
  4362.  
  4363.     %COMSPEC% /c ppwizard.cmd os2setup.db /output:out\os2setup.tmp /validate:{CmdRc=0}wpsobj.exe{x20}MakeObjects{x20}out\os2setup.tmp /debug >out\OS2SETUP.LOG 2>&1
  4364.     if not errorlevel 1 goto CreateOk
  4365.            echo ***
  4366.            echo *** Create of PPWIZARD objects has failed...
  4367.            echo *** Will display "out\OS2SETUP.LOG" (contains details).
  4368.            echo ***
  4369.            pause
  4370.            e.exe out\OS2SETUP.LOG
  4371.            goto EndBatch
  4372.     :CreateOk
  4373.  
  4374.  
  4375. ΓòÉΓòÉΓòÉ 5.55. /WarningsRc ΓòÉΓòÉΓòÉ
  4376.  
  4377. Switch /WarningsRc[:WantedRc] 
  4378.  
  4379. This is a PPWIZARD command line switch. You can set up your own default 
  4380. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  4381.  
  4382. By default when one or more warnings are displayed a return code of 1 will be 
  4383. returned. 
  4384.  
  4385. You can use this switch to set any return code you like (the default is 1). 
  4386.  
  4387. When you supply a value of 0 it indicates that you don't care what warnings 
  4388. were displayed, you do not consider a warning to be an error. 
  4389.  
  4390. You can get more fine tuning with the Warnings option. 
  4391.  
  4392.  
  4393. ΓòÉΓòÉΓòÉ 5.56. /XSlash ΓòÉΓòÉΓòÉ
  4394.  
  4395. Switch /XSlash[:YesOrNo] 
  4396.  
  4397. This is a PPWIZARD command line switch. You can set up your own default 
  4398. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  4399.  
  4400. In any location where ppwizard needs to generate html tags you can control 
  4401. whether or not it generates the "<Tag />" format suitable for XHTML etc when 
  4402. this is required. 
  4403.  
  4404. By default ppwizard does not generate the extra space followed by slash. 
  4405.  
  4406. The output of the "<?/>" macro is dependent on the XSLASH state. 
  4407.  
  4408. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  4409. one of the following values is expected: 
  4410.  
  4411.          Y 
  4412.          N 
  4413.          YES 
  4414.          NO 
  4415.  
  4416.  
  4417. ΓòÉΓòÉΓòÉ 5.57. /**/ ΓòÉΓòÉΓòÉ
  4418.  
  4419. Switch /**/[:YesOrNo] 
  4420.  
  4421. This is a PPWIZARD command line switch. You can set up your own default 
  4422. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  4423.  
  4424. This switch only has affect when /rexx also used to turn on rexx processing. 
  4425. Normally rexx comments on ends of lines are removed.  Use this switch to leave 
  4426. them in.  Normally there would be no need to leave them in however you might 
  4427. choose to do so to aid runtime debugging. 
  4428.  
  4429. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  4430. one of the following values is expected: 
  4431.  
  4432.          Y 
  4433.          N 
  4434.          YES 
  4435.          NO 
  4436.  
  4437.  
  4438. ΓòÉΓòÉΓòÉ 5.58. /#Include ΓòÉΓòÉΓòÉ
  4439.  
  4440. Switch /#INCLUDE:FileList] 
  4441.  
  4442. This is a PPWIZARD command line switch. You can set up your own default 
  4443. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  4444.  
  4445. This switch allows you to specify one or more files which should automatically 
  4446. be included before any other file processing takes place.  To specify more than 
  4447. one they should be separated by a ';' character (or ':' under unix). 
  4448.  
  4449. You could use this if you supply a set of macros in header file and supply a 
  4450. batch file to run the preprocessor.  You would then not have to require (or 
  4451. request) a user of your header to '#include' it themselves. 
  4452.  
  4453. Example 
  4454.  
  4455.     ppwizard  *.it  /output:out\*.htm /CrLf /#Include:Header1.H;Header2.H
  4456.  
  4457.  
  4458. ΓòÉΓòÉΓòÉ 5.59. /$Trace ΓòÉΓòÉΓòÉ
  4459.  
  4460. Switch /$Trace[:YesOrNo] 
  4461.  
  4462. This is a PPWIZARD command line switch. You can set up your own default 
  4463. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  4464.  
  4465. This switch sets the default "$trace" state for all #DefineRexx blocks. 
  4466.  
  4467. When $tracing is used rexx tracing code is inserted before most rexx lines (not 
  4468. statements). This inserted code will display the line of your code that is 
  4469. about to be executed and the current value of any variables that it references 
  4470. (also shows variables referenced by immediately previous statement). 
  4471.  
  4472. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  4473. one of the following values is expected: 
  4474.  
  4475.          Y 
  4476.          N 
  4477.          YES 
  4478.          NO 
  4479.  
  4480.  PPWIZARD REXX TRACING 
  4481.  
  4482.  Please be careful using this feature, a rexx command is generated to support 
  4483.  the tracing so always use do/end blocks when tracing within true or false "if" 
  4484.  blocks etc. To provide an example, the following code will fail!: 
  4485.  
  4486.          if  x = 1 then
  4487.              A = X;
  4488.          else
  4489.              A = 2;
  4490.  
  4491.  To be able to trace this code you will need to change it to: 
  4492.  
  4493.          if  x = 1 then
  4494.          do
  4495.              A = X;
  4496.          end;
  4497.          else
  4498.          do
  4499.              A = 2;
  4500.          end;
  4501.  
  4502.  The addition of tracing code is fairly primative, however the rule is 
  4503.  basically simple, it must be valid and not break your code for a rexx 
  4504.  statement to be inserted between any lines of your code. There are a few 
  4505.  exceptions, ppwizard will not insert code before any lines that are known 
  4506.  "dangerous" ones such as "then", "do" and "else". If you don't wish to follow 
  4507.  the "rules" then do not use any "$trace" facility. You will probably get a 
  4508.  rexx trap (unexpected "do" or similar) if a line is incorrect trapped but I'm 
  4509.  not going to guarantee this... 
  4510.  
  4511.  This type of tracing can be much easier to understand than normal rexx tracing 
  4512.  and also allows you to specify breakpoints (see below). Also unlike OS/2 rexx 
  4513.  tracing, Regina's tracing is almost useless. For these reasons and to reduce 
  4514.  clutter it is suggested that the PPWIZARD macro "REXXTRACE" be set to "OFF". 
  4515.  
  4516.  To make things easier to understand I'd suggest that you use /beep and /color 
  4517.  to turn on beeping on error and color highlighting. 
  4518.  
  4519.  SETTING BREAKPOINTS 
  4520.  
  4521.  You can set a breakpoint so that tracing stops (you are given a rexx debug 
  4522.  command prompt) when the trace output contains specified text. You must not be 
  4523.  redirecting output when a breakpoint expires otherwise you will of course not 
  4524.  be able see anything and ppwizard will be halted (waiting for your replies)! 
  4525.  
  4526.  Before rexx code is executed ppwizard looks to see if the "REXX_BP" macro 
  4527.  exists, if it does then this value is used as an initial breakpoint value. The 
  4528.  value can be one of the following: 
  4529.  
  4530.        1. A value of "?" indicates that you wish to set a breakpoint that 
  4531.           matches all traced lines. 
  4532.  
  4533.        2. A value of "=MacroName" indicates that you wish to call some rexx 
  4534.           code you have defined. It could dump variables and/or indicate that 
  4535.           you wish to stop (bring up a debug command prompt). Rexx variables 
  4536.           that you may wish to use are: 
  4537.  
  4538.               rtStop 
  4539.                Set this variable to "Y" to cause ppwizard to stop (breakpoint 
  4540.                expires). 
  4541.  
  4542.               RtSearchText 
  4543.                This variable contains the text that you can compare with to see 
  4544.                if a breakpoint should expire. You are more likely to look at 
  4545.                the variables directly yourself, if so then please be careful 
  4546.                not to try to display variables that don't exist or your tracing 
  4547.                code will trap (ppwizard will display the error and continue). 
  4548.                You can use the rexx 'symbol()' routine to determine if a 
  4549.                variable exists. 
  4550.  
  4551.        3. Any other value indicates that you wish to break on all lines that 
  4552.           contain the text you provided (case sensitive). You probably 
  4553.           determined a good value by looking at the rexx trace output from a 
  4554.           previous run. 
  4555.  
  4556.           Note that the string "{SOL}" represents the start of a line and 
  4557.           "{EOL}" represents the end of a line. All leading and trailing spaces 
  4558.           have been removed and there is never two or more spaces in a row. 
  4559.  
  4560.  When a breakpoint expires the current line will be displayed, it will not have 
  4561.  been executed and won't be until you press enter at the prompt. 
  4562.  
  4563.  BREAKPOINT COMMAND PROMPT 
  4564.  
  4565.  When a breakpoint expires you will be given a command prompt where you can 
  4566.  type: 
  4567.  
  4568.          Empty Command 
  4569.           If you don't enter any command (that is simply press [enter]), 
  4570.           ppwizard continues until the breakpoint expires again. 
  4571.  
  4572.          ? 
  4573.           In case you have forgotten the step you are up to or it scrolled off 
  4574.           the screen then you can redisplay just the text of the message again 
  4575.           (no variables are dumped). 
  4576.  
  4577.          ?a[liases] 
  4578.           This command shows you all aliases that you have created in the past. 
  4579.  
  4580.          ?#[aliases] 
  4581.           All commands that you type in are automatically remembered. This 
  4582.           command is used to list the commands, to reuse a remembered command 
  4583.           you need to specify it by number (which changes as you enter new 
  4584.           commands - but not as you use previous ones). 
  4585.  
  4586.          ?v[ariables] 
  4587.           This dumps all known variables, for the entire user script. Note that 
  4588.           this won't dump whole arrays, just variables that are easily 
  4589.           recognisable by looking at the rexx code. 
  4590.  
  4591.          /alias 
  4592.           This executes a previously set up command. It's a shorthand way of 
  4593.           specifying frequently used commands. If the alias is numeric or 
  4594.           begins with '#' then this is referring to an automatic alias and not 
  4595.           one that you created. 
  4596.  
  4597.          /alias=value 
  4598.           This allows you to specify a command. Do not use an alias that begins 
  4599.           with '#' or is numeric. 
  4600.  
  4601.          BP 
  4602.           This will prompt you for a new breakpoint. Type "" for none. 
  4603.  
  4604.          None of the Above 
  4605.           You have supplied a rexx command which will be executed. If the 
  4606.           command is "exit" then ppwizard will terminate! PPWIZARD protects you 
  4607.           from syntax errors in this prompt. 
  4608.  
  4609.           You could use this prompt to "say" the values of rexx variables or 
  4610.           anything else you require (run programs or anything else you can 
  4611.           normally do in a rexx program). 
  4612.  
  4613.  Example of use is: 
  4614.  
  4615.       ;--- Define some code that can be called to detect a breakpoint -------
  4616.       #DefineRexx TestBreakpointCode "$TRACE_OFF"
  4617.                   ;--- Simple test (same as simpler REXX_BP value) ----------
  4618.                   if pos('{SOL}x = 2{EOL}', RtSearchText) <> 0 then
  4619.                      rtStop = 'Y';               ;;Want debug prompt!
  4620.  
  4621.                   ;--- Also stop if variable 'FRED' exists and equals '1' ---
  4622.                   if symbol('FRED') = 'VAR' then
  4623.                   do
  4624.                      if  Fred = 1 then
  4625.                          rtStop = 'Y';           ;;Want debug prompt!
  4626.                   end;
  4627.       #DefineRexx
  4628.  
  4629.  
  4630.       ;--- Other possible settings for below --------------------------------------
  4631.       ;#define REXX_BP       {SOL}x = 2{EOL}      ;;Set break point for when x = 2 (whole line ie not "x=22" etc)
  4632.       ;#define REXX_BP       =TestBreakpointCode  ;;Stop where my code says
  4633.       ;#define REXX_BP_ALIAS ;project.a;global.a  ;;Define alias files used (changes NOT saved)
  4634.  
  4635.       ;--- Define rexx code to be debugged (Execute it) ---------------------
  4636.       #define RexxTrace      OFF                  ;;Don't want to see interpreters output
  4637.       #define REXX_BP        ?                    ;;Stop anywhere (first $trace)
  4638.       #define REXX_BP_ALIAS  project.a;global.a   ;;Define alias files used (changes saved to "project.a")
  4639.       #DefineRexx ''
  4640.          Fred = 1;
  4641.          do x = 1 to 3
  4642.             $trace                  ;;trace next command
  4643.             y = x; fred2 = Fred;
  4644.          end;
  4645.  
  4646.          ;--- Dump all vars now ---
  4647.          $trace Finished, dumping all vars
  4648.       #DefineRexx
  4649.  
  4650.  Some sample output (without breakpoint output): 
  4651.  
  4652.       ---------- REXX TRACE - START(OFF) ----------
  4653.       $TRACE: @4 -> y = x; fred2 = Fred
  4654.             |    x = 1
  4655.             | Fred = 1
  4656.       $TRACE: @4 -> y = x; fred2 = Fred
  4657.             |     y = 1
  4658.             |     x = 2
  4659.             | fred2 = 1
  4660.             |  Fred = 1
  4661.       $TRACE: @4 -> y = x; fred2 = Fred
  4662.             |     y = 2
  4663.             |     x = 3
  4664.             | fred2 = 1
  4665.             |  Fred = 1
  4666.         $SAY: Finished,dumping all vars
  4667.             |  Fred = 1
  4668.             |     x = 4
  4669.             |     y = 3
  4670.             | fred2 = 1
  4671.       ---------- REXX TRACE - END(OFF) ----------
  4672.  
  4673.  COMMAND PROMPT ALIASES 
  4674.  
  4675.  If ppwizard finds the "REXX_BP" macro then it also looks for the 
  4676.  "REXX_BP_ALIAS" macro. The value of this macro is a list of alias files 
  4677.  separated by semicolons. 
  4678.  
  4679.  You as a user are allowed to create your own aliases from the command prompt, 
  4680.  these are saved to the first file in the list, if you don't wish to allow 
  4681.  saving then begin the list with a semicolon. 
  4682.  
  4683.  All blank lines and lines that begin with ';' are ignored, otherwise the line 
  4684.  contains a set alias command of the same format that you use on the command 
  4685.  prompt, that is "/alias=value". 
  4686.  
  4687.  Alias names can contain virtually any characters and if duplicated all but the 
  4688.  first is ignored when read from a file. An alias specified on the command 
  4689.  prompt overwrites any stored. 
  4690.  
  4691.  If you do a lot of ppwizard rexx debugging you will probably want to set up at 
  4692.  least project and global level aliases for frequently used commands. 
  4693.  
  4694.  Note that there is no editing of alias commands at the command prompt, if you 
  4695.  make a mistake you will need to either recreate the alias or modify the saved 
  4696.  file when debugging complete. 
  4697.  
  4698.  AUTOMATIC ALIASES 
  4699.  
  4700.  These aliases are created automatically as you enter new commands. Only 
  4701.  successful commands that did not trap are remembered. This facility allows you 
  4702.  to refer to previously entered long commands with a short simple number. As 
  4703.  you will see below it will also allow you to give "good" commands a decent 
  4704.  name at the end of a debug session. 
  4705.  
  4706.  As these aliases are also saved along with normal aliases you can edit the 
  4707.  alias file after a debug session to give what you believe will be handly 
  4708.  common commands "decent" names. When an alias file is read in the auto alias 
  4709.  number is completely ignored so you don't have to worry about creating "holes" 
  4710.  etc. <p>You can control how many commands ppwizard remembers with the 
  4711.  "REXX_BP_MAX_AUTO_CMD" macro. This macro should specify the number of 
  4712.  commands, if it contains an invalid value or does not exist it will default. 
  4713.  
  4714.  
  4715. ΓòÉΓòÉΓòÉ 5.60. /@EXTN ΓòÉΓòÉΓòÉ
  4716.  
  4717. Switch /@EXTN[:ProjectFileMask] 
  4718.  
  4719. This is a PPWIZARD command line switch. You can set up your own default 
  4720. switches in the "PPWIZARD_OPTIONS" environment variable or in project files. 
  4721.  
  4722. After processing all other command line parameters (from all sources) ppwizard 
  4723. checks to see if all input files have the same extension, if so then it will 
  4724. also try to load a project file named "DEF_*.PPW" (the default mask), where the 
  4725. '*' represents the extension of the files. 
  4726.  
  4727. You can either turn off all extension based project handling by passing an 
  4728. empty value or change the name of the files. 
  4729.  
  4730. There is only one restriction, the project file can not try to specify more 
  4731. input files. 
  4732.  
  4733.  
  4734. ΓòÉΓòÉΓòÉ 6. The Source Code ΓòÉΓòÉΓòÉ
  4735.  
  4736. The Source Code 
  4737.  
  4738.        1. There is no limit to how long a line may be, so the only practical 
  4739.           limit will be whatever your editor or other tools impose. 
  4740.  
  4741.           You will wish to also check out the following extra details: 
  4742.  
  4743.               White Space 
  4744.               Commenting 
  4745.               Line Continuation 
  4746.               Quoted Text - qTextq 
  4747.               Quoted Text - qRestq 
  4748.               Dependancies 
  4749.  
  4750.        2. There is a range of "Standard Definitions" available for use in your 
  4751.           source.  You can create your own as well (for example a formatted 
  4752.           date/time of your document). 
  4753.  
  4754.        3. You can selectively include or exclude portions of the source code 
  4755.           using the "#if" command. 
  4756.  
  4757.        4. Large portions of text (with or without HTML tagging) that you place 
  4758.           in multiple places which you feel must be kept in sync can be defined 
  4759.           once with "#define" and referenced many times. 
  4760.  
  4761.        5. If you wish to use PPWIZARD and a WYSIWYG (GUI) Editor and the editor 
  4762.           cracks up at the PPWIZARD tags and commands you can used the /HideCmd 
  4763.           switch to effectively hide ppwizard related stuff in html comments. 
  4764.  
  4765.  
  4766. ΓòÉΓòÉΓòÉ 6.1. White Space ΓòÉΓòÉΓòÉ
  4767.  
  4768. White Space 
  4769.  
  4770. By default, leading whitespace is ignored.  You can use the "KeepIndent" to 
  4771. alter this. Even when not ignored all PPWIZARD commands may be indented from 
  4772. the left if you wish. 
  4773.  
  4774. Trailing whitespace is always removed from a line.  If you must have trailing 
  4775. whitespace you could specify one or more "<?Space>" codes. 
  4776.  
  4777. By default blank lines (after comment removal) are ignored. You can use the 
  4778. "LeaveBlankLines" option to alter this. 
  4779.  
  4780.  
  4781. ΓòÉΓòÉΓòÉ 6.2. Commenting ΓòÉΓòÉΓòÉ
  4782.  
  4783. Line Comments 
  4784.  
  4785. By default the commenting character is ';'. If a line begins with this 
  4786. character then it is ignored. If the line contains the character doubled up (as 
  4787. in ;;) then everything after the last occurance of this string is considered to 
  4788. be an inline comment and is removed. 
  4789.  
  4790. The line comment character can be modified with the LineComment option.  You 
  4791. could add ';;' to the end of a line so that an earlier occurance and everything 
  4792. following does not get removed.  You can also use the "<?SemiColon>" code if 
  4793. required. 
  4794.  
  4795. Note that if the line being dropped is in the middle of a set of continued 
  4796. lines then the line continuation characters at the end (or not at the end) of 
  4797. the dropped line are not ignored. 
  4798.  
  4799. Commenting Blocks of Lines 
  4800.  
  4801. The easiest way to comment out multiple lines at one time is to use the 
  4802. "#ifdef" command to check for a name that you will ensure never exists, such as 
  4803. in the following example: 
  4804.  
  4805.     ;--- This is a line comment ---
  4806.     #define Highlight <B>{$Text}</B>   ;;Comment here
  4807.  
  4808.     #ifdef xxxx
  4809.     1st line commented out
  4810.     2nd line commented out
  4811.     3rd line commented out
  4812.     #endif
  4813.  
  4814.  
  4815. ΓòÉΓòÉΓòÉ 6.3. Line Continuation ΓòÉΓòÉΓòÉ
  4816.  
  4817. Line Continuation 
  4818.  
  4819. PPWIZARD can handle any length line (subject to any REXX interpreter 
  4820. limitations), however the editor you are using may have limitations or you just 
  4821. might want to format the line better. PPWIZARD allows you to specify that a 
  4822. line continues onto the next line. The two or more lines will be merged 
  4823. together. 
  4824.  
  4825. You can continue long lines by placing the line continuation characters (' \' 
  4826. by default) at the end of a line that continues onto the next. 
  4827.  
  4828. The #( command provides an alternative to the use of the line continuation 
  4829. characters and the #DefineRexx command provides a simpler way of formatting 
  4830. REXX code. 
  4831.  
  4832. It is not valid for the last line of a file to contain the line continuation 
  4833. characters, all combined lines must come from the one input file. 
  4834.  
  4835. This capability would be most useful for #define commands. 
  4836.  
  4837. The "LineContinuation" option can be used to disable line continuation or to 
  4838. change the continuation character. 
  4839.  
  4840. When you have a long #define statement that spans lines you can have any 
  4841. commands (such as #if, #elseif and #endif) within a continue block, however 
  4842. these commands themselves NEVER continue on following lines. 
  4843.  
  4844. While line continuation is taking place blank or comment lines are treated no 
  4845. differently from any other lines (that is they are not completely ignored as 
  4846. would normally be the case). If a comment line is found while collecting 
  4847. continued lines it must contain line continuation characters if the 
  4848. continuation is to continue. 
  4849.  
  4850. There are actually a number of line continuation types which make for an easier 
  4851. to read shorthand for other variations. All valid variations are listed below: 
  4852.  
  4853.        1. -\ 
  4854.           All trailing whitespace is removed from this line before the next 
  4855.           line is added. 
  4856.  
  4857.        2. +\ 
  4858.           All trailing whitespace is removed from this line before a space and 
  4859.           then the next line is added. 
  4860.  
  4861.        3. \ (space + slash) 
  4862.           All trailing whitespace is removed from this line before a single 
  4863.           space and the next line is added. 
  4864.  
  4865.        4. %\ 
  4866.           All trailing whitespace is removed from this line before a newline 
  4867.           code and the next line is added. 
  4868.  
  4869.  If the line does not end in one of the above 2 character codes then the 
  4870.  continuation character is ignored.  Note that '+\' and ' \' currently serve 
  4871.  the same purpose, in a future release you will probably be able to set the 
  4872.  default continuation type for ' \'. 
  4873.  
  4874.  Note that line continuation does not occur when the #AsIs "ON" is used. 
  4875.  
  4876.  Example of #if Use Within Line Continuation 
  4877.  
  4878.       #define TheSame                                      \
  4879.               <P>Hi, my name is Dennis Bareis and I have   \
  4880.                  been using OS/2 and developing for        \
  4881.               #if '<$AtWork>' = 'Y'                        \
  4882.                  ANZ                                       \
  4883.               #elseif                                      \
  4884.                  *WRONG INC*                               \
  4885.               #endif                                       \
  4886.               on and off since the original 1.0 version.
  4887.  
  4888.  The above shows the creation of a multi-line macro. It is recommended (and in 
  4889.  some cases required) that the definition be formatted as above, that is the 
  4890.  line is continued by '\' after the macro name. All other line continuation can 
  4891.  be as per your requirements (the above is simple but not ideal...). 
  4892.  
  4893.  Example - Good Formatting, Macro Use 
  4894.  
  4895.       <$MyMacro                         \
  4896.                  Parm1=^a parameter^    \
  4897.                  Parm2=^a parameter^    \
  4898.                  Parm3=^a parameter^    \
  4899.       >
  4900.  
  4901.  
  4902. ΓòÉΓòÉΓòÉ 6.4. Quoted Text - qTextq ΓòÉΓòÉΓòÉ
  4903.  
  4904. Quoted Text - qTextq 
  4905.  
  4906. Many commands require quoted text. The only thing special about the quotes in 
  4907. this program are that they can be almost any character (anything 
  4908. non-alphanumeric). Tthe only restrictions are as follows: 
  4909.  
  4910.        1. The same quote character must appear at the start and end of the 
  4911.           text. 
  4912.        2. If another parameter follows then there must be at least one space 
  4913.           after the end quote character. 
  4914.        3. You can omit the quote characters if the first character is 
  4915.           alphanumeric and the the text does not contain spaces. 
  4916.  
  4917.  The rexx function GetQuotedText() can be used in your own code to read quotes 
  4918.  values such as this. 
  4919.  
  4920.  EXAMPLES 
  4921.  
  4922.  The following are examples of valid quoted strings: 
  4923.  
  4924.          "A string" 
  4925.          'Another string' 
  4926.          ^A 'string' which contains "quotes"^ 
  4927.          ΓûêABCΓûê 
  4928.          NoQuotesRequired 
  4929.  
  4930.  
  4931. ΓòÉΓòÉΓòÉ 6.5. Quoted Text - qRestq ΓòÉΓòÉΓòÉ
  4932.  
  4933. Quoted Text - qRestq 
  4934.  
  4935. Many commands require quoted text, this format of quoted text is only ever used 
  4936. for the last parameter of some commands. 
  4937.  
  4938. This is very similar in function to the "Quoted Text - qTextq" method except 
  4939. that no more parameters are expected after the current one.  All "Quoted Text - 
  4940. qTextq" examples are valid. 
  4941.  
  4942. Everything is the same as for "Quoted Text - qTextq" except: 
  4943.  
  4944.        1. The quote character can actually appear within the quoted text. 
  4945.        2. If the value is unquoted the rest of the line (stripped of leading & 
  4946.           trailing whitespace) is used. 
  4947.        3. Nothing follows the text. 
  4948.  
  4949.  The rexx function GetQuotedRest() can be used in your own code to read quotes 
  4950.  values such as this. 
  4951.  
  4952.  EXAMPLES 
  4953.  
  4954.  The following are examples of valid quoted strings: 
  4955.  
  4956.          ^A 'string' which contains "quotes"^ 
  4957.          "A string with "imbedded" double quotes" 
  4958.  
  4959.  
  4960. ΓòÉΓòÉΓòÉ 7. Macros ΓòÉΓòÉΓòÉ
  4961.  
  4962. Macros 
  4963.  
  4964. The "#include" command allows you to include external files (whole or selected 
  4965. fragments) so this would have to be the simplest and common way of obtaining 
  4966. code reuse and this is where facilities such as SSI (Server Side Includes) 
  4967. stop. PPWIZARD can do much more than this. 
  4968.  
  4969. Macros are collections of text and/or commands and would have to be one of the 
  4970. most important and most used features of this preprocessor. 
  4971.  
  4972. The most common ways of creating macros are with these methods: 
  4973.  
  4974.        1. #define[+] 
  4975.        2. #evaluate[+] 
  4976.        3. /define 
  4977.  
  4978.  The simplest types of macro simply allows you to define text which you will 
  4979.  use over and over again. You will want to specify it in one place so that if 
  4980.  it ever changes you won't need to hunt up all occurances. The following 
  4981.  example shows an email address being defined (this would normally be done in a 
  4982.  central place and be accessed with #include): 
  4983.  
  4984.       #define MyEmailAddress           dbareis@labyrinth.net.au
  4985.  
  4986.  Now that we have defined the email address (once as per example above), in all 
  4987.  the html pages that required it we could refer to it like: 
  4988.  
  4989.       <P>If you have any questions or suggestions for improvements please feel free to
  4990.       <A HREF="mailto:<$MyEmailAddress>">email me</A>.
  4991.  
  4992.  There are also a number of "Standard Macros" which always exist, these allow 
  4993.  you to easily obtain information about the current time or files being 
  4994.  generated or included. All sorts of useful information is available in 
  4995.  standard formats, if you don't like the format of a particular item such as 
  4996.  the "compile time" then it is a simple matter to use ppwizard to create your 
  4997.  own format. There are some specialised forms of standard variables as follows: 
  4998.  
  4999.        1. <?xXX> 
  5000.        2. <??RexxVariable> 
  5001.  
  5002.  All normal macros are replaced before standard macros. The "<?xXX>" form is 
  5003.  never replaced until just before the line is to be written to the output file. 
  5004.  
  5005.  A macro's name (or parameter) can be very long and can contain nearly any 
  5006.  character (space and end of macro replacement character are the main 
  5007.  exceptions). You will be told if a macro name is invalid when you try to 
  5008.  define it. The maximum length of a macro will be approximately 100 characters 
  5009.  in OS/2 rexx and unlimited with the regina interpreter. 
  5010.  
  5011.  The name of a macro (and it's parameters) are normally case insensitive, 
  5012.  however you can make them case sensitive by using the CsReplacement option. 
  5013.  When this option is not used all macros and parameters are converted to upper 
  5014.  case. 
  5015.  
  5016.  You now know enough to get started with simple macros which when used along 
  5017.  with the "#include" command are powerful facilities for reuse, not only can 
  5018.  you reuse all or parts of a file but you can define extremely small items 
  5019.  which are too small to put into files of their own (such as  email or web 
  5020.  addresses). 
  5021.  
  5022.  I recommend that you go on and at least the simplest macros section of the 
  5023.  doco. After becoming familiar with ppwizard and it's basic features I 
  5024.  recommend that all of the advanced sections listed below be read, while it can 
  5025.  be a hard slog, understanding these sections can greatly improve the quality 
  5026.  of what you can do. 
  5027.  
  5028.  Some more advanced topics follow: 
  5029.  
  5030.        1. Multi Line Macros 
  5031.        2. Macros With Mandatory Parameters 
  5032.        3. Macros With Optional Parameters 
  5033.        4. Macro Parameters without values 
  5034.        5. Positional Parameters (not named) 
  5035.  
  5036.  Even more advanced topics: 
  5037.  
  5038.        1. Using Standard Definitions + Using REXX Logic 
  5039.        2. Multi Line Macros With Logic 
  5040.        3. Die When Unused Parms 
  5041.        4. Expand All Unused Parameters 
  5042.        5. Expand All Parameters As Rexx Code 
  5043.        6. Expand Macro Name 
  5044.        7. $$ Transformation Commands 
  5045.  
  5046.  
  5047. ΓòÉΓòÉΓòÉ 7.1. Simplest Macros ΓòÉΓòÉΓòÉ
  5048.  
  5049. Simplest Macros 
  5050.  
  5051. The subject of macros is reasonably complex (but well worth learning) please 
  5052. ensure you have at least read the macro introduction before reading this 
  5053. section. 
  5054.  
  5055. The simplest macros don't contain any logic (just text) and are used where 
  5056. there are many places where you wish the same information used.  For example 
  5057. you might have an email address which you will refer to from 10 different HTML 
  5058. pages.  If this email address changes you do not wish to look for and then 
  5059. change all of these occurrances.  Not only would this be a real pain but you 
  5060. could miss one or get the new email address wrong on one (which you might never 
  5061. realise). 
  5062.  
  5063. You have probably got more than one macro you wish to define (others might be 
  5064. web addresses for external links), it is suggested that in general the best 
  5065. place to keep all of them is together in one place.  You could add all the 
  5066. macro definitions in one place in a file you create called "MACROS.IH". For 
  5067. example the contents of this file might be: 
  5068.  
  5069.     ;--- MY EMAIL Information ---------------------------------------------------
  5070.     #define MyEmailAddress           db0@anz.com
  5071.     #define EmailMeGraphic           <img src="graphics/email.jpg" border=0 width=28 height=19>
  5072.  
  5073.     ;--- Standard Graphics ------------------------------------------------------
  5074.     #define ImgUpdated               <IMG SRC="graphics/updated1.gif" HSPACE=10 ALIGN=middle BORDER=0 WIDTH=52 HEIGHT=12 ALT="updated">
  5075.     #define ImgNew                   <IMG SRC="graphics/new.gif"      HSPACE=10 ALIGN=middle BORDER=0 WIDTH=35 HEIGHT=20 ALT="new">
  5076.     #define ImgBarbedWire            <P><CENTER><IMG SRC="graphics/barbwire.gif"></CENTER>
  5077.  
  5078.     ;--- External WEB Addresses -------------------------------------------------
  5079.     #define HttpNetLabsMainPage      www.netlabs.org
  5080.     #define HttpNetLabsGimpPage      www.netlabs.org/gimp/
  5081.     #define HttpOs2WarpGuruMainPage  www.geocities.com/SiliconValley/Pines/7885/
  5082.     #define HttpOs2WarpGuruApmPage   <$HttpOs2WarpGuruMainPage>DownloadAPM2.html
  5083.  
  5084. At or near the start of the source for the html page (lets call it "Intro.IT") 
  5085. you would add the following statement to load the macros: 
  5086.  
  5087.     ;--- Load all required definitions ------------------------------------------
  5088.     #include "MACROS.IH"
  5089.  
  5090. Later on in "INTRO.IT" you could have the following: 
  5091.  
  5092.     <P>If you have any questions or suggestions for improvements please feel free to
  5093.     <A HREF="mailto:<$MyEmailAddress>">email me</A>.
  5094.  
  5095. As you may guess from the above example to refer to the macro you place '<$' at 
  5096. the start and '>' at the end of the macro (variables) name.  There is now only 
  5097. one place to change if your email address changes.  Not only that but if you 
  5098. get the new address wrong it should be immediately apparent as it will be wrong 
  5099. in all locations!  So not only have you simplified the process but you have 
  5100. probably improved the quality of your output as well! 
  5101.  
  5102. There are better ways to handle what was demonstrated above but hopefully the 
  5103. example was a simple enough starting point. If you are still confused I suggest 
  5104. that you read the e-Zine! articles written by Chris Wenham (the Senior Editor 
  5105. of OS/2 e-Zine! chris@os2ezine.com). 
  5106.  
  5107.  
  5108. ΓòÉΓòÉΓòÉ 7.2. Multi Line Macros ΓòÉΓòÉΓòÉ
  5109.  
  5110. Multi Line Macros 
  5111.  
  5112. The subject of macros is reasonably complex (but well worth learning) please 
  5113. ensure you have at least read the macro introduction before reading this 
  5114. section. 
  5115.  
  5116. Sometimes a macro contains quite a bit of text and to make it easier you might 
  5117. wish to spread the definition over a number of lines. This will also allow you 
  5118. to add comments and spacing to allow it to be easy to read. 
  5119.  
  5120. When PPWIZARD sees a multi line macro (formatted in a similar manner to the 
  5121. example below - break after macro name) it breaks it up into multiple lines so 
  5122. that any imbedded PPWIZARD commands will get executed. 
  5123.  
  5124. You need to be careful to correctly begin a multiline macro, the first line 
  5125. must be of the form: 
  5126.  
  5127.     #define TheMacroName  \
  5128.  
  5129. The following is an example of an invalid definition (as it does not ensure a 
  5130. space follows the "TheMacroName" parameter as is required by the #define 
  5131. command). : 
  5132.  
  5133.     #define TheMacroName  -\
  5134.  
  5135. Also check out the #( command as it is also very useful for creating multiline 
  5136. macros. To define blocks of rexx code use the #DefineRexx command. 
  5137.  
  5138. Note that for ppwizard commands (within a #define) to be executed when the 
  5139. macro is expanded the commands must be on their own line. 
  5140.  
  5141.     ;--- Define the macro -------------------------------------
  5142.     #define FeedBackParagraphs                                        \
  5143.             ;---- First paragraph -----------------------------       \
  5144.             <P>I have put a lot of work into this produce and         \
  5145.                believe it to be of a very high standard.  I           \
  5146.                always appreciate feedback which indicates which       \
  5147.                features you use and like and which you don't          \
  5148.                like.                                                  \
  5149.                                                                       \
  5150.             ;---- Second paragraph ----------------------------       \
  5151.             <P>Please <A HREF="mailto:<$MyEmailAddress>">email me</A> \
  5152.                with tour comments.
  5153.  
  5154.     ;--- Use the macro ----------------------------------------
  5155.     <$FeedBackParagraphs>
  5156.  
  5157. Notice that the expanded "<$FeedBackParagraphs>" will refer to our previously 
  5158. defined "MyEmailAddress" macro.  It is perfectly legal for a macro definition 
  5159. to refer to any number of other definitions. 
  5160.  
  5161.  
  5162. ΓòÉΓòÉΓòÉ 7.3. Macros With Mandatory Parameters ΓòÉΓòÉΓòÉ
  5163.  
  5164. Macros With Mandatory Parameters 
  5165.  
  5166. The subject of macros is reasonably complex (but well worth learning) please 
  5167. ensure you have at least read the macro introduction before reading this 
  5168. section. 
  5169.  
  5170. Back to my previously defined email macro, whenever I use it I still have to 
  5171. duplicate a lot of HTML tagging. What we could do is create an email macro 
  5172. which accepts the text or graphic that the user would click to email me, as 
  5173. below: 
  5174.  
  5175.     #define EmailMeLink  <A HREF="mailto:db0@anz.com">{$VISIBLE}</A>
  5176.  
  5177. The above macro accepts a single parameter which must be supplied when the 
  5178. macro is used.  The parameter's name is "VISIBLE".  The macro refers to a 
  5179. parameter by placing '{$' at the start and '}' at the end of the macro 
  5180. parameters name.  To use this macro we could say: 
  5181.  
  5182.     <P>If you have any questions or suggestions for improvements please feel free to
  5183.     <$EmailMeLink VISIBLE="email me">.
  5184.  
  5185. Note that when you supply the value for a macros parameter you can use 
  5186. virtually any character as a quote not just single or double quotes, for 
  5187. example you could say: 
  5188.  
  5189.     <P>If you have any questions or suggestions for improvements please feel free to
  5190.     <$EmailMeLink VISIBLE=@email me@>.
  5191.  
  5192.  
  5193. ΓòÉΓòÉΓòÉ 7.4. Macros With Optional Parameters ΓòÉΓòÉΓòÉ
  5194.  
  5195. Macros With Optional Parameters 
  5196.  
  5197. The subject of macros is reasonably complex (but well worth learning) please 
  5198. ensure you have at least read the macro introduction before reading this 
  5199. section. 
  5200.  
  5201. Also note that you can create a macro which accepts optional parameters.  The 
  5202. "VISIBLE" parameter we have been using up to now is manditory (required), if 
  5203. not supplied the preprocessor will inform you of this fact and stop.  To make a 
  5204. parameter optional you assign at least the first occurance of the parameter a 
  5205. default value.  You can give each occurance a default value (which may be 
  5206. different), and the last specified default value is remembered for subsequent 
  5207. occurances where a default value is required but not specified. For example to 
  5208. change the email macro to use my email address as the default but allow the 
  5209. specification of alternative addresses I could do the following: 
  5210.  
  5211.     #define EmailMeLink  <A HREF="mailto:{$EMAIL='db0@anz.com'}">{$VISIBLE}</A>
  5212.  
  5213. You could then say: 
  5214.  
  5215.     <P>If you have any questions or suggestions for improvements please feel free to
  5216.     <$EmailMeLink VISIBLE=@email me@>, I have another
  5217.     <$EmailMeLink VISIBLE=@email address@ EMAIL=$db1@anz.com$> which
  5218.     you might like to try.
  5219.  
  5220. Advanced Example 
  5221.  
  5222. This example is demonstrating a bit more than just optional parameters as it is 
  5223. a good example on how you can to some degree simulate rexx like arrays or stem 
  5224. variables: 
  5225.  
  5226.     ;--- Define some constants (make names likely to be unique) ---
  5227.     #define    OPENIT_OPENMODE_TEXT     'T'
  5228.     #define    OPENIT_OPENMODE_BINARY   'B'
  5229.  
  5230.     ;--- Allow user to specify "short" open mode! -----------------
  5231.     #define    OpenIt   \
  5232.                Open({$File}, <$OPENIT_OPENMODE_{$Mode=^TEXT^}>)     ;;Call to fictional open routine
  5233.  
  5234.     ;--- Test the macro -------------------------------------------
  5235.     OpenRc = <$OpenIt File="tfile">
  5236.     OpenRc = <$OpenIt File="bfile" MODE="BINARY">
  5237.  
  5238. What the above demonstrated was a simple way of defining long names for 
  5239. constants with liitle or no chance of clashing with other variable names 
  5240. (possibly outside your control) but allowing the user to specify shorter more 
  5241. friendly aliases ("BINARY" instead of "OPENIT_OPENMODE_BINARY"). 
  5242.  
  5243.  
  5244. ΓòÉΓòÉΓòÉ 7.5. Macro Parameters without values ΓòÉΓòÉΓòÉ
  5245.  
  5246. Macro Parameters without values 
  5247.  
  5248. The subject of macros is reasonably complex (but well worth learning) please 
  5249. ensure you have at least read the macro introduction before reading this 
  5250. section. 
  5251.  
  5252. A macro reference would normally specify values for all parameters it uses, 
  5253. however there are times when this is not required. PPWIZARD does not require 
  5254. you to set a value, if you don't supply one then the name of the parameter in 
  5255. upper case is used. 
  5256.  
  5257. The definition of the macro would supply a default value in case the parameter 
  5258. (keyword) was not used and would normally do some conditional generation (using 
  5259. #if etc). 
  5260.  
  5261. The following example shows a simple macro with very little validation that 
  5262. simply assumes if the "keyword" "start" was not supplied that the "end" 
  5263. condition is required: 
  5264.  
  5265.     ;--- Define the macro ---
  5266.     #define StupidMacro                 \
  5267.             #if '{$START=""}' = 'START' \
  5268.                 start stuff             \
  5269.             #elseif                     \
  5270.                 end stuff               \
  5271.             #endif
  5272.  
  5273.     ;--- Use the macro ---
  5274.     <$StupidMacro start>   ;;Start
  5275.        stuff
  5276.     <$StupidMacro>         ;;End
  5277.  
  5278.  
  5279. ΓòÉΓòÉΓòÉ 7.6. Positional Parameters (not named) ΓòÉΓòÉΓòÉ
  5280.  
  5281. Positional Parameters (not named) 
  5282.  
  5283. The subject of macros is reasonably complex (but well worth learning) please 
  5284. ensure you have at least read the macro introduction before reading this 
  5285. section. 
  5286.  
  5287. In some cases (especially with simple one parameter macros) you may simply wish 
  5288. to supply a value without bothering to name it. For example one way to 
  5289. implement a HTML comment might be: 
  5290.  
  5291.        ;--- Define a macro (takes a parameter called "Text") ----
  5292.        #define COMMENT <!-- {$Text} -->
  5293.  
  5294.  
  5295.        ;--- Use the above macro ---
  5296.        <$COMMENT Text="This will become a html comment">
  5297.  
  5298. As you can see from the above we had to use "Text=" even though that is all the 
  5299. parameter could be (at least correctly), lets do this again but this time using 
  5300. a positional parameter: 
  5301.  
  5302.        ;--- Define a macro (takes a single positional parameter) ----
  5303.        #define COMMENT <!-- {$#1} -->
  5304.  
  5305.  
  5306.        ;--- Use the above macro ---
  5307.        <$COMMENT "This will become a html comment">
  5308.  
  5309. Now the rules are that positional parameters must start with a double quote (as 
  5310. demonstrated above), a single quote or an equal sign. If unquoted the value is 
  5311. assumed to be a Parameters without a value. 
  5312.  
  5313. The macro contents refers to the parameters as a '#' followed by a decimal 
  5314. number which indicates it's position (there can be any number of positional 
  5315. parameters). 
  5316.  
  5317. The reason for the equal sign is that it allows you to quote a string with any 
  5318. quote character (otherwise you wouldn't bother). As an example the above 
  5319. "COMMENT" macro could be called as follows: 
  5320.  
  5321.        ;--- Use the above macro ---
  5322.        <$COMMENT  "Using double quotes">
  5323.        <$COMMENT  'Using single quotes'>
  5324.        <$COMMENT =@Using any    quotes (can then include '" <-- single and double quotes)@>
  5325.  
  5326.  
  5327. ΓòÉΓòÉΓòÉ 7.7. Using Standard Definitions + Using REXX Logic ΓòÉΓòÉΓòÉ
  5328.  
  5329. Using Standard Definitions + Using REXX Logic 
  5330.  
  5331. The subject of macros is reasonably complex (but well worth learning) please 
  5332. ensure you have at least read the macro introduction before reading this 
  5333. section. 
  5334.  
  5335. The following example uses the "#evaluate" command and the "Standard 
  5336. Definition" of "<?OutputFile>" as well as demonstrating the use of using rexx 
  5337. code to include logic. 
  5338.  
  5339.     ;--- Capture some HTML information ------------------------------------------
  5340.     #evaluate ShortNameHtml            "_filespec('name', '<?OutputFile>')"
  5341.     #evaluate ShortNameHtmlLowerCase   "ToLowerCase('<$ShortNameHtml>')"
  5342.  
  5343. The above defined two macros, the first is the short name of the output file 
  5344. (no path or drive attached) and the second is the same short name but all lower 
  5345. case. 
  5346.  
  5347. A "Problem" 
  5348.  
  5349. Notice that the first parameter to the rexx translate function above is 
  5350. surrounded by single quotes, we could safely do this only because we know that 
  5351. a filename can't contain single quotes!  You need to be careful with your use 
  5352. of quotes etc as the macro replacement simply places the correct text where 
  5353. requested.  We could have used the PPWIZARD "MacroGet" function if we were not 
  5354. sure about the quote situation as demonstrated below: 
  5355.  
  5356.     ;--- Capture some HTML information ------------------------------------------
  5357.     #evaluate ShortNameHtmlLowerCase   "ToLowerCase(MacroGet('ShortNameHtml'))"
  5358.  
  5359. There is another (probably better way) of handling the quote 'problem' as in: 
  5360.  
  5361.     ;--- Capture some HTML information ------------------------------------------
  5362.     #evaluate ShortNameHtmlLowerCase   "ToLowerCase('<$ShortNameHtml $$SQX2>')"
  5363.  
  5364.  
  5365. ΓòÉΓòÉΓòÉ 7.8. Multi Line Macros With Logic ΓòÉΓòÉΓòÉ
  5366.  
  5367. Multi Line Macros With Logic 
  5368.  
  5369. The subject of macros is reasonably complex (but well worth learning) please 
  5370. ensure you have at least read the macro introduction before reading this 
  5371. section. 
  5372.  
  5373. In this example we add some conditional inclusion where the same macro can 
  5374. generate different text based on the environment or parameters that are passed 
  5375. to it.  In the following macro the size of the image file is calculated unless 
  5376. a value was passed to it. 
  5377.  
  5378. You might create a macros as follows to display some photos in a table: 
  5379.  
  5380.    ;--- Photo macro will either use passed size or work out correct size for you ---
  5381.    #define Photo                                                               \
  5382.            #evaluate+  LocalFileName    ^"..\graphics\{$Image}"^               \
  5383.            #DependsOn  INPUT            "<$LocalFileName>"                     \
  5384.            <TR>                                                                \
  5385.            #if "{$Size=''}" <> ""                                              \
  5386.                #define+   TmpSize {$Size=''}     ;;User supplied size          \
  5387.            #elseif                                                             \
  5388.                #evaluate+ TmpSize ^GetImageHeightWidth("<$LocalFileName>")^    \
  5389.            #endif                                                              \
  5390.            <TD ALIGN=CENTER>                                                   \
  5391.            <IMG SRC="graphics/clear1x1.gif" WIDTH=1 HEIGHT=1 VSPACE=20>        \
  5392.            {$Title}<BR><BR>                                                    \
  5393.            <IMG SRC="graphics/{$Image}" BORDER=0 <$TmpSize> ALT="{$Title}">    \
  5394.            <IMG SRC="graphics/clear1x1.gif" WIDTH=1 HEIGHT=1 VSPACE=20>        \
  5395.            </TR>
  5396.  
  5397. It is then a simple matter to create format and add new photos as follows (note 
  5398. that the image size is automatically calculated): 
  5399.  
  5400.     ;--- Create table of photos --------------------------------------------
  5401.     <BR><CENTER><TABLE COLS=1 BORDER=10 CELLSPACING=10>
  5402.        <TR>
  5403.        <TH ALIGN=CENTER>Pictures
  5404.        </TR>
  5405.  
  5406.        ;--- Include all my photos ------------------------------------------
  5407.        <$Photo Image="lazy.jpg"     Title="Watching TV">
  5408.        <$Photo Image="carback.jpg"  Title="New Car (Back Left)">
  5409.     </TABLE></CENTER>
  5410.  
  5411.  
  5412. ΓòÉΓòÉΓòÉ 7.9. Die When Unused Parms ΓòÉΓòÉΓòÉ
  5413.  
  5414. Die When Unused Parms 
  5415.  
  5416. The subject of macros is reasonably complex (but well worth learning) please 
  5417. ensure you have at least read the macro introduction before reading this 
  5418. section. 
  5419.  
  5420. While PPWIZARD does show unused parameters when in debug mode, this does not 
  5421. cause ppwizard to complain. This is because there are a number of situations 
  5422. (some coding style issues as well) where you can expect to find some parameters 
  5423. whose values were not expanded by a macro. 
  5424.  
  5425. While PPWIZARD does not know if unused parameters might indicate an error, you 
  5426. do, so you can tell ppwizard to die if a macro is passed parameters that it 
  5427. does not use. 
  5428.  
  5429. You may not always get this error, for example if a manditory parameter was 
  5430. mispelt it would fail because the parameter was missing but it does provide 
  5431. some helpful extra validation. 
  5432.  
  5433. Some common mistakes that could be detected by this validation include: 
  5434.  
  5435.          The extra parameters may have been passed because the wrong macro was 
  5436.           accidently used. 
  5437.  
  5438.          An optional parameter was mispelt and therefore not used. 
  5439.  
  5440.          A macro was modified but not all references were updated. 
  5441.  
  5442.  This validation may slow down processing slightly but is probably worth it 
  5443.  anyway if others will be using your macros. You could compromise and limit the 
  5444.  validation to externally known macros  and keep "internal" ones unvalidated. 
  5445.  
  5446.  The main situation where you are likely to get a false hit is where a 
  5447.  parameter's value is only used as a default for another parameter. In cases 
  5448.  like this you could use the parameter with the '$$IGNORE' command so as to 
  5449.  expand to nothing but mark the parameter as used. Otherwise if you get a false 
  5450.  hit remove the validation on those macros or alter your style. 
  5451.  
  5452.  The "ParmVal" option influences the operation of this tag. 
  5453.  
  5454.  Example 
  5455.  
  5456.       ;--- Define a macro that takes no parameters ---
  5457.       #define EMAIL   fred@home.com{$!}
  5458.  
  5459.       ;--- Correct Use (no parameters) ---
  5460.       VALUE: <$EMAIL>
  5461.  
  5462.       ;--- Incorrect Use (some parameters) ---
  5463.       VALUE: <$EMAIL X=1 Y=2 "3">
  5464.  
  5465.  
  5466. ΓòÉΓòÉΓòÉ 7.10. Expand All Unused Parameters ΓòÉΓòÉΓòÉ
  5467.  
  5468. Expand All Unused Parameters 
  5469.  
  5470. The subject of macros is reasonably complex (but well worth learning) please 
  5471. ensure you have at least read the macro introduction before reading this 
  5472. section. 
  5473.  
  5474. This option allows you to create a ppwizard macro for a html tag and process 
  5475. any parameters you wish while expanding any you don't specifically make use of. 
  5476. For example the following is a simplistic "IMG" tag front end: 
  5477.  
  5478.     #define  IMG   <IMG SRC="graphics/{$FILE}" ALT="{$ALT='{$FILE}'}"{$?}>
  5479.  
  5480. Notice the "{$?}" tag above, it will expand all parameters used on a reference 
  5481. except "FILE" and "ALT". You can also use "{$?ResetUsed}" if you want to 
  5482. process all parameters (used or not). If there are specific parameters that you 
  5483. don't want included (as yet unused) then you should preceed this command with 
  5484. the parameter using '$$IGNORE'. If there were no parameters then nothing is 
  5485. expanded else a space preceeds the resultant parameter. 
  5486.  
  5487. There are actually 2 modes of replacement, the above shows one mode where no 
  5488. "$$" Commands were used, if they were used then the commands are applied to 
  5489. each unused parameter in turn. In general one of the $$ commands would be a 
  5490. "pass" command. 
  5491.  
  5492. Using the $$ commands gives you much more quoting flexability and gives you the 
  5493. option of not passing on the parameters, you may wish to simply memorise them 
  5494. for later use. 
  5495.  
  5496. To allow you to use it any number of times, this parameter does not mark all 
  5497. the parameters as used. It does however disable any {$!} validation for the 
  5498. macro. 
  5499.  
  5500.  
  5501. ΓòÉΓòÉΓòÉ 7.11. Expand All Parameters As Rexx Code ΓòÉΓòÉΓòÉ
  5502.  
  5503. Expand All Parameters As Rexx Code 
  5504.  
  5505. The subject of macros is reasonably complex (but well worth learning) please 
  5506. ensure you have at least read the macro introduction before reading this 
  5507. section. 
  5508.  
  5509. This section describes an advanced rarely used or required facility which 
  5510. allows you to write a macro that can take variable parameters with unknown 
  5511. names etc. This is useful in cases where the macro logic is very generic but 
  5512. can be applied for an unknown number of parameters or parameters whose names 
  5513. may change (as the name itself is significant for the generated code). 
  5514.  
  5515. The parameter information that is expanded by "{$??}" is in the form of rexx 
  5516. code initializing an array (stem). This means that you would normally require 
  5517. rexx code to process the information. 
  5518.  
  5519. The information generated is as follows (where '?' represents a number 1 to 
  5520. 'n'): 
  5521.  
  5522.          MP.?.MPNAME 
  5523.           This holds the name of the parameter in the case the user supplied. 
  5524.  
  5525.          MP.?.MPVALUE 
  5526.           This holds the value of the parameter. 
  5527.  
  5528.          MP.?.MPUSED 
  5529.           This holds 'Y' or 'N' to indicate whether the parameter was used in 
  5530.           the macro prior to expansion of this code. 
  5531.  
  5532.          MP.?.MPTYPE 
  5533.           This holds 'V' (for value) or 'NV' (no value) to indicate whether or 
  5534.           not the parameter had a value. 
  5535.  
  5536.  Note that "MP.0" holds the value of 'n', that is the number of parameters 
  5537.  stored. Any "$$" commands are unfortunately ignored, tell me if you have 
  5538.  problems with this. 
  5539.  
  5540.  To allow you to use it any number of times, this parameter does not mark all 
  5541.  the parameters as used. It does however disable any {$!} validation for the 
  5542.  macro. 
  5543.  
  5544.  Example 
  5545.  
  5546.  This example code shows how the parameter is used and what it expands to but 
  5547.  does not show the generated array being used in any way. 
  5548.  
  5549.  The source code: 
  5550.  
  5551.       #define    TestQmQm        {$??}
  5552.  
  5553.       *** 0 PARMS *****
  5554.       <$TestQmQm>
  5555.  
  5556.       *** SOME PARMS *****
  5557.       <$TestQmQm "Parm1IsPositional 1" Parm2HasNoValue Parm3="Parm3Value">
  5558.  
  5559.  Generates: 
  5560.  
  5561.       *** 0 PARMS *****
  5562.       MP.0 = 0
  5563.  
  5564.       *** SOME PARMS *****
  5565.       MP.1.MPNAME  = '#1'
  5566.       MP.1.MPVALUE = 'Parm1IsPositional 1'
  5567.       MP.1.MPUSED  = 'N'
  5568.       MP.1.MPTYPE  = 'V'
  5569.       MP.2.MPNAME  = 'Parm2HasNoValue'
  5570.       MP.2.MPVALUE = 'PARM2HASNOVALUE'
  5571.       MP.2.MPUSED  = 'N'
  5572.       MP.2.MPTYPE  = 'NV'
  5573.       MP.3.MPNAME  = 'Parm3'
  5574.       MP.3.MPVALUE = 'Parm3Value'
  5575.       MP.3.MPUSED  = 'N'
  5576.       MP.3.MPTYPE  = 'V'
  5577.       MP.0 = 3
  5578.  
  5579.  The "Row" macro in my "WISEINST.WIH" is built around this facility. 
  5580.  
  5581.  
  5582. ΓòÉΓòÉΓòÉ 7.12. Expand Macro Name ΓòÉΓòÉΓòÉ
  5583.  
  5584. Expand Macro Name 
  5585.  
  5586. The subject of macros is reasonably complex (but well worth learning) please 
  5587. ensure you have at least read the macro introduction before reading this 
  5588. section. 
  5589.  
  5590. This section describes an advanced rarely used or required facility which 
  5591. allows you to write a macro that can determine the name of the macro being 
  5592. expanded (in the exact case used). This value can be obtained by using 
  5593. "{$MACNAME}". 
  5594.  
  5595. One example of where this could be handy is if you are marking the start of 
  5596. some sort of block for which you need an ending marker. If you would also like 
  5597. this block to be able to contain the ending marker (for example in 
  5598. documentation you may be showing someone how to do something) then you will 
  5599. need to perform a case sensitive search for the end block marker. The 
  5600. "<$eExample>" macro/tag (used in some of my headers) is an example of this sort 
  5601. of situation. 
  5602.  
  5603. If you vary the case on the start of block macros and can determine this case 
  5604. you can create a end block marker from this value. 
  5605.  
  5606. Example 
  5607.  
  5608. Some test code follows: 
  5609.  
  5610.     #define    TestMacName      {$?MacName}
  5611.     #define    TestMacNameUpper {$?MacName $$UPPER}
  5612.  
  5613.     *** Macro name ***
  5614.     MacroName = "<$TestMacName>"
  5615.     MacroNAME = "<$TestMacNAME>"
  5616.     MACRONAME = "<$TestMacNameUpper>"
  5617.  
  5618.  
  5619. ΓòÉΓòÉΓòÉ 7.13. Macro Tranformations ΓòÉΓòÉΓòÉ
  5620.  
  5621. Macro Tranformations 
  5622.  
  5623. The subject of macros is reasonably complex (but well worth learning) please 
  5624. ensure you have at least read the macro introduction before reading this 
  5625. section. 
  5626.  
  5627. PPWIZARD provides a mechanism to hold macro data in one format but transform 
  5628. this data when tranformed, this removes the need to hold the same data in 
  5629. multiple formats. 
  5630.  
  5631. Transformation commands all start with $$ and apply to: 
  5632.  
  5633.        1. Macro Replacement 
  5634.           Macros parameter where they were supplied on a reference without a 
  5635.           value that and begin with '$$' have special meaning, they are 
  5636.           commands to PPWIZARD. 
  5637.  
  5638.           The command applies to the complete contents of a macro before any 
  5639.           replacement of parameters has occurred. 
  5640.  
  5641.        2. Macro Parameter Replacement 
  5642.  
  5643.  Restriction 
  5644.  
  5645.  Note that most of the above '$$' commands work directly on the contents of the 
  5646.  macro (after parameter substitution). If the contents (or parameters) 
  5647.  contained macros then you may not get the desired affect. 
  5648.  
  5649.  The Available $$ Tranformations 
  5650.  
  5651.  In the following list "Bold $$ commands" apply to both macro and parameter 
  5652.  replacement, "Dark Green $$ commands" only apply to macro replacement and 
  5653.  "Magenta $$ commands" only apply to macro parameter replacement: 
  5654.  
  5655.                    $$ADDCOMMA
  5656.           The parameter will be formatted using AddCommasToDecimalNumber(). 
  5657.  
  5658.                    $$ASIS
  5659.           The value of the macro is substituted EXACTLY as it is, there is no 
  5660.           substitution of macro parameters etc. Note that this will not prevent 
  5661.           any macros the contents refers to from being expanded. 
  5662.  
  5663.                    $$AQ
  5664.           You use this command to surround your parameters data with quotes. 
  5665.           The quotes used are double or single quotes, if neither can be used 
  5666.           ppwizard will go through a whole list of alternative 'quote' 
  5667.           characters, if none of these can be used then ppwizard will 
  5668.           terminate. 
  5669.  
  5670.                    $$DSQ
  5671.           You use this command to surround your parameters data with quotes. 
  5672.           The quotes used are double or single quotes, if neither can be used 
  5673.           ppwizard will terminate. 
  5674.  
  5675.                    $$HTMLQ
  5676.           The parameter is all or part of a string surrounded by double quotes, 
  5677.           any double quotes that exist in the data should be converted to 
  5678.           """. 
  5679.  
  5680.                    $$IGNORE
  5681.           The parameter will be "dropped" (a empty string will be substituted). 
  5682.           The main reason you might want to do this is to prevent a '"{$?}"' 
  5683.           type parameter from including this parameter. 
  5684.  
  5685.                    $$LOWER
  5686.           The parameter will be converted to lower case. 
  5687.  
  5688.                    $$RX'
  5689.           This can be very useful if you wish to use the value in a rexx string 
  5690.           which is surrounded by single quotes. It makes sure that the value 
  5691.           will not break any rexx rules. Note that there is also a '$$RX"' 
  5692.           variant for use in double quoted rexx literals. 
  5693.  
  5694.                    $$RXEXEC
  5695.           The value is taken to be rexx code to be executed. The value to be 
  5696.           substituted should be returned in the "RXEXEC" variable. 
  5697.  
  5698.                    $$SPCPLUS
  5699.           A space is added before the start of the value if it is non-empty. 
  5700.  
  5701.                    $$SQX2
  5702.           The value is modified such that all single quote characters are 
  5703.           doubled up. This can be very useful if you wish to use the value in a 
  5704.           rexx string which is surrounded by single quotes as rexx will in this 
  5705.           situation treat the two single quotes as a single single quote that 
  5706.           does not terminate the string. <P>It should be noted that under 
  5707.           regina there is a limitation that a long string could break so I now 
  5708.           recommend the use of "$$RX'" instead. 
  5709.  
  5710.                    $$PASSDSQ
  5711.           The parameter will be quoted as per the $$DSQ command and the 
  5712.           parameter name followed by the equal sign will be added to the start. 
  5713.           This is handy when one macro uses another and a parameter needs to be 
  5714.           passed to the inner macro (parameter has same name in both macros). 
  5715.  
  5716.                    $$PASSAQ
  5717.           The parameter will be quoted as per the $$AQ command and the 
  5718.           parameter name followed by the equal sign will be added to the start. 
  5719.           This is handy when one macro uses another and a parameter needs to be 
  5720.           passed to the inner macro (parameter has same name in both macros). 
  5721.  
  5722.                    $$SDQ
  5723.           You use this command to surround your parameters data with quotes. 
  5724.           The quotes used are single or double quotes, if neither can be used 
  5725.           ppwizard will terminate. 
  5726.  
  5727.                    $$UPPER
  5728.           The parameter will be converted to upper case. 
  5729.  
  5730.          $$? 
  5731.           If the '$$' command is otherwise unknown you can create your own 
  5732.           formatting (ie you can not redefine an existing format). 
  5733.  
  5734.           To define a format you need to define a macro which contains the rexx 
  5735.           formatting code. The macro must have the name of "REXX_$$" followed 
  5736.           by the name of your command, for example to use the command 
  5737.           "$$TO_C_STRING" you would create "REXX_$$TO_C_STRING". The value to 
  5738.           be formatted is in the "TheValue" variable. 
  5739.  
  5740.           If required you can also determine the source of the value (macro or 
  5741.           parameter name) as it is stored in "TheName" (for case insensitive 
  5742.           items it is in upper case). For macro parameters only the name of the 
  5743.           macro being expanded is in the "TheMacro" variable. 
  5744.  
  5745.  Note that the quoting routines above do more than just make your code 
  5746.  "prettier", without using these commands you have to decide on a quote 
  5747.  character yourself and then a parameters value must never contain this 
  5748.  character. These special commands won't solve all quoting issues (remember 
  5749.  parameter processed left to right - imbedded parameters are not processed 
  5750.  first) however they will make life much easier. 
  5751.  
  5752.  EXAMPLE - $$ Parameter Replacement 
  5753.  
  5754.  Lets make sure that parameters 2 and 3 in the following macro get translated 
  5755.  to upper case: 
  5756.  
  5757.       ;--- Define macro ---------
  5758.       #define  SimpleTest P1={$parm1}, P2={$parm2="parm1_default" $$upper}, P3={$parm3 $$upper $$DSQ}
  5759.  
  5760.       ;--- Expand macro ---------
  5761.       <$SimpleTest Parm1='value1' Parm2='value2' Parm3='value3'>
  5762.  
  5763.  EXAMPLE - $$ Macro Replacement 
  5764.  
  5765.  A simple example where if the "$$SQX2" command were not used that ppwizard 
  5766.  would fail (in this case with variable "A" unknown trap): 
  5767.  
  5768.       #define TheMacro   The value 'A' is in quotes
  5769.       #evaluate "" "call Summary 'VALUE', '<$TheMacro $$SQx2>'"
  5770.  
  5771.  Another example where we wish to add commas to a rexx variable: 
  5772.  
  5773.       Value = <??ARexxVariable $$ADDCOMMA>
  5774.  
  5775.  Here is another example which may be useful if you were creating 'C' code and 
  5776.  maybe other situations: 
  5777.  
  5778.       ;--- Define directory (non 'C' format as used elsewhere) ---
  5779.       #define DIR_NAME     C:\DB\PROJECTS\FRED
  5780.  
  5781.       ;--- Define a macro to transform a string into 'C' format ---
  5782.       #DefineRexx REXX_$$TO_C_STRING
  5783.                   TheValue = ReplaceString(TheValue, '\',     '\\');
  5784.                   TheValue = ReplaceString(TheValue, '"',     '\"');
  5785.                   TheValue = ReplaceString(TheValue, d2c(10), '\n');
  5786.                   TheValue = ReplaceString(TheValue, d2c(13), '\r');
  5787.                   TheValue = ReplaceString(TheValue, d2c(7),  '\b');
  5788.       #DefineRexx
  5789.  
  5790.       ;--- Use our defined transformation ---
  5791.       StringC = "<$DIR_NAME $$TO_C_STRING>";
  5792.  
  5793.  
  5794. ΓòÉΓòÉΓòÉ 8. Dependancies ΓòÉΓòÉΓòÉ
  5795.  
  5796. Dependancies 
  5797.  
  5798. If you know what a make file does then this is basically the functionality 
  5799. PPWIZARD is trying to supply.  Once you have built your output files you don't 
  5800. need to rebuild them unless you modify one of your source files.  PPWIZARD 
  5801. actually does a very much better job than any make-file-based process. 
  5802.  
  5803. Let's consider a very complicated example where: 
  5804.  
  5805.        1. The source file is called "INPUT.IT". 
  5806.  
  5807.        2. It #includes "MACROS.IH". 
  5808.  
  5809.        3. For some stupid reason it reads in line one of "CONFIG.SYS". 
  5810.  
  5811.        4. It creates "OUTPUT.OUT" and "ALSO.OUT". 
  5812.  
  5813.        5. You have many other ".IT" files with their own dependancies. 
  5814.  
  5815.  The whole process might take a while.  You really only want to preprocess the 
  5816.  above 3 input files to produce the 2 output files if you need to. PPWIZARD 
  5817.  stores information in a dependancy file for each compile which will allow it 
  5818.  to check whether a build is required or not.  It will detect if any input or 
  5819.  output files have changed or if they are missing and begin to rebuild the 
  5820.  output. 
  5821.  
  5822.  To conditionally make your ".IT" files you could use: 
  5823.  
  5824.       ppwizard  *.it  /output:out\*.htm /CrLf /DependsOn:Depends\*.dep
  5825.  
  5826.  This command says to make "*.IT" and put all output into the "OUT" directory 
  5827.  and creates a "DEPENDS" directory and places dependancy information in this 
  5828.  directory. 
  5829.  
  5830.  Most dependancies can be handled by the preprocessor but sometimes you need to 
  5831.  help identify the input and output files.  For example, you probably used a 
  5832.  REXX linein() command to read from "CONFIG.SYS", you will need to use the 
  5833.  #DependsOn command to indicate this one. In a similar manner, the example 
  5834.  generates 2 output files; if you used the REXX lineout() command to create 
  5835.  these then you would again need to use the #DependsOn command to indicate this 
  5836.  output dependancy. 
  5837.  
  5838.  Filter 
  5839.  
  5840.  It is possible to tweek the contents of the generated file by creating a rexx 
  5841.  macro called "HOOK_DEPENDSON", rexx variables involved are: 
  5842.  
  5843.          DepIn 
  5844.           This is an array that holds each input dependancy. If you set an item 
  5845.           to "" then it will be dropped (no need to compress the array). Note 
  5846.           that any item that starts with "*" is not actually a file! 
  5847.  
  5848.          DepOut 
  5849.           This is an array that holds each output dependancy. If you set an 
  5850.           item to "" then it will be dropped (no need to compress the array). 
  5851.  
  5852.          DepDrop 
  5853.           If you wish to tell PPWIZARD not to generate the file at all then set 
  5854.           the value to non-blank, the value should be the reason which will 
  5855.           show up in any debug output. 
  5856.  
  5857.  An example of a hook which ensures that no output dependancies are recorded 
  5858.  follows: 
  5859.  
  5860.       #DefineRexx 'HOOK_DEPENDSON'
  5861.          ;--- Don't generate any output dependanies -------------------------------
  5862.          DepOut.0  = 0;
  5863.  
  5864.          ;--- Clear specific input dependancy -------------------------------------
  5865.       ;;;DepIn.1 = '';          ;;Changing to blank saves having to compress array
  5866.  
  5867.          ;--- Don't create dependancy file after all ------------------------------
  5868.       ;;;DepDrop = "Changed my Mind";
  5869.       #DefineRexx
  5870.  
  5871.  Since in this case PPWIZARD does not know about the output dependancies you 
  5872.  can safely manipulate or delete these without ppwizard remaking them. In 
  5873.  general I don't recommend this approach but it is another option for you. 
  5874.  
  5875.  
  5876. ΓòÉΓòÉΓòÉ 9. Commands ΓòÉΓòÉΓòÉ
  5877.  
  5878. Commands 
  5879.  
  5880. PPWIZARD has a lot of different commands and features, you could cover basic 
  5881. requirements (enough to get you well and truely started) with the "#include" 
  5882. command which includes external files and "#define" would allow you to start 
  5883. with simple macros or symbolic variables (these allow more reuse than simple 
  5884. file inclusion allows). 
  5885.  
  5886. The next step up from this is to look at conditional generation of code ("#if" 
  5887. etc), as an example this can be useful where there are two or more variations 
  5888. in how a header or footer should look. 
  5889.  
  5890. Note that you may wish to use the /HideCmd switch if you use a WYSIWYG editor. 
  5891.  
  5892. The following is a complete list of what is available to you when you use the 
  5893. PPWIZARD Preprocessor: 
  5894.  
  5895.          #AsIs 
  5896.          #AutoTag 
  5897.          #AutoTagClear 
  5898.          #AutoTagState 
  5899.          #debug 
  5900.          #define[+|?] 
  5901.          #DefineRexx[+] 
  5902.          #DependsOn 
  5903.          #ElseIf 
  5904.          #EndIf 
  5905.          #EOF 
  5906.          #error 
  5907.          #evaluate[+] 
  5908.          #if 
  5909.          #IfDef 
  5910.          #IfNDef 
  5911.          #import 
  5912.          #include 
  5913.          #Info 
  5914.          #intercept 
  5915.          #MacroSpace 
  5916.          #NextId 
  5917.          #OnExit 
  5918.          #option 
  5919.          #output 
  5920.          #OutputHold 
  5921.          #push 
  5922.          #pop 
  5923.          #require 
  5924.          #RexxVar 
  5925.          #transform 
  5926.          #UnDef 
  5927.          #warning 
  5928.          #( 
  5929.          #) 
  5930.          #Unknown Commands 
  5931.  
  5932.  The following commands allow you to perform PPWIZARD looping: 
  5933.  
  5934.          #{ 
  5935.          #} 
  5936.          #break 
  5937.          #continue 
  5938.  
  5939.  
  5940. ΓòÉΓòÉΓòÉ 9.1. #( ΓòÉΓòÉΓòÉ
  5941.  
  5942. #( 
  5943.  
  5944. This command provides a simple way to spread a long line of over many lines 
  5945. without the need for line continuation characters at the end of each line. 
  5946.  
  5947. Basically you define a block, within this block all lines are combined with the 
  5948. character(s) you chose used to separate the lines. Note that if some lines 
  5949. within the block need different line separators, you can still use the normal 
  5950. line continuation characters for these lines! An alternative method is to nest 
  5951. this command where multiple separators are required. 
  5952.  
  5953. It is recommended that you do not use this command to handle rexx code, use the 
  5954. #DefineRexx command instead. 
  5955.  
  5956. Note that the restriction of on long imbedded ppwizard command mentioned in the 
  5957. line continuation section also applies here. 
  5958.  
  5959. You can use this command to surround the definition of a macro, however the 
  5960. first line (The "#define[?|+]" command) must not end with a line continuation 
  5961. character. PPWIZARD will detect the definition and will ensure a space is used 
  5962. for the separator and not the "Separator" character sequence you defined. 
  5963.  
  5964. This command can't itself be used in a macro! If you try to do this the most 
  5965. likely result is being told that ppwizard does not understand the '#)' command. 
  5966.  
  5967. Syntax 
  5968.  
  5969.     [WhiteSpace]#(  [["]Separator["] [["]EndBlockMarker["]]]
  5970.  
  5971. If the Separator parameter is supplied it defines the zero or more characters 
  5972. that separate each line within the block. The default separator is a space. 
  5973.  
  5974. If the EndBlockMarker parameter is supplied this determines the text that marks 
  5975. the end of the block, this can be any text and by default is "#)" (note that 
  5976. the current prefix is used). Lines are combined until this text is located (in 
  5977. this exact case). 
  5978.  
  5979. This command used to be called "#OneLine" and you should replace all 
  5980. occurances. 
  5981.  
  5982. EXAMPLE - Basic Demo 
  5983.  
  5984.     #( '<?NewLine>'
  5985.        Line 1
  5986.        Line 2
  5987.        #( ' ' '$$$'      ;;"nested" block (block ends at '$$$')
  5988.            This
  5989.            is
  5990.            Line
  5991.            3
  5992.        $$$
  5993.        This    \
  5994.        is Line \
  5995.        4
  5996.        Line 5
  5997.     #)
  5998.  
  5999. EXAMPLE - Repeat Block 
  6000.  
  6001. In a jetform JMD (Job Management Database) we needed to define 82 lines for 
  6002. each product (only a subset of this is shown in the example) so we defined this 
  6003. macro: 
  6004.  
  6005.     ;--- Define the template for a "Product Summary" ---
  6006.     #define ExpandMacro <${$#1}>
  6007.     #( '<?NewLine>'
  6008.        #define ProductSummary
  6009.        <?Hash>===[ Product Summary ]========================================
  6010.        <?Hash>===    Product: {$Product}
  6011.        <?Hash>===        MDF: {$Mdf}
  6012.        <?Hash>=== Input Tray: {$InputTray}
  6013.        <?Hash>=== Defined at: Line <?InputComponentLine> of <?InputComponent>
  6014.        <?Hash>==============================================================
  6015.        !f {$Product}_F_1 RIGHTFAX """<$DirJfForms>\{$MDF}.mdf"" -afxon -aip2 -agvFAX_MESS=1" * 1 T SSPPGGET * * C *
  6016.        !f {$Product}_F_1 RIGHTFAX """<$DirJfForms>\{$MDF}.mdf"" -afxon -aip2 -agvFAX_MESS=1" * 1 T SSPPGSET * * C *
  6017.        ...
  6018.        ...
  6019.        !f {$Product}_P Optra """<$DirJfForms>\{$MDF}.mdf"" -afxon -aip1 -ati20<$ExpandMacro =^{$InputTray}^>" * 1 T SSPPGGET * * C *
  6020.        !f {$Product}_P Optra """<$DirJfForms>\{$MDF}.mdf"" -afxon -aip1 -ati20<$ExpandMacro =^{$InputTray}^>" * 1 T SSPPGSET * * C *
  6021.        <?Hash>
  6022.        <?Hash>
  6023.     #)
  6024.  
  6025.     ;--- Define the input paper trays used ---
  6026.     #define LIGHT   3
  6027.     #define DARK    4
  6028.  
  6029. We then use the above macro: 
  6030.  
  6031.     <$ProductSummary  Product="PROD19"   MDF="PSMORT"     InputTray="DARK">
  6032.     ...
  6033.     <$ProductSummary  Product="PROD40"   MDF="PSGENERAL"  InputTray="LIGHT">
  6034.     ...
  6035.     <$ProductSummary  Product="PROD73"   MDF="PSGENERAL"  InputTray="LIGHT">
  6036.  
  6037.  
  6038. ΓòÉΓòÉΓòÉ 9.2. #) ΓòÉΓòÉΓòÉ
  6039.  
  6040. #) 
  6041.  
  6042. There is no such command although it may at first glance appear so. 
  6043.  
  6044. The text "#)" is simply the default end of #( block marker if no alternative 
  6045. was specified. 
  6046.  
  6047. If you find ppwizard telling you that there is no such command then that is 
  6048. perfectly correct. The fault is that the block commands can not appear in a 
  6049. macro. 
  6050.  
  6051. This "command" used to be called "#OneLineEnd" and you should replace all 
  6052. occurances. 
  6053.  
  6054.  
  6055. ΓòÉΓòÉΓòÉ 9.3. #{ ΓòÉΓòÉΓòÉ
  6056.  
  6057. #{ 
  6058.  
  6059. This command is used to define the start of a loop which ends with the "#}" 
  6060. statement. Loops can be used within a macro. 
  6061.  
  6062. Syntax 
  6063.  
  6064.     [WhiteSpace]#{  [FOR RexxVariable = Start TO End] or
  6065.     [WhiteSpace]#{  [SET [COUNTER RexxVar] ["]SetSpec1["] ...]
  6066.  
  6067. The syntax directly supports simple "for" loops and "set" loops, for more 
  6068. complicated requirements you would need to do your own end of loop processing. 
  6069.  
  6070. The #continue command can be used to restart at the top of the loop and #break 
  6071. will cause you to exit the loop. 
  6072.  
  6073. FOR Loops 
  6074.  
  6075. Probably fairly obvious but you are looping through all integers from a 
  6076. starting point and incrementing by one until the ending point is reached. 
  6077.  
  6078. SET Loops 
  6079.  
  6080. The idea behind a set loop is that you have one or more sets of values which 
  6081. you'd like to process, effectively this can provide a nested loop like 
  6082. functionality. 
  6083.  
  6084. A set is simply an array containing items (possibly created using Add2() or 
  6085. ArraySplit()). In general having duplicated entries would make no sense but 
  6086. this is no validated. 
  6087.  
  6088. If a set specification contains an equals sign then you wish to create a set of 
  6089. data by splitting the string after the equal sign. By default a space is used 
  6090. as a delimiter, to override this preceed the string with '{Delimiter}'. Leading 
  6091. and trailing whitespace is always removed and blank items ignored. 
  6092.  
  6093. If set "a" contains 10 items, set "b" contains 3 and set "c" contains 4 and you 
  6094. specified "SET A B C" then the loop will be executed 10x3x4=120 times as every 
  6095. combination will be processed. 
  6096.  
  6097. To access the current values of the sets within the loop you use rexx variables 
  6098. "SET_A", "SET_B" and "SET_C". The names must be valid as rexx symbols. There is 
  6099. no built in limit on the number of set items and the left most item varies 
  6100. slowest until the right most which varies fastest. 
  6101.  
  6102. If you specify a "COUNTER" name then you can use this variable within the loop, 
  6103. it will start at one and increment for each combination processed. 
  6104.  
  6105. Restrictions 
  6106.  
  6107.        1. Both the start and end of a loop must occur within the same input 
  6108.           file. 
  6109.  
  6110.        2. Loops can't be nested (within a single file). 
  6111.  
  6112.           If you need to nest loops you can either use the #include command to 
  6113.           include a file which then itself contains a loop or you do a bit of 
  6114.           rexx programming. 
  6115.  
  6116.        3. Since PPWIZARD loads the whole loop without processing lines in 
  6117.           between the affect of any intermediate "HashPrefix" option is ignored 
  6118.           for the purposes of finding the end of the loop. 
  6119.  
  6120.  Example 1 - Create 99 Printers in a Jetform JMD 
  6121.  
  6122.  This creates 99 printer definitions in a Jetform JMD, looking similar to: 
  6123.  
  6124.       !p PRINTR01 PRINTR01 PRINTR01/q "-afx...
  6125.       ...
  6126.       !p PRINTR99 PRINTR99 PRINTR99/q "-afx...
  6127.  
  6128.  The code to generate these printer definitions is: 
  6129.  
  6130.       ;--- Define 99 SSP Printers ---
  6131.       #RexxVar SspPrinter = 1
  6132.       #{
  6133.          ;--- Make sure we use "01" - "99" ---
  6134.          #if [<??SspPrinter> < 10]
  6135.              #evaluate ^^ ^SspPrinter = '0' || SspPrinter^    ;;Does not affect addition
  6136.          #endif
  6137.  
  6138.          ;--- Create the printer ---
  6139.          !p PRINTR<??SspPrinter> PRINTR<??SspPrinter> PRINTR<??SspPrinter>/q "-afxon -apfon -axpson -asplex616p -rYES -aduON" 50
  6140.  
  6141.          ;--- Finished? ---
  6142.          #RexxVar SspPrinter + 1      ;;Add 1 to count
  6143.          #if [<??SspPrinter> > 99]    ;;Finished?
  6144.              #break                   ;;Created all printers!
  6145.          #endif
  6146.       #}
  6147.  
  6148.  The above again but this time using a "for" loop as well as using a macro 
  6149.  replacement tranformation (this is slower): 
  6150.  
  6151.       ;--- Simple transformation to product 2 digit (minimum) integers ---
  6152.       #DefineRexx REXX_$$0PadTo2
  6153.          TheValue = TheValue + 0;                ;;Strip off excess spaces and leading zeros
  6154.          if  TheValue < 10 then                  ;;Has less than 2 digits?
  6155.              TheValue = right(TheValue, 2, '0'); ;;Left pad to 2 digits
  6156.       #DefineRexx
  6157.  
  6158.       ;--- The code to produce 99 printer definitions ---
  6159.       #{ for SspPrinter = 1 to 99
  6160.          ;--- Create a printer ---
  6161.          !p PRINTR<??SspPrinter $$0PadTo2> PRINTR<??SspPrinter $$0PadTo2> PRINTR<??SspPrinter $$0PadTo2>/q "-afxon -apfon -axpson -asplex616p -rYES -aduON" 50
  6162.       #}
  6163.  
  6164.  Example 2 - Test "SET" loop 
  6165.  
  6166.  The following code shows 4 different variations on how set data can be created 
  6167.  and specified. 
  6168.  
  6169.       #DefineRexx ''
  6170.          ;--- Create SET "A" ---
  6171.          A.1 = '1'
  6172.          A.2 = '4'
  6173.          A.3 = '7'
  6174.          A.0 =  3   ;;Number of Items in set "A"
  6175.  
  6176.          ;--- Create SET "B" ---
  6177.          call ArraySplit 'B', 'apple orange'
  6178.       #DefineRexx
  6179.  
  6180.       ;--- Use the "sets" created above -------------------------------------------
  6181.       #RexxVar NUMLOOPS = 0                   ;;Loop counter (Better way demonstrated below)
  6182.       #{ SET A B
  6183.          #RexxVar NUMLOOPS + 1
  6184.          <??NUMLOOPS>. A = "<??SET_A>"   , B = "<??SET_B>"
  6185.       #}
  6186.  
  6187.       ;--- Create sets as part of the loop command --------------------------------
  6188.       #{ SET counter NUMLOOPS                        \
  6189.              ^A=1 7 9 11^                            \
  6190.              ^B={,}aaa,bbb,ccc,ddd,eee,fff^
  6191.          <??NUMLOOPS>. A = "<??SET_A>"   , B = "<??SET_B>"
  6192.       #}
  6193.  
  6194.  Example 3 - Read File Until End 
  6195.  
  6196.  This example is used to load a list of languages and to create a directory for 
  6197.  each ones generated html.  The languages file looks like: 
  6198.  
  6199.       en     ;;English
  6200.       it     ;;Italian
  6201.       fr     ;;French
  6202.  
  6203.  The code (OS/2 only) to read the above file and create the directories is: 
  6204.  
  6205.       ;--- Define some directories ---
  6206.       #define site.root            C:\sitetest
  6207.       #define site.out.dir         <$site.root>\html     ;;output root
  6208.  
  6209.       ;--- Initialization ---
  6210.       #DefineRexx ''
  6211.          ;--- Load standard rexx library ---
  6212.          call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
  6213.          call SysLoadFuncs
  6214.  
  6215.          ;--- Make required base directories ---
  6216.          MkDirRc = SysMkDir('<$site.root>')
  6217.          MkDirRc = SysMkDir('<$site.out.dir>')
  6218.       #DefineRexx
  6219.  
  6220.       ;--- Make language directories ---
  6221.       #define    LanguageFile   "LANG.IH"           ;;Note in this case would be more CPU efficent if rexx variable
  6222.       #DependsOn INPUT <$LanguageFile>
  6223.       #evaluate "" ^CloseFileRc = stream(<$LanguageFile>, 'c', 'close');^
  6224.       #{
  6225.          ;--- Exit on EOF ---
  6226.          #if  lines(<$LanguageFile>) = 0
  6227.               #break
  6228.          #endif
  6229.  
  6230.          ;--- Read the language line, strip out comment and make directory ---
  6231.          #evaluate "" "MkDirRc=SysMkDir('<$site.out.dir>\' || '<?=word(linein(<$LanguageFile>), 1)>')"
  6232.       #}
  6233.       #evaluate "" ^CloseFileRc = stream(<$LanguageFile>, 'c', 'close');^
  6234.  
  6235.  
  6236. ΓòÉΓòÉΓòÉ 9.4. #} ΓòÉΓòÉΓòÉ
  6237.  
  6238. #} 
  6239.  
  6240. This command is used to define the end of a loop the start of which must also 
  6241. occur within the same input file. 
  6242.  
  6243. Please see the "#{" command for an example and more information. 
  6244.  
  6245.  
  6246. ΓòÉΓòÉΓòÉ 9.5. #AsIs ΓòÉΓòÉΓòÉ
  6247.  
  6248. #AsIs 
  6249.  
  6250. This command is frequently used to allow you to #include real working code as 
  6251. examples.  Any modifications required to get the file (or part of) to display 
  6252. "as is" occurs automatically as programmed by you. 
  6253.  
  6254. Turning on "asis" mode basically allows you to read in text without PPWIZARD 
  6255. getting in the way.  More than this is can simplify issues such as the fact 
  6256. that the viewer may not be able to display certain characters unless converted. 
  6257. For example a html viewer may have trouble with '<' characters unless they are 
  6258. converted to '<'. 
  6259.  
  6260. Turning "asis" mode on will modify a number of PPWIZARD #Options so that lines 
  6261. will get passed through "as is".  This means blank lines are kept, line comment 
  6262. and continuation is ignored and a number of other options may be modified. Use 
  6263. "#Debug" to see all that are modified. 
  6264.  
  6265. While #AsIs mode is turned on, PPWIZARD commands are still processed. This is 
  6266. fine if your examples either don't include ppwizard commands or you wish to 
  6267. conditionally include parts of the example. If you did not want this you would 
  6268. need to use the "HashPrefix" option or take some other action to prevent it. 
  6269.  
  6270. You may need to do more than this to get the effect you desire. For example to 
  6271. have have the lines appear in a HTML browser as they do in your source you will 
  6272. need to do more work (or blank lines get removed and long lines wrap etc).  The 
  6273. minimum you would require for HTML is to use <PRE> & </PRE> tags around the 
  6274. lines. 
  6275.  
  6276. Using "<PRE>" as mentioned above only handles part of your issues with a HTML 
  6277. browser, any html tags such as "<P>" will get interpreted by the browser and 
  6278. generate a new paragraph. This is fine if that was your intention however you 
  6279. probably wish to see the characters "<P>" in the browser.  You could make use 
  6280. of the "#AutoTag" or "#AsIs" autotagging facility to convert all occurrances of 
  6281. "<" to "<". 
  6282.  
  6283. It's normally more flexible to have basic autotagging such as that mentioned 
  6284. for the "<" character handled by this command and any extensions to the 
  6285. fundamental changes handled by the "#AutoTag" command.  You would also wish to 
  6286. check out the "#AutoTagClear" & "#AutoTagState" commands. 
  6287.  
  6288. There are some tricky bits that you may need to handle - such as how do you 
  6289. tell PPWIZARD where the end of the example code is. If you are not careful any 
  6290. end of example marker you place could get autotagged in such a way that 
  6291. PPWIZARD will not recogise it! This can be tricky, to see examples of how this 
  6292. can be handled, see my "OL_DOC.DH" header file which handles examples for IPF 
  6293. and HTML examples. 
  6294.  
  6295. All AsIs tagging is performed before "#AutoTag" tagging. As mentioned earlier 
  6296. it can be difficult or impossible (in some situations) to escape out of an 
  6297. "example" mode that you set up. It will help you to remember that all 
  6298. autotagging is case sensitive and only occurs on data as it is read from a file 
  6299. (not on lines from memory/macros). If you don't get the results you expect you 
  6300. will need to use "#debug" or "/debug" to watch what occurs. In debug mode lines 
  6301. from a file are show in a similar manner to "0012:" where a line from memory 
  6302. could be shown as "####:". 
  6303.  
  6304. Like autotagging you must be very careful in the order that you tag things for 
  6305. example specifing that '<' gets replaced with '<' and then that '&' gets 
  6306. replaced with '&' is wrong as you would be tagging the '<' from the 
  6307. first replacement.  For the example given here you would need to swap the 
  6308. order, in other cases you may need to use an intermediate 'unique' string and 
  6309. convert it back as the last change. 
  6310.  
  6311. If possible try and group changes so that all single character changes are 
  6312. together this allows PPWIZARD to perform faster replacments as it can make good 
  6313. use of the BulkChar2String() routine. 
  6314.  
  6315. Syntax 
  6316.  
  6317.     [WhiteSpace]#AsIs ["]SETUP["]  ["]NAME["]         OR
  6318.     [WhiteSpace]#AsIs ["]OFF["]                       OR
  6319.     [WhiteSpace]#AsIs ["]ON["]   [["]NAME1["]  ...]
  6320.  
  6321. The "SETUP" command is used to store all currently defined "#AutoTag" commands 
  6322. under the "NAME" you supply. The existing AutoTags are cleared. 
  6323.  
  6324. The "OnOrOffCommand" specifies whether or not "asis" mode is on. 
  6325.  
  6326. When turning #AsIs mode on you may specify one or more named sets of tags that 
  6327. were previously set up with "SETUP". 
  6328.  
  6329. Example - SETUP 
  6330.  
  6331.     ;--- Setup minimum tagging for IPF lines ---------------------------------
  6332.     #AutoTagState +                        ;;Lets not effect current tags
  6333.     #AutoTag      "&"   "&."
  6334.     #AutoTag      ":"   "&colon."
  6335.     #AsIs         SETUP IpfAsIsChanges     ;;Copy tags and clear (name tags "IpfAsIsChanges")
  6336.     #AutoTagState -                        ;;Restore Original AutoTag state
  6337.  
  6338. Example - Including Example File 
  6339.  
  6340. The following is an example of a macro which will display an example file with 
  6341. a nice border and title (in a table).  The included file does not contain 
  6342. conditional commands etc (or if it does we want to see it as part of the 
  6343. example).  This is one example of a macro you could use: 
  6344.  
  6345.     #define    IncludeExampleFile                    \
  6346.                <BR><TABLE BORDER=5 CELLSPACING=5>    \
  6347.                <TR>                                  \
  6348.                <TH ALIGN=LEFT>{$TEXT}                \
  6349.                </TR>                                 \
  6350.                <TR><TH ALIGN=LEFT>                   \
  6351.                <PRE>                                 \
  6352.                <FONT size=-1>                        \
  6353.                #AsIs       ON HtmlAsIsChanges        \
  6354.                #AutoTag    ON                        \
  6355.                #option     PUSH HashPrefix="#$@!"    \
  6356.                #$@!include "{$FILE}"                 \
  6357.                #$@!option  POP   ;;Restore Prefix    \
  6358.                #AutoTag    OFF                       \
  6359.                #AsIs       OFF                       \
  6360.                </FONT>                               \
  6361.                </PRE>                                \
  6362.                </TR>                                 \
  6363.                </TABLE>
  6364.  
  6365. Prior to using the above macro we need to have defined up the "HtmlAsIsChanges" 
  6366. tagging.  This could have been done as follows: 
  6367.  
  6368.     #Autotagstate +                     ;;Lets not stuff up any existing autotags
  6369.     #AutoTag '<' '<'                 ;;Browser may not display text unless '<' etc changed.
  6370.     #AutoTag '>' '>'
  6371.     #AsIs    SETUP     HtmlAsIsChanges  ;;Remember tagging we wish to take place
  6372.     #Autotagstate -                     ;;Restore previous autotag state
  6373.  
  6374. Now lets use the above macro (and do some automatic tagging): 
  6375.  
  6376.     #AutoTagClear
  6377.     #AutoTag  "REM "    '<A HREF="rem.htm">REM</A> '
  6378.     #AutoTag  /SET /    *<A HREF="set.htm">SET</A> *
  6379.     #AutoTag  "set "    ~<A HREF="set.htm">set</A> ~
  6380.  
  6381.     <$IncludeExampleFile FILE="C:\AUTOEXEC.BAT" TEXT='Example file "C:\AUTOEXEC.BAT"'>
  6382.  
  6383. Note that in the example above all existing autotags were cleared before 
  6384. setting our own.  This is restrictive and intelligent use of the 
  6385. "#AutoTagState" command will be more useful. 
  6386.  
  6387.  
  6388. ΓòÉΓòÉΓòÉ 9.6. #AutoTag ΓòÉΓòÉΓòÉ
  6389.  
  6390. #AutoTag 
  6391.  
  6392. This command allows you to automatically modify text.  This is mainly handly 
  6393. when "#AsIs" mode is on and you are including text which you don't wish to 
  6394. modify (such as a real live working module you wish to use as an example). 
  6395.  
  6396. By default the search operation is case sensitive and a simple textual 
  6397. replacement occurs. There are other options such as case insensitive 
  6398. replacements that you can set using the AtChangeType option. 
  6399.  
  6400. When used with the "#AsIs" command  you can include real working code as 
  6401. examples and link parts of this working example to your explanations. 
  6402.  
  6403. Automatic tagging is not recommended for general use as it can greatly decrease 
  6404. performance of this program. 
  6405.  
  6406. AutoTag definitions are applied to lines in the order of declaration in a 
  6407. single pass.  This means that you can make use of common "macro" like tags but 
  6408. they must be defined later than all references.  If AutoTags are used while 
  6409. "#AsIs" mode is off then it can generate references to #define variables and 
  6410. they will be expanded. 
  6411.  
  6412. You can temporarily hide or extend the existing autotag list with the 
  6413. "#AutoTagState" command. You can clear all or some AutoTags with 
  6414. "#AutoTagClear". 
  6415.  
  6416. Only lines that come directly from a file are tagged. Macro contents are safe. 
  6417. Autotagging occurs after any required "#AsIs" tagging. 
  6418.  
  6419. The parameters shown below do not have macros expanded before this command 
  6420. processes them.  This ensures that complex macros can be handled.  The 
  6421. replacement will occur after the autotag text has been replaced. 
  6422.  
  6423. Syntax #1 
  6424.  
  6425.     [WhiteSpace]#AutoTag  ["]OnOrOffCommand["]
  6426.  
  6427. This form of the command turns on or off the automatic tagging of text.  The 
  6428. "OnOrOffCommand" parameter should be "+", "ON" or "YES" to keep leading 
  6429. whitespace otherwise use "-", "OFF" or "NO". 
  6430.  
  6431. Syntax #2 
  6432.  
  6433.     [WhiteSpace]#AutoTag  ["]BeforeText["] [ ["]AfterText["]  [#Slot]]
  6434.  
  6435. The "BeforeText" is translated into "AfterText".  Note that the "AfterText" can 
  6436. contain the "BeforeText" and both can contain absolutely any characters.  If 
  6437. the "AfterText" parameter is missing (not empty) then the first autotag for 
  6438. "BeforeText" is deleted.  Note that "AfterText" can contain the string "{$AT}" 
  6439. which will get replaced with the value of "BeforeText". 
  6440.  
  6441. The optional "Slot" parameter can be used to adjust the ordering of the tag. 
  6442. Normally the new tag is placed after all existing ones, to make it first 
  6443. specify "#1". A tag of "#2" would ensure it's the second change etc. 
  6444.  
  6445. Note that it's perfectly legal and in some cases may be required that you 
  6446. specify the same "BeforeText" more than once. 
  6447.  
  6448. When "#AsIs" mode is on you need to be very careful about what you use as 
  6449. replacement text, for example if you wish to see a '<' character you will 
  6450. actually need to use '<' instead! 
  6451.  
  6452. Example 
  6453.  
  6454. In the following example we are including "C:\AUTOEXEC.BAT" and wish to create 
  6455. hypertext links from the "REM" command to "rem.htm" and from the "SET" command 
  6456. to "set.htm".  Note that I expect  my source to contain "set" or "SET" but not 
  6457. "SeT" etc.  Also note that to eliminate the chance (in this example certainty) 
  6458. of clashes with future #defines I use the text ">$<" to split up the file 
  6459. "set.htm". Also note that I look for "SET" and not "SET ", this is silly as it 
  6460. would also match on "SETTLE" or other similar text and not just "SET" commands 
  6461. which I know need at least one space. 
  6462.  
  6463.     #AutoTagClear
  6464.     #AutoTag  "REM "    '<A HREF="rem.htm">REM</A> '
  6465.     #AutoTag  /SET/    *<A HREF="s><?Dollar><et.htm">SET</A>*
  6466.     #AutoTag  "set"    ~<A HREF="s><?Dollar><et.htm">set</A>~
  6467.     #AutoTag  "><?Dollar><"    ""
  6468.     #AutoTag  ON
  6469.     <$IncludeExampleFile FILE="C:\AUTOEXEC.BAT" TEXT='Example file "C:\AUTOEXEC.BAT"'>
  6470.     #AutoTag  OFF
  6471.  
  6472.  
  6473. ΓòÉΓòÉΓòÉ 9.7. #AutoTagClear ΓòÉΓòÉΓòÉ
  6474.  
  6475. #AutoTagClear 
  6476.  
  6477. This command allows you to clear out unwanted #AutoTags that you probably used 
  6478. to tag a previous sample so as not to interfere with the next one. 
  6479.  
  6480. By default only the current autotag state is cleared so it is possible to be 
  6481. selective about the clearing of tags with intelligent use of the #AutoTagState 
  6482. command. 
  6483.  
  6484. Syntax 
  6485.  
  6486.     [WhiteSpace]#AutoTagClear  [["]ALL["] ]
  6487.  
  6488. If the literal value "ALL" is specified the autotag state is cleared as well as 
  6489. all tags.  The default is to only clear autotags defined in the current state. 
  6490.  
  6491.  
  6492. ΓòÉΓòÉΓòÉ 9.8. #AutoTagState ΓòÉΓòÉΓòÉ
  6493.  
  6494. #AutoTagState 
  6495.  
  6496. This command can be used to create autotag "pools" which can be selectively 
  6497. used and cleared without affecting any previously defined pools.  This allows a 
  6498. self contained macro to create, use and clear autotags and still restore the 
  6499. state so as not to affect the rest of the system. 
  6500.  
  6501. This command also saves and restores whether or not tagging was on. 
  6502.  
  6503. A common use of this command is to temporarily hide all autotags, another is to 
  6504. make a temporary copy then delete one or more tags, perform some tagging and 
  6505. then restore the original state. 
  6506.  
  6507. Syntax 
  6508.  
  6509.     [WhiteSpace]#AutoTagState  ["]Name["]                               OR
  6510.     [WhiteSpace]#AutoTagState  ["]Mode["]   [["]REMEMBER["]]            OR
  6511.     [WhiteSpace]#AutoTagState  ["]+["]       ["]REMEMBER["]|["]Name["]  ...
  6512.  
  6513. It is possible to name a state at any time.  When you increment the state the 
  6514. name will be remembered as the "Name" you supply.  When incrementing to a new 
  6515. state you can copy tags from one or more named states. 
  6516.  
  6517. The "Mode" parameter should be either: 
  6518.  
  6519.        1. "+" 
  6520.           This saves the current state.  By default the new state has no tags 
  6521.           available.  If the literal value "REMEMBER" is also used then the new 
  6522.           state has access to all tags available in the previous state.  You 
  6523.           can also specify one or more previously defined state names to copy 
  6524.           their tags. 
  6525.  
  6526.           Note that if #AutoTagClear is used (without 'ALL') in a state where 
  6527.           "REMEMBER" was also used then this will only clear tags that you have 
  6528.           defined in the current state (not all tags available in that state). 
  6529.  
  6530.        2. "-" 
  6531.           This restores the previous state.  If the literal value "REMEMBER" is 
  6532.           also used then the new (previous) state's tags are replaced with 
  6533.           those currently available. 
  6534.  
  6535.  EXAMPLE 
  6536.  
  6537.       #Autotagstate FirstState                   ;;Name this state
  6538.       #AutoTag      "1"   "one"                  ;;Create a tag
  6539.       #Autotagstate +                            ;;Create new state (no tags available)
  6540.       #Autotagstate SecondState                  ;;Name this state
  6541.       #AutoTag      "2"   "two"                  ;;Create a tag
  6542.       #Autotagstate +  REMEMBER                  ;;Create new state (get access to last states tags)
  6543.       #AutoTag      "2"                          ;;Delete this tag
  6544.       #Autotagstate +                            ;;Create new state (no tags available)
  6545.       #Autotagstate +  FirstState 'SecondState'  ;;Create new state (copy tags from 2 states)
  6546.       #Autotagstate -  REMEMBER                  ;;Go back to previous state (overwriting any tags it might have)
  6547.       #Autotagstate -                            ;;Go back one state (keep that states tags)
  6548.       #Autotagstate -
  6549.       #Autotagstate -
  6550.  
  6551.  
  6552. ΓòÉΓòÉΓòÉ 9.9. #Break ΓòÉΓòÉΓòÉ
  6553.  
  6554. #Break 
  6555.  
  6556. This command is used to exit a PPWIZARD loop (similar to rexx 'leave' loop 
  6557. instruction). 
  6558.  
  6559. Please see the "#{" command for an example and more information. 
  6560.  
  6561.  
  6562. ΓòÉΓòÉΓòÉ 9.10. #Continue ΓòÉΓòÉΓòÉ
  6563.  
  6564. #Continue 
  6565.  
  6566. This command is used to immediately restart a PPWIZARD loop from the top 
  6567. (similar to rexx 'iterate' loop instruction). 
  6568.  
  6569. Please see the "#{" command for an example and more information. 
  6570.  
  6571.  
  6572. ΓòÉΓòÉΓòÉ 9.11. #Debug ΓòÉΓòÉΓòÉ
  6573.  
  6574. #Debug 
  6575.  
  6576. This will turn debug mode on or off.  Debug mode is normally off but can also 
  6577. be turned on with the /debug command line switch. 
  6578.  
  6579. Note that this command will not adjust the debugging mode if the /debug switch 
  6580. was used. 
  6581.  
  6582. The output is fairly easy to understand and aims to actually teach (or help you 
  6583. to understand) certain commands (such as #import). 
  6584.  
  6585. Syntax 
  6586.  
  6587.     [WhiteSpace]#Debug  ["]OnOrOffCommand["]
  6588.  
  6589. The "OnOrOffCommand" should be "+", "ON" or "YES" to turn debug on otherwise 
  6590. use "-", "OFF" or "NO". 
  6591.  
  6592. Example 
  6593.  
  6594.     #debug on
  6595.     ...
  6596.     ...
  6597.     #debug 'no'
  6598.  
  6599.  
  6600. ΓòÉΓòÉΓòÉ 9.12. #define[+|?] ΓòÉΓòÉΓòÉ
  6601.  
  6602. #define[+|?] 
  6603.  
  6604. A #define can be used to define a value (constant) once and then refer to it 
  6605. elsewhere. It allows you to update one place and have all necessary change flow 
  6606. though to all the statements that refer to it. 
  6607.  
  6608. If ppwizard discovers that you are about to redefine an existing variable then: 
  6609.  
  6610.        1. If the command was "#define" a warning is generated. The reason for 
  6611.           this is because it is assumed you did not expect this. You could be 
  6612.           reusing a macro that belongs to someone else (hidden in a header you 
  6613.           use) or you may have made some kind if mistake. 
  6614.  
  6615.        2. If the command was "#define+" then you are expecting to override a 
  6616.           variable and so no warning is generated. I recommend you don't use 
  6617.           this command for general use. 
  6618.  
  6619.        3. If the command was "#define?" then the defintion is aborted. This is 
  6620.           useful in your header files where the user is allowed to override 
  6621.           default values. 
  6622.  
  6623.  For more information on macros and their use please see the macros section. 
  6624.  
  6625.  There are some situations where you may wish to use the #AutoTag facility 
  6626.  instead. The main difference is with a #define'd variable you indicate where 
  6627.  the replacement will occur - if it can't do it the build fails, when using 
  6628.  #AutoTags the replacement occurs automatically but it may not always come out 
  6629.  the way you wish and of course no error if it "fails" (use of #defines is also 
  6630.  very much faster).  I mainly use #AutoTag when I'm including real working code 
  6631.  from a file and I want to created hypertext links or highlight sections.  I 
  6632.  can then quickly change the example without having to worry about having to 
  6633.  retag it. 
  6634.  
  6635.  You should also have a look at the #evaluate command which can do things that 
  6636.  a #define can't. 
  6637.  
  6638.  Note that there are some extreme situations which you will not be able to wrap 
  6639.  up in a #define (or at least easily). As an example of a situation which will 
  6640.  be very difficult (if not impossible) would be to include a reference to a 
  6641.  macro which then uses the #AsIs command, also be careful with #AutoTag. 
  6642.  commands. In these situations you can use a #Include command to perform the 
  6643.  textual replacement. 
  6644.  
  6645.  The DefineMacroReplace option affects how this command works. 
  6646.  
  6647.  Syntax 
  6648.  
  6649.  The syntax of this command is different from most others as it does not accept 
  6650.  quoted strings, the reason for this is to ensure that you can include 'C' 
  6651.  header files with a bit of care (allowing sharing of the common header). 
  6652.  
  6653.       [WhiteSpace]#define[+] Variable  Contents
  6654.  
  6655.  The "Variable" is the name of the macro and when seen in following lines will 
  6656.  be replaced by the contents. If the macro you are creating contains ppwizard 
  6657.  commands then you must use the line continuation characters and place each 
  6658.  ppwizard command on a line of it's own. 
  6659.  
  6660.  The "Contents" is basically the rest of the line and is what is placed into 
  6661.  the output.  This may contain any number of mandatory or optional parameters. 
  6662.  
  6663.  The line containing a #define does not itself have variables substituted. 
  6664.  What this means is that if the "Contents" contains other definitions, the 
  6665.  values of these at the time of use will be used. If this is not what you wish 
  6666.  then use the "#evaluate" to create the definition. 
  6667.  
  6668.  Note that for ppwizard commands (within a #define) to be executed when the 
  6669.  macro is expanded the commands must be on their own line. Please see the multi 
  6670.  line macros section. 
  6671.  
  6672.  I highly recommend that you read the whole section on macros. I get a reason 
  6673.  amount of emails from people who haven't.... 
  6674.  
  6675.  You can redefine a variable if you wish. 
  6676.  
  6677.  Example 1 - No Parameters Used 
  6678.  
  6679.       ;--- #define some standard stuff --------------------------------------------
  6680.       #define Img100%PureJava         <IMG SRC="graphics/java100.gif" ALT="{100% pure Java}" HSPACE=5 VSPACE=10 ALIGN=middle BORDER=0 WIDTH=100 HEIGHT=100>
  6681.       #define ImgFreeIbmVisualAgeJava <IMG                                 \
  6682.                                               SRC="graphics/vaj_free.gif"  \
  6683.                                               ALT="{Free Visual Age Java}" \
  6684.                                               HSPACE=5                     \
  6685.                                               ALIGN=middle                 \
  6686.                                               BORDER=0                     \
  6687.                                               WIDTH=88 HEIGHT=31           \
  6688.                                       >
  6689.       #define ImgBarbedWire           <P><CENTER><IMG SRC="graphics/barbwire.gif"></CENTER>
  6690.  
  6691.       ;--- Now use some #defines -------------------------------------------------
  6692.       <P>Paragraph before barbed wire.
  6693.  
  6694.       <$ImgBarbedWire>
  6695.  
  6696.       <P>Paragraph after barbed wire.
  6697.  
  6698.  Example 2 - Parameters Used 
  6699.  
  6700.       ;--- Define an image -------------------------------------------------------
  6701.       #define AnImage <IMG SRC="graphics/AnImage.gif" WIDTH={$WIDTH} HEIGHT={$HEIGHT}>
  6702.  
  6703.       ;--- Refer to image twice, each with different size ------------------------
  6704.       <P>Image at Size 1 = <$AnImage WIDTH="100" HEIGHT="33">
  6705.       <P>Image at Size 2 = <$AnImage WIDTH='200' HEIGHT=|66|>
  6706.  
  6707.  
  6708.       ;--- Define an image -------------------------------------------------------
  6709.       #define AnImage2 <IMG SRC="graphics/AnImage.gif" {$All}>>
  6710.  
  6711.       ;--- Refer to the image supplying any and all parameters -------------------
  6712.       <P>Image = <$AnImage2 All=/ALT="{An Image}" WIDTH="100" HEIGHT="33"/>
  6713.  
  6714.       ;--- Refer to the image supplying NO parameters ----------------------------
  6715.       <P>Image = <$AnImage2 All="">
  6716.  
  6717.  Example 3 - Contains Logic 
  6718.  
  6719.       ;--- Define a macro that can be used to include my example files -----------
  6720.       #define    IncludeExampleFile                    \
  6721.                  <BR><TABLE BORDER=5 CELLSPACING=5>    \
  6722.                  <TR>                                  \
  6723.                  <TH ALIGN=LEFT>{$TEXT}                \
  6724.                  </TR>                                 \
  6725.                  <TR><TH ALIGN=LEFT>                   \
  6726.                  <PRE>                                 \
  6727.                  <FONT size=-1>                        \
  6728.                  #AsIs    ON                           \
  6729.                  #include "{$FILE}"                    \
  6730.                  #AsIs    OFF                          \
  6731.                  </FONT>                               \
  6732.                  </PRE>                                \
  6733.                  </TR>                                 \
  6734.                  </TABLE>
  6735.  
  6736.       <$IncludeExampleFile FILE="Example.TXT" TEXT='Example file "EXAMPLE.TXT"'>
  6737.  
  6738.  Example 4 - Default Parameters 
  6739.  
  6740.       ;--- Define a stupid macro which defaults some parameters ------------------
  6741.       #define    AMacro /{Parm1}/{Parm2="Default2"}/{Parm3=+Default3+}/
  6742.  
  6743.       ;--- Use the macro ---------------------------------------------------------
  6744.       <$AMacro Parm1='Text1'>
  6745.       <$AMacro Parm1='Text1' Parm2=*Text2*>
  6746.  
  6747.  
  6748. ΓòÉΓòÉΓòÉ 9.13. #DefineRexx[+] ΓòÉΓòÉΓòÉ
  6749.  
  6750. #DefineRexx[+] 
  6751.  
  6752. This command provides a simple way to define multi line/statement rexx code 
  6753. without requiring line continuation characters. This is useful for: 
  6754.  
  6755.        1. Defining rexx code to be executed at some later stage (if not 
  6756.           immediately). 
  6757.  
  6758.        2. Defining a fragment of rexx code which may act much like a 
  6759.           subroutine. 
  6760.  
  6761.        3. Defining rexx code (or fragments) for generating into the rexx 
  6762.           program you are creating (/rexx). 
  6763.  
  6764.  You use this command to define the start and end of a block of rexx code and 
  6765.  anything in between is either rexx code or a ppwizard command. 
  6766.  
  6767.  The fact that ppwizard commands are interpreted while the block is being 
  6768.  processed allows you to use useful commands such as #include or #if to 
  6769.  selectively include or exclude parts of the rexx code (at definition time). To 
  6770.  make decisions at runtime you must use the rexx "if" statement and not the 
  6771.  ppwizard #if command! 
  6772.  
  6773.  Each line of rexx goes through the following processing: 
  6774.  
  6775.        1. The line goes through all normal PPWIZARD processing except symbol 
  6776.           substitution. This means for example that line continuation occurs so 
  6777.           that a "line" that this command sees can actually be made up of many 
  6778.           source lines. 
  6779.  
  6780.        2. All leading and trailing whitespace is removed. 
  6781.  
  6782.        3. A trailing rexx comment if it exists is removed. 
  6783.  
  6784.        4. A trailing ';' is removed if it exists. 
  6785.  
  6786.        5. If the line starts with "$trace" (any case) then if the command: 
  6787.  
  6788.               is "$trace off" then tracing of following code is not allowed. 
  6789.  
  6790.               is "$trace on" then tracing of following code is again allowed. 
  6791.                Note that this command does not turn on $tracing. 
  6792.  
  6793.               is "$trace" then the following command will be traced. 
  6794.  
  6795.               is "$trace SomeText" then the the text will be displayed. 
  6796.  
  6797.  Please see /$Trace for more information and for details on restrictions. If 
  6798.  debug is off then this command will be ignored. 
  6799.  
  6800.        6. Unless you specify otherwise the line is packed and you should be 
  6801.           aware of some of the restrictions involved (described below). Packing 
  6802.           reduces the chance that the rexx interpreter you are using will 
  6803.           reject the code due to clause or line length restrictions. The 
  6804.           packing also means that you can format the code to be easier to read 
  6805.           (since you aren't worried about the extra spacing etc). 
  6806.  
  6807.        7. The line is added to any previously collected (separated with 
  6808.           "<?xRexxEos>"). This seperator string is automatically handled if the 
  6809.           rexx is executed under ppwizard control. If you generate the rexx 
  6810.           code (into the output rexx program) then the default is that it is 
  6811.           converted to a newline. 
  6812.  
  6813.           Note that the end of each rexx line is expected to be the end of a 
  6814.           rexx statement so if a rexx statement spans multiple lines you will 
  6815.           still need to use line continuation on these lines. 
  6816.  
  6817.           Note that if you combine multiple macros generated this way you must 
  6818.           separate them with ';' as this command does not terminate the last 
  6819.           statement. 
  6820.  
  6821.  At the end of the block the complete rexx code may have symbols substituted 
  6822.  depending on how the DefineMacroReplace option is set. 
  6823.  
  6824.  Note that the last line/statement of the block will not be terminated with a 
  6825.  semicolon, if you wish to combine blocks you will need to take this into 
  6826.  account. 
  6827.  
  6828.  Syntax 
  6829.  
  6830.       [WhiteSpace]#DefineRexx[+]  [["]Variable["] ["]NOPACK["] ["]$TRACE["] ["]$TRACE_OFF["]]
  6831.  
  6832.  If the command was "#DefineRexx+" then if a redefine of a variable occurs then 
  6833.  this is considered to be OK and no warnings are generated. 
  6834.  
  6835.  If the Variable parameter is supplied it defines the name of a #define to be 
  6836.  generated with the following lines as their contents. If no parameters are 
  6837.  supplied the rexx code block is completed. 
  6838.  
  6839.  If the Variable parameter is given as "" (empty) then the rexx code is 
  6840.  immediately executed and not saved. When code is executed immediately then any 
  6841.  macro parameters are always replaced. 
  6842.  
  6843.  The "$Trace" option on this command indicates that you wish to trace all rexx 
  6844.  commands in the block. The "$trace_off" command turns off all tracing for the 
  6845.  code. Please see /$Trace for more information and for details on restrictions. 
  6846.  This command is ignored if debug is not on. 
  6847.  
  6848.  The default situation is that rexx code is packed, the optional NOPACK keyword 
  6849.  allows you to prevent this. Some rexx interpreters have trouble with legal 
  6850.  rexx code when excess spaces are removed! Rather than completely disabling all 
  6851.  packing you can also make use of the AllowPack option to selectively prevent 
  6852.  the packing of certain lines. 
  6853.  
  6854.  Use Within Macros 
  6855.  
  6856.  The line by line processing described above can not occur when the rexx code 
  6857.  is being defined within a macro (it sees one line). 
  6858.  
  6859.  I recommend that you do not use this command within a macro definition unless 
  6860.  this command is used for the immediate execution the rexx code. If defining a 
  6861.  macro containing rexx code then there is no reason why it need be imbedded. 
  6862.  
  6863.  You need to end each line with either a ";" or space as appropriate, consider 
  6864.  the following: 
  6865.  
  6866.       #( ''
  6867.          #define EnclosingMacro
  6868.          ...
  6869.  
  6870.          #DefineRexx 'Something'
  6871.              Var1 = ''
  6872.              if (Test) then
  6873.              do
  6874.                 fred = 1
  6875.              end
  6876.          #DefineRexx
  6877.          ...
  6878.       #)
  6879.  
  6880.  The rexx code actually ends up looking like: 
  6881.  
  6882.       Var1 = ''if (Test) thendofred = 1end
  6883.  
  6884.  It was the "#(" command which did this, not the "#DefineRexx" command (it only 
  6885.  sees the one "line"!). 
  6886.  
  6887.  Now to fix it you could ensure a ";" was on each line, in the following I use 
  6888.  a space also (purely for example): 
  6889.  
  6890.       #( ''
  6891.          #define EnclosingMacro
  6892.          ...
  6893.  
  6894.          #DefineRexx 'Something'
  6895.              Var1 = '';
  6896.              if (Test) then        \
  6897.              do;
  6898.                 fred = 1;
  6899.              end;
  6900.          #DefineRexx
  6901.          ...
  6902.       #)
  6903.  
  6904.  Now the line will look like(ignoring any packing that "#DefineRexx" might do: 
  6905.  
  6906.       Var1 = '';if (Test) then do;fred = 1;end
  6907.  
  6908.  Much better! This is valid rexx and so should work! 
  6909.  
  6910.  Debugging 
  6911.  
  6912.  You can turn on rexx's inbuilt tracing by ensuring that you have set the 
  6913.  "REXXTRACE" DebugLevel and setting the "REXXTRACE" macro to an appropriate 
  6914.  value. This tracing does not work well on regina (excellent on OS/2 though). 
  6915.  
  6916.  To simply test a few spots for correct function typically you would use 
  6917.  standard rexx "say" commands like: 
  6918.  
  6919.       say 'About to do stuff, Line = "' || TheLine || '"';
  6920.  
  6921.  A better method to do the same thing is to use the "$trace" facility, the 
  6922.  command would now look like: 
  6923.  
  6924.       $trace About to do stuff
  6925.  
  6926.  The above "$trace" would display the string and dump the contents of all known 
  6927.  variables. It would also be possible to set breakpoints and the values at the 
  6928.  end of the execution of the rexx code also get displayed. 
  6929.  
  6930.  Now you can also turn on "$trace mode" where $trace commands are automatically 
  6931.  added to each line however you should read about the (reasonable) restrictions 
  6932.  you should follow when formatting your code. 
  6933.  
  6934.  MORE ON PACKING 
  6935.  
  6936.  The preprocessor packs well written code (by my definition!) and can fail to 
  6937.  correctly pack code where strings are appended without the use of the "||" 
  6938.  operator (as the excess spaces will be removed).  For example the following 
  6939.  statement will not create the string you expect when packed: 
  6940.  
  6941.          BothPartsCombined = 'Value:'   TheValue;
  6942.  
  6943.  The following statement is a version of the above that will work: 
  6944.  
  6945.           BothPartsCombined = 'Value:   ' || TheValue;
  6946.  
  6947.  Note that PPWIZARD may not be able to correctly pack lines that refer to macro 
  6948.  variables such as in the following: 
  6949.  
  6950.       #DefineRexx ValidateUrlR_REXX_Location
  6951.                   #Option PUSH AllowPack=NO
  6952.                   do  IncIndex = 1 to <?IncludeLevel>  ;;This line can't be packed
  6953.                   #Option POP
  6954.                      ;--- Format the input file at this level ---
  6955.                      ThisBit = _filespec('name', InputComponentLevel(IncIndex));
  6956.                      ThisBit = ThisBit || '(' || AddCommasToDecimalNumber(InputComponentLineLevel(IncIndex)) || ')';
  6957.  
  6958.                      ;--- Update location string ----------------
  6959.                      if  IncIndex = 1 then
  6960.                          UrlSourceLocation = ThisBit;
  6961.                      else
  6962.                          UrlSourceLocation = UrlSourceLocation || '->' || ThisBit;
  6963.                   end
  6964.       #DefineRexx
  6965.  
  6966.  The reason for the failure to pack (without the #option commands) in this 
  6967.  circumstance is that the rexx code is not valid until the substitution has 
  6968.  taken place, this confuses the packing logic (it is not packing "pure" rexx 
  6969.  code). 
  6970.  
  6971.  EXAMPLE 
  6972.  
  6973.       #DefineRexx  SomeRexxCode $trace
  6974.                    ;--- Comment to be removed (as are blank lines) ---
  6975.                    $trace   At start of rexx code
  6976.                    RexxVar1 = strip(GetEnv('PATH'));
  6977.  
  6978.                    /*--- This rexx comment will also be removed ----*/
  6979.                    RexxVar2 = '[' || 'stuff';  /*This rexx comment gets removed*/
  6980.  
  6981.                    ;--- Lets not pack the following rexx code ---
  6982.                    #option PUSH AllowPack=OFF
  6983.                    BothPartsCombined = 'Value:'   TheValue;
  6984.                    #option POP
  6985.  
  6986.                    ;--- Gets some code from a file ---
  6987.                    #include "SomeRexx.X"
  6988.       #DefineRexx
  6989.       #evaluate   ^^  ^<$SomeRexxCode>^
  6990.  
  6991.  You could also have a look at the PPWSORT.H header file as a further example. 
  6992.  
  6993.  
  6994. ΓòÉΓòÉΓòÉ 9.14. #DependsOn ΓòÉΓòÉΓòÉ
  6995.  
  6996. #DependsOn 
  6997.  
  6998. This command can be used to indicate a dependancy that is not obvious to 
  6999. PPWIZARD. All input and output files seen by PPWIZARD are automatically taken 
  7000. care of but there may be instances where you might need to indicate other 
  7001. files. 
  7002.  
  7003. As an example of an INPUT dependancy, you might have a macro which reads parts 
  7004. of CONFIG.SYS (only you know why!) using the rexx linein() function, because 
  7005. your generated output is dependant on the contents of CONFIG.SYS you will wish 
  7006. to rebuild if the file changes. 
  7007.  
  7008. As an example of an OUTPUT dependancy, you might not wish to use the #output 
  7009. command and therefore directly write to files using a rexx "lineout()" 
  7010. function. 
  7011.  
  7012. A file input dependancy should be defined before the file is used as this 
  7013. ensures that ppwizard can detect changes to the input file even while it is 
  7014. executing. It does not matter when an output dependancy is defined as the 
  7015. timestamp is only read at completion. 
  7016.  
  7017. If /DependsOn was not specified then the command is ignored. 
  7018.  
  7019. Syntax 
  7020.  
  7021.     [WhiteSpace]#DependsOn  ["]DepType["]  ["]StampWhat1["]  ...
  7022.  
  7023. The "DepType" parameter indicates should be one of: 
  7024.  
  7025.          INPUT 
  7026.           The following information is an input dependancy. Note that PPWIZARD 
  7027.           can look at other things and not just input files (as explained 
  7028.           below). The rexx AddInputFileToDependancyList() routine can also be 
  7029.           used. 
  7030.  
  7031.          OUTPUT 
  7032.           The following file(s) are output (target) file dependancies. The rexx 
  7033.           AddOutputFileToDependancyList() routine can also be used. 
  7034.  
  7035.          TEMP 
  7036.           The following file(s) are temporary files and should be ignored. This 
  7037.           must be used before a file is marked as an input or output 
  7038.           dependancy. The rexx AddTempFileToDependancyList() routine can also 
  7039.           be used. 
  7040.  
  7041.  A rebuild or your target files is required if there are any input files which 
  7042.  have a later date/time than any of your output files. A rebuild is also forced 
  7043.  if an input or output file can't be located. 
  7044.  
  7045.  The "StampWhat" parameter(s) are usually the names of files that should be 
  7046.  added to the dependancy list. It is not an error (just time consuming) to 
  7047.  specify the same item more than once. Normally a files date and time is used 
  7048.  for the "stamp" however if the parameter (for an INPUT dependancy) starts with 
  7049.  '*' then this has special meaning as follows: 
  7050.  
  7051.          *CmdLine 
  7052.           Use this to indicate that you wish ppwizard to examine the command 
  7053.           line switches (masks ignored). If different switches were used then a 
  7054.           remake is required. This dependancy is on by default (see the 
  7055.           /DependsOnComplete switch). 
  7056.  
  7057.          *Exec=CommandLine 
  7058.           This allows a you to process any command that can be typed at a 
  7059.           command line. Its redirected output, stripped of carriage return, 
  7060.           Line Feed and End Of File characters is used as the "stamp". 
  7061.  
  7062.          *Expires=When 
  7063.           This indicates that at some time in the future you wish to force a 
  7064.           rebuild. The "When" parameter has the same syntax as the offset 
  7065.           passed to the TimeStamp() routine except that you can use "NOW" to 
  7066.           represent 0 (always rebuild). 
  7067.  
  7068.          *Files=[+]FileMask 
  7069.           This allows a list of files matching a mask to be stamped in one hit. 
  7070.           Unlike simple stamping of individual files this uses the mask to 
  7071.           determine differences so it will detect file additions and not just 
  7072.           deletions and modifications to already known files. For example 
  7073.           "*Files=+E:\DB\URLS\*.*" will stamp all files in the directory, and 
  7074.           since "+" was used will also process those in it's subdirectories. 
  7075.  
  7076.          *PpwPgm 
  7077.           Use this to indicate that you wish ppwizard to rebuild if the version 
  7078.           of ppwizard changes in any way. This dependancy is on by default (see 
  7079.           the /DependsOnComplete switch). 
  7080.  
  7081.          *Rexx=Expression(s) 
  7082.           This allows a you to process some rexx and return a value. The value 
  7083.           to be used should be returned in the rexx variable DepValue, if your 
  7084.           rexx code does not include "DepValue" (any case) then it is assumed 
  7085.           to be a single rexx expression which can safely be assigned to that 
  7086.           variable. 
  7087.  
  7088.           One good example of how to use this is where your build depends on 
  7089.           the value of an environment variable (although in this case a "*Exec" 
  7090.           of the "set" command would also work in most operating systems). 
  7091.  
  7092.          *Today 
  7093.           Use this to indicate that you do not need a rebuild today but you 
  7094.           would tomorrow. One example of why you might want to do this is my 
  7095.           DLCNTR ppwizard add-on where it marks "new" downloads if they are 
  7096.           recent, I need to check if recent every day. 
  7097.  
  7098.  Example 1 - Two files specified 
  7099.  
  7100.       #DependsOn  INPUT   "C:\CONFIG.SYS"   "C:\STARTUP.CMD"
  7101.  
  7102.  Example 2 - Assorted Commands 
  7103.  
  7104.       #DependsOn INPUT '*TODAY'        ;;Rebuild tomorrow
  7105.       #DependsOn INPUT '*EXPIRES=1w'   ;;Rebuild in another week
  7106.       #DependsOn INPUT '*EXPIRES=3H'   ;;rebuild in 3 hours
  7107.       #DependsOn INPUT '*EXPIRES=NOW'  ;;Must always rebuild
  7108.       #dependson INPUT "*CMDLINE"      ;;If command line switches change
  7109.       #dependson INPUT "*PpWPGM"       ;;If ppwizard program changes in any way
  7110.       #dependson INPUT ^*Rexx=getenv('ppwizard_include')^ ;;If the environment variable changes
  7111.  
  7112.  Example 3 - Real life macro 
  7113.  
  7114.      ;--- Outputs the size of a file (takes parameter "File") --------------------
  7115.      #define SizeOfFile                                                                                                         \
  7116.              #evaluate+  LocalFileName    ^ReplaceString("../{$File}", "/", "\")^                                               \
  7117.              #DependsOn  INPUT            "<$LocalFileName>"                                                                    \
  7118.              #evaluate+  TmpFileSize      ^AddCommasToDecimalNumber(stream("<$LocalFileName>", "c", "query size"))^             \
  7119.              #if "<$TmpFileSize>" = ""                                                                                          \
  7120.                  #error $Failed getting size of "<$LocalFileName>"$                                                             \
  7121.              #endif                                                                                                             \
  7122.              <$TmpFileSize>
  7123.      #define SizeOfFileInSmallFont   <FONT SIZE=-1>{$Before=""}<$SizeOfFile File=*{$File}*> bytes{$After=""}</FONT>
  7124.      #define (SizeOfFileInSmallFont) <$SizeOfFileInSmallFont File=*{$File}* Before='(' After=')'>
  7125.  
  7126.  
  7127. ΓòÉΓòÉΓòÉ 9.15. #elseif ΓòÉΓòÉΓòÉ
  7128.  
  7129. #elseif 
  7130.  
  7131. This command is used if you wish to have some lines included when the #if 
  7132. condition is false. 
  7133.  
  7134.  
  7135. ΓòÉΓòÉΓòÉ 9.16. #endif ΓòÉΓòÉΓòÉ
  7136.  
  7137. #endif 
  7138.  
  7139. This command is used to terminate a previous #if command.  There should be a 
  7140. matching #endif for every #if command. 
  7141.  
  7142.  
  7143. ΓòÉΓòÉΓòÉ 9.17. #EOF ΓòÉΓòÉΓòÉ
  7144.  
  7145. #EOF 
  7146.  
  7147. This command marks where processing of the current file should be stopped. 
  7148. Anything after this command can be in any format as it's never read. 
  7149.  
  7150. This command is ignored if it appears in an #imported file. 
  7151.  
  7152. Syntax 
  7153.  
  7154.     [WhiteSpace]#EOF  [["]EndifCount["]]
  7155.  
  7156. The "EndifCount" parameter is optional and may be required if you wish to use 
  7157. the #EOF command conditionally.  The number should normally match the nesting 
  7158. level within the file. 
  7159.  
  7160.  
  7161. ΓòÉΓòÉΓòÉ 9.18. #evaluate[+] ΓòÉΓòÉΓòÉ
  7162.  
  7163. #evaluate[+] 
  7164.  
  7165. This command will execute a rexx command line. The result of this command can 
  7166. be stored into a "#define" variable. If the command was "#evaluate+" then if a 
  7167. redefine of a variable occurs then this is considered to be OK and no warnings 
  7168. are generated. For more information on macros and their use please see the 
  7169. macros section. 
  7170.  
  7171. You would use this command (over #define) for one of the following main 
  7172. reasons: 
  7173.  
  7174.        1. You wish to get some some data from rexx.  Any standard rexx 
  7175.           functions (or your own as ".CMD") can be used.  If you are frequently 
  7176.           calling your own routine for performance you may wish to look at the 
  7177.           #MacroSpace command. 
  7178.  
  7179.        2. You wish to perform arithmetic or other similar operation. 
  7180.  
  7181.        3. You wish the macros contents to have leading or trailing whitespace. 
  7182.  
  7183.        4. You wish to get some information out of the environment (contents of 
  7184.           environment variables, information from text or INI files etc). 
  7185.  
  7186.  The #evaluate command will handle syntax errors and unknown variables, dumping 
  7187.  what it knows and then aborting the preprocessing. 
  7188.  
  7189.  It is recommended that you read the performance documentation as this command 
  7190.  is much slower than some other alternatives which you can use in some 
  7191.  circumstances (such as the #define command). 
  7192.  
  7193.  Syntax 
  7194.  
  7195.       [WhiteSpace]#evaluate[+]  ["]Variable["]  [']Expression[']
  7196.  
  7197.  The "Variable" parameter is the name of the macro you wish created or updated. 
  7198.  This parameter is optional if you don't wish to use the result as text in your 
  7199.  HTML.  If supplied the result of the "Expression" is assigned to the macro 
  7200.  specified. 
  7201.  
  7202.  The "Expression" parameter is executed by rexx. It is highly recommended that 
  7203.  for all but trivial amounts of rexx code that you define the rexx code with 
  7204.  the #DefineRexx command. 
  7205.  
  7206.  As well as supporting all standard rexx functions and any ".CMD" you care to 
  7207.  write yourself there are many ppwizard defined Rexx Extensions that you can 
  7208.  make use of. 
  7209.  
  7210.  EXAMPLE #1 
  7211.  
  7212.       ;--- Get current date ------------------------------------------------------
  7213.       #evaluate TodaysDate      "date('WeekDay') || ' ' || date('Normal')"
  7214.  
  7215.  EXAMPLE #2 
  7216.  
  7217.       ;--- Get SHORT name of Generated HTML file ---------------------------------
  7218.       #evaluate ShortNameHtml   "_filespec('name', '<?OutputFile>')"
  7219.  
  7220.  EXAMPLE #3 
  7221.  
  7222.       ;--- Beep and then generate first 3 lines of CONFIG.SYS into HTML ----------
  7223.       #evaluate ""                "call beep 1000, 800"
  7224.       #evaluate ""                'File2Read = "C:\CONFIG.SYS"'
  7225.       #evaluate ""                "CloseFileRc = stream(File2Read, 'c', 'close')"
  7226.       #evaluate "ConfigSysLine1"  "linein(File2Read, 1)"
  7227.       #evaluate "ConfigSysLine2"  "linein(File2Read)"
  7228.       #evaluate "ConfigSysLine3"  /linein(File2Read)/
  7229.       #evaluate ||                /CloseFileRc = stream(File2Read, 'c', 'close')/
  7230.       <$ConfigSysLine1><BR>
  7231.       <$ConfigSysLine2><BR>
  7232.       <$ConfigSysLine3><BR>
  7233.  
  7234.  
  7235. ΓòÉΓòÉΓòÉ 9.19. #Error ΓòÉΓòÉΓòÉ
  7236.  
  7237. #Error 
  7238.  
  7239. This command allows you to halt processing and display an error message to 
  7240. explain the problem. 
  7241.  
  7242. The #Warning command is similar but does not halt processing. 
  7243.  
  7244. Syntax 
  7245.  
  7246.     [WhiteSpace]#error  [']ErrorMessage[']
  7247.  
  7248. The "ErrorMessage" specifies the text to be displayed. The text can contain 
  7249. "{NL}" to cause a line break. 
  7250.  
  7251. Example 
  7252.  
  7253.     #if GetEnv('FRED') <> 1 & GetEnv('FRED') <> 2
  7254.         #error "Invalid value for variable 'FRED'"
  7255.     #endif
  7256.  
  7257.  
  7258. ΓòÉΓòÉΓòÉ 9.20. #if ΓòÉΓòÉΓòÉ
  7259.  
  7260. #if 
  7261.  
  7262. A #if command (like #ifdef and #ifndef) can be used to conditionally include 
  7263. lines of text, this can be any other type of line or command except #elseif or 
  7264. #endif. As an example of its use, #if allows you to examine the machine it is 
  7265. running on (for example its environment variables) and generate the appropriate 
  7266. code. 
  7267.  
  7268. #if commands can be nested to any level and there need not be any lines between 
  7269. a #if and a #endif or #elseif command. 
  7270.  
  7271. There are two forms of this command.  The second exists only to speed up the 
  7272. performance, it supplies a small subset of the full functionality but is very 
  7273. much faster. 
  7274.  
  7275. Syntax #1 - Full Functionality (but slower) 
  7276.  
  7277.     [WhiteSpace]#if  ValidRexxCondition
  7278.  
  7279. The "ValidRexxCondition" specifies a valid rexx conditional test which results 
  7280. in a TRUE or FALSE answer.  The condition may be as complex as you wish and may 
  7281. include the special GetEnv() function (or many others) to obtain information 
  7282. from the environment.  For complex logic an external rexx script could be 
  7283. called, these can return numeric or text return codes. 
  7284.  
  7285. Syntax #2 - Partial Functionality (but fast) 
  7286.  
  7287. It is recommended that this form be used where possible if you have many tests 
  7288. in your code, if you only have a few you probably don't need to bother.  This 
  7289. form does a single compare between two simple values.  The square brackets 
  7290. surrounding the compare are used to indicate that this form is supplied by the 
  7291. user. 
  7292.  
  7293.     [WhiteSpace]#if  [Value1  Operator  Value2]
  7294.  
  7295. The "Operator" parameter should have whitespace to either side and be one of 
  7296. the following: 
  7297.  
  7298.        1. == Strict compare for equal. 
  7299.        2. = Compare for equal. 
  7300.        3. <> Compare for not equal. 
  7301.        4. < Less than. 
  7302.        5. > Greater than . 
  7303.        6. <= Less than or equal. 
  7304.        7. >= Greater than or equal. 
  7305.  
  7306.  The Value1 & Value2 parameters can be one of the following: 
  7307.  
  7308.          A rexx number. 
  7309.          A rexx variable. 
  7310.          A rexx literal. 
  7311.  
  7312.  Example #1 
  7313.  
  7314.       ;--- Don't not display following graphics on works INTRANET! ----------------
  7315.       #if translate(GetEnv("PRJSRCDIR")) = "E:\DB\PROJECTS\HOMEPAGE"
  7316.           <CENTER><IMG SRC="graphics/fatguy.gif" BORDER=0 WIDTH=182 HEIGHT=181></CENTER>
  7317.       #endif
  7318.  
  7319.  Example #2 
  7320.  
  7321.       #define StupidExampleMacro                                                             \
  7322.               <P>Hi, my name is Dennis Bareis and I have been using OS/2 and developing for  \
  7323.               #if ['<$AtWork>' = 'Y']                                                        \
  7324.                  ANZ                                                                         \
  7325.               elseif                                                                         \
  7326.                  *WRONG INC*                                                                 \
  7327.               endif                                                                          \
  7328.               on and off since the original 1.0 version.
  7329.  
  7330.  
  7331. ΓòÉΓòÉΓòÉ 9.21. #ifdef ΓòÉΓòÉΓòÉ
  7332.  
  7333. #ifdef 
  7334.  
  7335. A #ifdef command (like #if and #ifndef) can be used to conditionally include 
  7336. lines of text, this can be any other type of line or command except #elseif or 
  7337. #endif. 
  7338.  
  7339. #if commands can be nested to any level and there need not be any lines between 
  7340. a #if command and a #endif or #elseif command. 
  7341.  
  7342. Note that this command only checks on a single variable, for more complex 
  7343. requirements you will need to use a #if command along with calls to the 
  7344. Defined() routine. For performance reasons it is recommended that you use 
  7345. #ifdef and #ifndef commands where possible. 
  7346.  
  7347. A common use of this command is as a method of creating block comments. Simply 
  7348. specify a variable you know does not exist! 
  7349.  
  7350. Syntax 
  7351.  
  7352.     [WhiteSpace]#ifdef  VariableName
  7353.  
  7354. The "VariableName" specifies a variable that should exist for the test to 
  7355. evaluate to true. 
  7356.  
  7357. Example #1 
  7358.  
  7359.     #define Fred FredsValue
  7360.     #ifdef Fred
  7361.         ...
  7362.     #endif
  7363.  
  7364. Example #2 - Block Comment 
  7365.  
  7366.     #ifdef DoesNotExist
  7367.            <P>This paragraph
  7368.            has been commented out
  7369.            as we are testing for
  7370.            a variable we
  7371.            know does not exist.
  7372.     #endif
  7373.  
  7374.  
  7375. ΓòÉΓòÉΓòÉ 9.22. #ifndef ΓòÉΓòÉΓòÉ
  7376.  
  7377. #ifndef 
  7378.  
  7379. A #ifndef command (like #if and #ifdef) can be used to conditionally include 
  7380. lines of text, this can be any other type of line or command except #elseif or 
  7381. #endif. 
  7382.  
  7383. #if commands can be nested to any level and there need not be any lines between 
  7384. a #if command and a #endif or #elseif command. 
  7385.  
  7386. Note that this command only checks on a single variable, for more complex 
  7387. requirements you will need to use a #if command along with calls to the 
  7388. Defined() routine. For performance reasons it is recommended that you use 
  7389. #ifdef and #ifndef commands where possible. 
  7390.  
  7391. Syntax 
  7392.  
  7393.     [WhiteSpace]#ifndef  VariableName
  7394.  
  7395. The "VariableName" specifies a variable that should NOT exist for the test to 
  7396. evaluate to true. 
  7397.  
  7398. Example 
  7399.  
  7400.     #define Fred FredsValue
  7401.     #ifndef Fred
  7402.         ...
  7403.     #endif
  7404.  
  7405.  
  7406. ΓòÉΓòÉΓòÉ 9.23. #import ΓòÉΓòÉΓòÉ
  7407.  
  7408. #import 
  7409.  
  7410. Many programs and databases (Microsoft Excel or Access, Lotus 123 etc) allow 
  7411. you to export data in many different formats. The #import command allows you to 
  7412. import the most common formats and generate output to your specification. 
  7413.  
  7414. The default output format for quite a few of the import types is a HTML table. 
  7415. Not only don't you need to generate a table at all, you also have a lot of fine 
  7416. tuning parameters if you wish to remain with a table but just wish to tweek its 
  7417. look (give certain columns a special background color etc). I have seen people 
  7418. generate a whole series of #define and #include commands to generate a separate 
  7419. html page for each record (from a product database). 
  7420.  
  7421. This command might seem complicated at first (and in actual fact it is!), I 
  7422. recommend you actually try the examples (cut and paste as required). 
  7423.  
  7424. If you are having problems working out what is going on I highly recommend the 
  7425. use of debugging (/debug or #debug) as this has been designed not just for 
  7426. debugging but for training as well. Note I recommend that if debugging you cut 
  7427. your database down to a few test records so that you won't be swamped with 
  7428. output. 
  7429.  
  7430. Import Processing Details 
  7431.  
  7432. All import types get handled in two distinct passes as follows: 
  7433.  
  7434.        1. The imported file is read, processed (including calls to your rexx 
  7435.           filter code if defined) and the output is generated to a temporary 
  7436.           file. 
  7437.  
  7438.           If you have a filter then in some advanced applications you may need 
  7439.           to use the WriteLineToTmpImportFile() routine. An example of this is 
  7440.           if you wished to generate PPWIZARD commands such as #output. 
  7441.  
  7442.        2. The temporary file is read in and processed in exactly the same 
  7443.           manner as any file that you yourself might include with a #include 
  7444.           command. This is where any macros you may have referenced are 
  7445.           expanded. 
  7446.  
  7447.           By default, if debug is not on then after pass two completes the 
  7448.           temporary file is deleted. Turn debug on and examine the temporary 
  7449.           file if things are not going to plan! This will tell you at which of 
  7450.           the 2 stages your import is failing to work correctly. 
  7451.  
  7452.  Syntax 
  7453.  
  7454.       [WhiteSpace]#import  ["]File2Import["]  ["]T2H|WRAP["]  ["]DefineName["]    OR
  7455.       [WhiteSpace]#import  ["]File2Import["]  ["]ImportType[-]["]  ["]DefineName["]  ["]FieldInfo1["]  ...
  7456.  
  7457.  The parameters are as follows: 
  7458.  
  7459.        1. File2Import 
  7460.           This is the name of the file to be imported.  Blank lines are ignored 
  7461.           (is this causing anyone problems?). 
  7462.  
  7463.        2. ImportType 
  7464.           This describes the format of the data to be imported.  If the type 
  7465.           has "-" appended then the first lines of the file are dropped 
  7466.           (default is one line). The currently supported types are: 
  7467.  
  7468.               SQL 
  7469.                PPWIZARD can perform any SQL query you like and process the 
  7470.                resulting rows. 
  7471.               CMA[-] 
  7472.                All fields are comma delimited (fields can't contain commas 
  7473.                unless quoted). Fields may be empty. Blank trailing fields may 
  7474.                be missing. 
  7475.               TAB[-] 
  7476.                As above except a tab (ascii 9) is the delimiter. 
  7477.               ???[-] 
  7478.                As above except you specify the exact delimiter you want. For 
  7479.                example "^^^" indicates that you wish a delimiter of "^". 
  7480.               FIX[-] 
  7481.                Unlike all previous types there is no delimiter.  Items appear 
  7482.                in fixed columns in the file.  While you can play with 
  7483.                "FieldInfo" there is not much point as you can specify all the 
  7484.                fields you want in the order you want them. 
  7485.               ML 
  7486.                Each record spans multiple lines and ends with a blank line. 
  7487.                Each field takes up a line and specifies a field name and a 
  7488.                value separated by a user defined delimiter ('=' by default). 
  7489.               T2H 
  7490.                This is a text to HTML type import. 
  7491.               WRAP 
  7492.                This is a specialised import facility. You get passed a line at 
  7493.                a time and you decide how to handle it. 
  7494.  
  7495.        3. DefineName 
  7496.           This parameter gives you a lot of control over how your output is 
  7497.           generated.  The value you supply here is used as a prefix for all 
  7498.           your import options. As an example, if you specified "FRED" as a 
  7499.           value then some import types would look for a #define of 
  7500.           "FRED_DROP_BLANK_LINES" to see if you wished to override the default 
  7501.           handling of blank lines. 
  7502.  
  7503.           The exact #define options which are available will differ depending 
  7504.           on the import type. If you specified a blank value for the prefix a 
  7505.           default is used.  The name of the default also varies with import 
  7506.           type but for the common types is "IMPORT". 
  7507.  
  7508.           In some cases such as when HTML tables are generated there are 
  7509.           multiple levels of defaults and changing a lower level one may have 
  7510.           no effect if you also override a higher one.  This is because the 
  7511.           lower level values became the default values for the higher level. As 
  7512.           an example there is no point specifying that record columns should 
  7513.           have a background color of green and then overriding the record 
  7514.           generation default!  Again the use of debugging support will 
  7515.           generally make this clear as it will show PPWIZARD looking for all 
  7516.           options and display the value PPWIZARD has decided to use. 
  7517.  
  7518.  
  7519. ΓòÉΓòÉΓòÉ 9.23.1. #import - Delimited Records ΓòÉΓòÉΓòÉ
  7520.  
  7521. #import - Delimited Records 
  7522.  
  7523. This type of #Import has clearly defined fields. You would frequently wish to 
  7524. display these in a table (say in a HTML page) however nothing says that you 
  7525. need to do so. If you wish to create macros and then #include a template file 
  7526. then that is also possible. 
  7527.  
  7528. Within a record the fields are delimited by a single character such as a tab or 
  7529. comma. 
  7530.  
  7531. Note that under Windows you have the option of reading these sorts of files via 
  7532. ODBC and therefore you can use an SQL import! This gives you greater control 
  7533. without extra coding such as controlling sorting the data or only choosing 
  7534. records that match certain criteria (as per normal SQL query syntax). 
  7535.  
  7536. Field Information Parameters 
  7537.  
  7538. On these types of imports "FieldInfo" follows the "DefineName" parameter on the 
  7539. #import command line. 
  7540.  
  7541. You must specify field information for each field up to the last one you are 
  7542. interested in. The field information is of the format: 
  7543.  
  7544.   [{NewColumn}]TitleText 
  7545.  
  7546. The optional "NewColumn" specifies the column you wish the field to be moved 
  7547. to.  This need only be supplied if you wish to change the order, by default the 
  7548. first field is column 1 etc. 
  7549.  
  7550. The "title text" specifies the value for the field in the header record. A 
  7551. blank "title" is used to indicate that we don't require a field and it should 
  7552. be dropped. 
  7553.  
  7554. DEFINITIONS/OPTIONS 
  7555.  
  7556. If you can't understand how these options work then I suggest you try using 
  7557. /debug or #debug to watch what variables the import uses etc. 
  7558.  
  7559.          DefineName_BLANK_FIELD 
  7560.           Normally a blank field will be displayed as blank. You may wish to 
  7561.           display '-' instead. Another possiblity is to display a 1 by 1 
  7562.           transparent gif so as to have table borders around blank fields look 
  7563.           better. 
  7564.  
  7565.           For even more control (probably rare requirement): 
  7566.  
  7567.             -  DefineName_BLANK_COLUMN_? 
  7568.                This allows you to specify different blank replacement values 
  7569.                for each column. 
  7570.  
  7571.          DefineName_DROP_BLANK_LINES 
  7572.           You can specify whether or not blank lines (or lines where all fields 
  7573.           are blank) are significant.  The default is 'Y' to drop blank lines, 
  7574.           specify 'N' to prevent this. 
  7575.  
  7576.          DefineName_NEWLINE_CHAR 
  7577.           This can be used to determine what newlines within fields should be 
  7578.           replaced with ("<BR>" by default). 
  7579.  
  7580.          DefineName_TAB_CHAR 
  7581.           Normally tabs are ignored by the import process.  This variable 
  7582.           allows you to replace them with something else. 
  7583.  
  7584.          DefineName_ASIS_TAGGING 
  7585.           This option can be used to adjust the conversion of what may be 
  7586.           problem characters (such as '<' in HTML). By default importing does 
  7587.           not handle/convert international characters such as umlauts to html 
  7588.           symbols but there is nothing preventing you from doing so. 
  7589.  
  7590.           This definition lists zero, one or more names as used on previous 
  7591.           "#AsIs SETUP" commands (seperated by whitespace). Clear this 
  7592.           definition to prevent all ASIS conversions. 
  7593.  
  7594.           Note that you will probably need to override this value (maybe others 
  7595.           as well) if you wished to expand any macros that the imported data 
  7596.           might contain (by default this is not done). 
  7597.  
  7598.          DefineName_DROP_LINE_COUNT 
  7599.           If we are dropping lines (TAB- command etc), then how many should be 
  7600.           dropped.  The default is one. 
  7601.  
  7602.          DefineName_BEFORE 
  7603.           You would probably only use this define if you didn't want to 
  7604.           generate a table at all. You may specify the string "{$Columns}" 
  7605.           which will get replaced with the number of fields to be displayed. If 
  7606.           this define is not used then you can use the following: 
  7607.  
  7608.             -  DefineName_TABLE_ATTRIBS 
  7609.                This value allows you to specify all HTML attributes of the 
  7610.                table apart from the number of columns. 
  7611.  
  7612.          DefineName_HEADER 
  7613.           This is used to control the "code" which handles the "heading" 
  7614.           record, <B>this does not have to be a html table</B>. You can specify 
  7615.           the string {$Column?} to represent a fields value (? = number of 
  7616.           field where 1 is the first). 
  7617.  
  7618.           If this define is not used then you can use the following: 
  7619.  
  7620.             -  DefineName_HEADING_COLUMNS 
  7621.                This value allows you to specify the column (HTML "<TH>" tags) 
  7622.                information to change alignment or colours of columns. This 
  7623.                value becomes the default for all columns. 
  7624.  
  7625.             -  DefineName_HEADING_COLUMN_? 
  7626.                This value allows you to specify the column (HTML "<TH>" tags) 
  7627.                information to change alignment or colours of specific columns. 
  7628.                Another use for this would be to specify the width of a column. 
  7629.                This value is only used for column number '?'. 
  7630.  
  7631.             -  DefineName_HEADING_BEFORE_DATA 
  7632.                This value allows you to specify some text to be placed in front 
  7633.                of the fields data, for example if you wish to change the font 
  7634.                size for each column you might used the value "<FONT SIZE=-1>". 
  7635.                This value becomes the default for all columns. 
  7636.  
  7637.             -  DefineName_HEADING_BEFORE_DATA_? 
  7638.                This value allows you to specify leading data on a column by 
  7639.                column basis. 
  7640.  
  7641.             -  DefineName_HEADING_AFTER_DATA 
  7642.                This value allows you to specify some text to be placed after 
  7643.                the fields data, for example if you wish to change the font size 
  7644.                for each column you might used the value "</FONT>" to close the 
  7645.                previous font tag. This value becomes the default for all 
  7646.                columns. 
  7647.  
  7648.             -  DefineName_HEADING_AFTER_DATA_? 
  7649.                This value allows you to specify trailing data on a column by 
  7650.                column basis. 
  7651.  
  7652.          DefineName_RECORD 
  7653.           This is used to control the "code" for each record, <B>this does not 
  7654.           have to be a html table</B>. You would definately define this option 
  7655.           if you didn't want a html table, you might wish to create s series of 
  7656.           #defines or maybe you are not generating html at all and need to 
  7657.           generate an IPF table. You can specify the string {$Column?} to 
  7658.           represent a fields value (? = number of field where 1 is the first). 
  7659.  
  7660.           If this define is not used then you can use the following: 
  7661.  
  7662.             -  DefineName_RECORD_COLUMNS 
  7663.                This value allows you to specify the column (HTML "<TD>" tags) 
  7664.                information to change alignment or colours of columns. This 
  7665.                value becomes the default for all columns. 
  7666.  
  7667.             -  DefineName_RECORD_COLUMN_? 
  7668.                This value allows you to specify the column (HTML "<TD>" tags) 
  7669.                information to change alignment or colours of specific columns. 
  7670.                Another use for this would be to specify the width of a column. 
  7671.                This value is only used for column number '?'. 
  7672.  
  7673.             -  DefineName_RECORD_BEFORE_DATA 
  7674.                This value allows you to specify some text to be placed in front 
  7675.                of the fields data, for example if you wish to change the font 
  7676.                size for each column you might used the value "<FONT SIZE=-1>". 
  7677.                This value becomes the default for all columns. 
  7678.  
  7679.             -  DefineName_RECORD_BEFORE_DATA_? 
  7680.                This value allows you to specify leading data on a column by 
  7681.                column basis. 
  7682.  
  7683.             -  DefineName_RECORD_AFTER_DATA 
  7684.                This value allows you to specify some text to be placed after 
  7685.                the fields data, for example if you wish to change the font size 
  7686.                for each column you might used the value "</FONT>" to close the 
  7687.                previous font tag. This value becomes the default for all 
  7688.                columns. 
  7689.  
  7690.             -  DefineName_RECORD_AFTER_DATA_? 
  7691.                This value allows you to specify trailing data on a column by 
  7692.                column basis. 
  7693.  
  7694.          DefineName_AFTER 
  7695.           Unless you are not creating a table you are unlikely to want to 
  7696.           change the codes that end the table. 
  7697.  
  7698.          DefineName_RECORD_FILTER 
  7699.           The contents of this variable should be one or more rexx expressions. 
  7700.  
  7701.           Normally all records are displayed. A filter can examine all column 
  7702.           variables and modify them or tell PPWIZARD to ignore the record.  The 
  7703.           filter is not called for the heading record. 
  7704.  
  7705.           The following rexx variables and functions are relevant: 
  7706.  
  7707.             -  Remove 
  7708.                If this variable is set to any non blank value then the record 
  7709.                will be dropped, the variables value is shown when debugging so 
  7710.                it is recommended that the value be the reason for dropping the 
  7711.                record. 
  7712.  
  7713.                If the contents starts with 'EOF:' then the current record and 
  7714.                ALL following are dropped. 
  7715.  
  7716.             -  Column.? 
  7717.                The "Column" array holds the data for each field (that you are 
  7718.                interested in) of the current record in the order you provided. 
  7719.                For example "Column.2" holds the 2nd column's data. Note that 
  7720.                "Column.0" holds the number of fields in the array. 
  7721.  
  7722.             -  Dropped.? 
  7723.                The "Dropped" array holds the data for each field (that you 
  7724.                dropped) of the current record in the order that they were 
  7725.                dropped. For example "Dropped.1" holds the first dropped field. 
  7726.                Note that "Dropped.0" holds the number of fields in the array. 
  7727.  
  7728.             -  ThisRecordsCodes 
  7729.                This variable gets initialized for each record with the value 
  7730.                that you defined (or allowed to default) for the 
  7731.                "DefineName_RECORD" option.  You can add to or modify this 
  7732.                record in any way. The value of "{$Column1}" gets replaced with 
  7733.                the contents of the rexx variable "Column.1" etc. 
  7734.  
  7735.                If all your records are processed the same way then you should 
  7736.                not need to modify this variable.  It is useful where you might 
  7737.                want the output (row of table) to look different depending on 
  7738.                the records data.  In some cases this can be better done by 
  7739.                updating the rexx "Column.?" array. 
  7740.  
  7741.                If you need multiple lines you can of course use "<?NewLine>" 
  7742.                where required. 
  7743.  
  7744.             -  WriteLineToTmpImportFile() 
  7745.                The passed data is written to the output file, any line feed 
  7746.                characters will indicate the end of a line. 
  7747.  
  7748.             -  RecordFilter 
  7749.                If you don't need to do any more filtering then you can clear 
  7750.                this variable.  This will improve performance. 
  7751.  
  7752.          DefineName_KEEP_TMP_FILE 
  7753.           Normally PPWIZARD keeps the temporary file it creates while importing 
  7754.           when debug is on. This option allows you to specify whether you do or 
  7755.           don't want the file kept (whether debug is on or off). 
  7756.  
  7757.          DefineName_DO_PASS_2 
  7758.           You would rarely wish to modify this value. It controls whether or 
  7759.           not the generated file is #included (pass 2), it's value defaults to 
  7760.           'Y'. You might wish to disable the processing if all your processing 
  7761.           can be done in pass one (for example you have imported a database 
  7762.           into memory. 
  7763.  
  7764.          DefineName_PROTECT_START 
  7765.           By default will be set to the value <?ProtectFromPpwStart>. If you 
  7766.           have filter code that wants to generate PPWIZARD commands then you 
  7767.           will need to override this value. Have a look at the multiple HTML 
  7768.           pages example. 
  7769.  
  7770.          DefineName_PROTECT_END 
  7771.            By default will be set to the value <?ProtectFromPpwEnd>. 
  7772.  
  7773.  You should also check out an example of importing a file into multiple HTML 
  7774.  pages based on the contents of one of the fields. 
  7775.  
  7776.  Examples - Comma Delimited 
  7777.  
  7778.  A tab delimited file is probably be best format to use however this example 
  7779.  will use comma delimited as it's a bit hard to display a tab!  Assume the 
  7780.  following file is being imported (Importme.CMA): 
  7781.  
  7782.   Dennis,Bareis,Programmer
  7783.   Wendy,Buxton,Librarian
  7784.   Fred,Nerk,Idiot
  7785.  
  7786.  
  7787.  Please treat each of the following examples in isolation and assume that no 
  7788.  #defines other than those specifically shown for that example have been set. 
  7789.  Please note that I could have used ",,," instead of "CMA" when specifying the 
  7790.  format. 
  7791.  
  7792.  The following code will display the 3 fields in the order they occur (in a 
  7793.  completely default table format): 
  7794.  
  7795.       #import IMPORTME.CMA "CMA" '' "First Name" "Last Name" "Job"
  7796.  
  7797.  We now wish to simply swap the order of the "Job" column so it becomes first: 
  7798.  
  7799.       #import IMPORTME.CMA CMA '' "{2}First Name" "{3}Last Name" "{1}Job"
  7800.  
  7801.  Lets drop the last name altogether so that we only see the first name and job 
  7802.  columns: 
  7803.  
  7804.       #import IMPORTME.CMA CMA '' "First Name" "" "Job"
  7805.  
  7806.  Lets display the above table using slightly different table formatting (column 
  7807.  borders thinner, table border fatter, headings centered on yellow background 
  7808.  and record data left justified): 
  7809.  
  7810.       #define IMPORT_TABLE_ATTRIBS    BORDER=20 CELLSPACING=1
  7811.       #define IMPORT_HEADING_COLUMNS  ALIGN=CENTER BGCOLOR=YELLOW
  7812.       #define IMPORT_RECORD_COLUMNS   ALIGN=LEFT
  7813.       #import IMPORTME.CMA CMA '' "First Name" "" "Job"
  7814.  
  7815.  As above but column 2 is centered: 
  7816.  
  7817.       #define IMPORT_TABLE_ATTRIBS    BORDER=20 CELLSPACING=1
  7818.       #define IMPORT_HEADING_COLUMNS  ALIGN=CENTER BGCOLOR=YELLOW
  7819.       #define IMPORT_RECORD_COLUMNS   ALIGN=LEFT
  7820.       #define IMPORT_RECORD_COLUMN_2  ALIGN=CENTER
  7821.       #import IMPORTME.CMA CMA '' "First Name" "" "Job"
  7822.  
  7823.  
  7824.  Examples - More Complex 
  7825.  
  7826.  This example is based on a real one situation at work.  We export date from 
  7827.  Microsoft's access/Excel and want this data to appear in a table. 
  7828.  
  7829.  The following main points are demonstrated: 
  7830.  
  7831.        1. The use of #defines and line continuation to format things to be 
  7832.           easier to read and understand. 
  7833.  
  7834.        2. The use of #autotag to translate some of the text (for example 
  7835.           "priority") to minimize the width of the columns. 
  7836.  
  7837.        3. More complex overriding of defaults to get smaller font size etc. 
  7838.  
  7839.        4. More field dropping but also swapping of fields. 
  7840.  
  7841.   <HTML>
  7842.  
  7843.   ;--- Problem database data exported from Excel (trying from access) ---------
  7844.   <CENTER><H1>Release 98.0.1</H1></CENTER>
  7845.  
  7846.   ;--- Setup table definitions ------------------------------------------------
  7847.   #define    IMPORT_TABLE_ATTRIBS    BORDER=5 CELLSPACING=1
  7848.   #define    IMPORT_BLANK_FIELD      -
  7849.   ;**      CommentBlock  /* (Tuesday 23/06/1998, 13:00:55, by Dennis_Bareis) */
  7850.   ;**+--------------------------------------------------------------------------
  7851.   ;**|#define    IMPORT_HEADING_COLUMNS  ALIGN=CENTER BGCOLOR=YELLOW
  7852.   ;**|#define    IMPORT_RECORD_COLUMNS   ALIGN=CENTER
  7853.   ;**|#define    IMPORT_RECORD_COLUMN_2  ALIGN=LEFT
  7854.   ;**|#define    IMPORT_RECORD_COLUMN_4  ALIGN=LEFT
  7855.   ;**+--------------------------------------------------------------------------
  7856.   ;**                    /* (Tuesday 23/06/1998, 13:00:55, by Dennis_Bareis) */
  7857.  
  7858.   ;--- Define some data translations (shorten Priority + Problem Type) --------
  7859.   #AutoTag ">High<"       ">H<"
  7860.   #AutoTag ">Low<"        ">L<"
  7861.   #AutoTag ">Medium<"     ">M<"
  7862.   #AutoTag ">Change<"     ">C<"
  7863.   #AutoTag ">Error<"      ">E<"
  7864.  
  7865.   ;--- Try these --------------------------------------------------------------
  7866.   #define  IMPORT_HEADER  <TR>                                                      -\
  7867.                           <TH ALIGN=CENTER BGCOLOR=YELLOW><FONT SIZE=-1>{$Column1}  -\
  7868.                           <TH ALIGN=CENTER BGCOLOR=YELLOW><FONT SIZE=-1>{$Column2}  -\
  7869.                           <TH ALIGN=CENTER BGCOLOR=YELLOW><FONT SIZE=-1>{$Column3}  -\
  7870.                           <TH ALIGN=CENTER BGCOLOR=YELLOW><FONT SIZE=-1>{$Column4}  -\
  7871.                           <TH ALIGN=CENTER BGCOLOR=YELLOW><FONT SIZE=-1>{$Column5}  -\
  7872.                           <TH ALIGN=CENTER BGCOLOR=YELLOW><FONT SIZE=-1>{$Column6}  -\
  7873.                           <TH ALIGN=CENTER BGCOLOR=YELLOW><FONT SIZE=-1>{$Column7}  -\
  7874.                           <TH ALIGN=CENTER BGCOLOR=YELLOW><FONT SIZE=-1>{$Column8}  -\
  7875.                           </TR>
  7876.   #define  IMPORT_RECORD  <TR>                                                      -\
  7877.                           <TD ALIGN=CENTER><FONT SIZE=-1>{$Column1}                 -\
  7878.                           <TD ALIGN=LEFT><FONT SIZE=-1>{$Column2}                   -\
  7879.                           <TD ALIGN=CENTER><FONT SIZE=-1>{$Column3}                 -\
  7880.                           <TD ALIGN=LEFT><FONT SIZE=-1>{$Column4}                   -\
  7881.                           <TD ALIGN=CENTER><FONT SIZE=-1>{$Column5}                 -\
  7882.                           <TD ALIGN=CENTER><FONT SIZE=-1>{$Column6}                 -\
  7883.                           <TD ALIGN=CENTER><FONT SIZE=-1>{$Column7}                 -\
  7884.                           <TD ALIGN=CENTER><FONT SIZE=-1>{$Column8}                 -\
  7885.                           </TR>
  7886.  
  7887.   ;--- Specify the fields -----------------------------------------------------
  7888.   #define  FIELD_NAMES    "{1}Problem<BR>#"                \
  7889.                           "{2}Title"                       \
  7890.                           "{5}P<BR>r<BR>i"                 \
  7891.                           "{8}Pre<BR>/<BR>Spar"            \
  7892.                           "{6}T<BR>y<BR>p<BR>e"            \
  7893.                           "{3}Application"                 \
  7894.                           ""                               \
  7895.                           ""                               \
  7896.                           "{7}Fixed By"                    \
  7897.                           ""                               \
  7898.                           ""                               \
  7899.                           ""                               \
  7900.                           ""                               \
  7901.                           ""                               \
  7902.                           "{4}User Impact"
  7903.  
  7904.   ;--- Make the changes (autotag some text) -----------------------------------
  7905.   #AutoTag ON
  7906.   #import "export.tab" TAB- ""    <$FIELD_NAMES>
  7907.   #AutoTag OFF
  7908.  
  7909.  
  7910.   </HTML>
  7911.  
  7912.  
  7913.  
  7914.  
  7915.  Examples - IPF Import 
  7916.  
  7917.  The following code: 
  7918.  
  7919.   #define IMPORT_NEWLINE_CHAR    <?NewLine>.br<?NewLine>
  7920.   #define IMPORT_BEFORE          :table cols='15 15 10'.
  7921.   #define IMPORT_HEADER          :row.                              -\
  7922.                                  :c.:hp9.{$Column1}:ehp9.           -\
  7923.                                  :c.:hp9.{$Column2}:ehp9.           -\
  7924.                                  :c.:hp9.{$Column3}:ehp9.
  7925.   #define IMPORT_RECORD          :row.                              -\
  7926.                                  :c.{$Column1}                      -\
  7927.                                  :c.{$Column2}                      -\
  7928.                                  :c.{$Column3}
  7929.   #define IMPORT_AFTER           :etable.
  7930.  
  7931.  
  7932.   #define IMPORT_RECORD_COLUMNS   ALIGN=LEFT
  7933.  
  7934.   #import "EXAMPLE.CMA" CMA '' "First Name"  "Surname"   "Job"
  7935.  
  7936.  
  7937.  Produces this IPF table: 
  7938.  
  7939.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  7940.   ΓöéFirst Name     ΓöéSurname        ΓöéJob       Γöé
  7941.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7942.   ΓöéDennis         ΓöéBareis         ΓöéProgrammerΓöé
  7943.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7944.   ΓöéWendy          ΓöéBuxton         ΓöéLibrarian Γöé
  7945.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7946.   ΓöéFred           ΓöéNerk           ΓöéIdiot     Γöé
  7947.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  7948.  
  7949.  Example - Use of Filter 
  7950.  
  7951.   #DefineRexx IMPORT_RECORD_FILTER
  7952.               if Column.1 = "Wendy" then
  7953.                  Remove='This is "Wendy" record'    ;;Don't want this record
  7954.               else
  7955.                  Column.1 = translate(Column.1)     ;;Make column #1 upper case
  7956.   #DefineRexx
  7957.   #import ImportMe.CMA CMA "" "First<BR>Name" "Surname" "Job"
  7958.  
  7959.  
  7960. ΓòÉΓòÉΓòÉ 9.23.2. #import - Fixed Field Records ΓòÉΓòÉΓòÉ
  7961.  
  7962. #import - Fixed Field Records 
  7963.  
  7964. This type of #Import has clearly defined fields. You would frequently wish to 
  7965. display these in a table (say in a HTML page) however nothing says that you 
  7966. need to do so. If you wish to create macros and then #include a template file 
  7967. then that is also possible. 
  7968.  
  7969. The fields have a fixed starting and ending column.  The last record does not 
  7970. need to have a fixed ending column and can span to the end of the line. 
  7971. Leading and trailing whitespace is removed. 
  7972.  
  7973. Field Information Parameters 
  7974.  
  7975. On these types of imports "FieldInfo" follows the "DefineName" parameter on the 
  7976. #import command line. 
  7977.  
  7978. For each field that you are interested in you need to define information in the 
  7979. format: 
  7980.  
  7981.   {*,StartingColumn-[EndingColumn]}TitleText 
  7982.  
  7983. In place of the '*' you could specify the column number you wish to place the 
  7984. field but it's usually easier to simply reorder the fields. 
  7985.  
  7986. The "StartingColumn" specifies the column where the field starts. The optional 
  7987. "EndingColumn" specifies where it ends, if not supplied it ends at the end of 
  7988. the line.  The first column in a line is column 1. 
  7989.  
  7990. The "title text" specifies the value for the field in the header record.  If 
  7991. this "title" is blank the field will be dropped. 
  7992.  
  7993. DEFINITIONS/OPTIONS 
  7994.  
  7995. If you can't understand how these options work then I suggest you try using 
  7996. /debug or #debug to watch what variables the import uses etc. 
  7997.  
  7998.          DefineName_BLANK_FIELD 
  7999.           Normally a blank field will be displayed as blank. You may wish to 
  8000.           display '-' instead. Another possiblity is to display a 1 by 1 
  8001.           transparent gif so as to have table borders around blank fields look 
  8002.           better. 
  8003.  
  8004.           For even more control (probably rare requirement): 
  8005.  
  8006.             -  DefineName_BLANK_COLUMN_? 
  8007.                This allows you to specify different blank replacement values 
  8008.                for each column. 
  8009.  
  8010.          DefineName_DROP_BLANK_LINES 
  8011.           You can specify whether or not blank lines (or lines where all fields 
  8012.           are blank) are significant.  The default is 'Y' to drop blank lines, 
  8013.           specify 'N' to prevent this. 
  8014.  
  8015.          DefineName_NEWLINE_CHAR 
  8016.           This can be used to determine what newlines within fields should be 
  8017.           replaced with ("<BR>" by default). 
  8018.  
  8019.          DefineName_TAB_CHAR 
  8020.           Normally tabs are ignored by the import process.  This variable 
  8021.           allows you to replace them with something else. 
  8022.  
  8023.          DefineName_ASIS_TAGGING 
  8024.           This option can be used to adjust the conversion of what may be 
  8025.           problem characters (such as '<' in HTML). By default importing does 
  8026.           not handle/convert international characters such as umlauts to html 
  8027.           symbols but there is nothing preventing you from doing so. 
  8028.  
  8029.           This definition lists zero, one or more names as used on previous 
  8030.           "#AsIs SETUP" commands (seperated by whitespace). Clear this 
  8031.           definition to prevent all ASIS conversions. 
  8032.  
  8033.           Note that you will probably need to override this value (maybe others 
  8034.           as well) if you wished to expand any macros that the imported data 
  8035.           might contain (by default this is not done). 
  8036.  
  8037.          DefineName_DROP_LINE_COUNT 
  8038.           If we are dropping lines (TAB- command etc), then how many should be 
  8039.           dropped.  The default is one. 
  8040.  
  8041.          DefineName_HANDLE_IMBEDDED_NEWLINES 
  8042.           Excel and probably other programs can output delimited files where a 
  8043.           "line" can contain a newline.  To detect this takes more work and so 
  8044.           it is not the default situation.  To turn on imbedded newline 
  8045.           detection use a value of 'Y'. 
  8046.  
  8047.          DefineName_BEFORE 
  8048.           You would probably only use this define if you didn't want to 
  8049.           generate a table at all. You may specify the string "{$Columns}" 
  8050.           which will get replaced with the number of fields to be displayed. If 
  8051.           this define is not used then you can use the following: 
  8052.  
  8053.             -  DefineName_TABLE_ATTRIBS 
  8054.                This value allows you to specify all HTML attributes of the 
  8055.                table apart from the number of columns. 
  8056.  
  8057.          DefineName_HEADER 
  8058.           This is used to control the "code" which handles the "heading" 
  8059.           record, <B>this does not have to be a html table</B>. You can specify 
  8060.           the string {$Column?} to represent a fields value (? = number of 
  8061.           field where 1 is the first). 
  8062.  
  8063.           If this define is not used then you can use the following: 
  8064.  
  8065.             -  DefineName_HEADING_COLUMNS 
  8066.                This value allows you to specify the column (HTML "<TH>" tags) 
  8067.                information to change alignment or colours of columns. This 
  8068.                value becomes the default for all columns. 
  8069.  
  8070.             -  DefineName_HEADING_COLUMN_? 
  8071.                This value allows you to specify the column (HTML "<TH>" tags) 
  8072.                information to change alignment or colours of specific columns. 
  8073.                Another use for this would be to specify the width of a column. 
  8074.                This value is only used for column number '?'. 
  8075.  
  8076.             -  DefineName_HEADING_BEFORE_DATA 
  8077.                This value allows you to specify some text to be placed in front 
  8078.                of the fields data, for example if you wish to change the font 
  8079.                size for each column you might used the value "<FONT SIZE=-1>". 
  8080.                This value becomes the default for all columns. 
  8081.  
  8082.             -  DefineName_HEADING_BEFORE_DATA_? 
  8083.                This value allows you to specify leading data on a column by 
  8084.                column basis. 
  8085.  
  8086.             -  DefineName_HEADING_AFTER_DATA 
  8087.                This value allows you to specify some text to be placed after 
  8088.                the fields data, for example if you wish to change the font size 
  8089.                for each column you might used the value "</FONT>" to close the 
  8090.                previous font tag. This value becomes the default for all 
  8091.                columns. 
  8092.  
  8093.             -  DefineName_HEADING_AFTER_DATA_? 
  8094.                This value allows you to specify trailing data on a column by 
  8095.                column basis. 
  8096.  
  8097.          DefineName_RECORD 
  8098.           This is used to control the "code" for each record, <B>this does not 
  8099.           have to be a html table</B>. You would definately define this option 
  8100.           if you didn't want a html table, you might wish to create s series of 
  8101.           #defines or maybe you are not generating html at all and need to 
  8102.           generate an IPF table. You can specify the string {$Column?} to 
  8103.           represent a fields value (? = number of field where 1 is the first). 
  8104.  
  8105.           If this define is not used then you can use the following: 
  8106.  
  8107.             -  DefineName_RECORD_COLUMNS 
  8108.                This value allows you to specify the column (HTML "<TD>" tags) 
  8109.                information to change alignment or colours of columns. This 
  8110.                value becomes the default for all columns. 
  8111.  
  8112.             -  DefineName_RECORD_COLUMN_? 
  8113.                This value allows you to specify the column (HTML "<TD>" tags) 
  8114.                information to change alignment or colours of specific columns. 
  8115.                Another use for this would be to specify the width of a column. 
  8116.                This value is only used for column number '?'. 
  8117.  
  8118.             -  DefineName_RECORD_BEFORE_DATA 
  8119.                This value allows you to specify some text to be placed in front 
  8120.                of the fields data, for example if you wish to change the font 
  8121.                size for each column you might used the value "<FONT SIZE=-1>". 
  8122.                This value becomes the default for all columns. 
  8123.  
  8124.             -  DefineName_RECORD_BEFORE_DATA_? 
  8125.                This value allows you to specify leading data on a column by 
  8126.                column basis. 
  8127.  
  8128.             -  DefineName_RECORD_AFTER_DATA 
  8129.                This value allows you to specify some text to be placed after 
  8130.                the fields data, for example if you wish to change the font size 
  8131.                for each column you might used the value "</FONT>" to close the 
  8132.                previous font tag. This value becomes the default for all 
  8133.                columns. 
  8134.  
  8135.             -  DefineName_RECORD_AFTER_DATA_? 
  8136.                This value allows you to specify trailing data on a column by 
  8137.                column basis. 
  8138.  
  8139.          DefineName_AFTER 
  8140.           Unless you are not creating a table you are unlikely to want to 
  8141.           change the codes that end the table. 
  8142.  
  8143.          DefineName_RECORD_FILTER 
  8144.           The contents of this variable should be one or more rexx expressions. 
  8145.  
  8146.           Normally all records are displayed. A filter can examine all column 
  8147.           variables and modify them or tell PPWIZARD to ignore the record.  The 
  8148.           filter is not called for the heading record. 
  8149.  
  8150.           The following rexx variables and functions are relevant: 
  8151.  
  8152.             -  Remove 
  8153.                If this variable is set to any non blank value then the record 
  8154.                will be dropped, the variables value is shown when debugging so 
  8155.                it is recommended that the value be the reason for dropping the 
  8156.                record. 
  8157.  
  8158.                If the contents starts with 'EOF:' then the current record and 
  8159.                ALL following are dropped. 
  8160.  
  8161.             -  Column.? 
  8162.                The "Column" array holds the data for each field (that you are 
  8163.                interested in) of the current record in the order you provided. 
  8164.                For example "Column.2" holds the 2nd column's data. Note that 
  8165.                "Column.0" holds the number of fields in the array. 
  8166.  
  8167.             -  Dropped.? 
  8168.                The "Dropped" array holds the data for each field (that you 
  8169.                dropped) of the current record in the order that they were 
  8170.                dropped. For example "Dropped.1" holds the first dropped field. 
  8171.                Note that "Dropped.0" holds the number of fields in the array. 
  8172.  
  8173.             -  ThisRecordsCodes 
  8174.                This variable gets initialized for each record with the value 
  8175.                that you defined (or allowed to default) for the 
  8176.                "DefineName_RECORD" option.  You can add to or modify this 
  8177.                record in any way. The value of "{$Column1}" gets replaced with 
  8178.                the contents of the rexx variable "Column.1" etc. 
  8179.  
  8180.                If all your records are processed the same way then you should 
  8181.                not need to modify this variable.  It is useful where you might 
  8182.                want the output (row of table) to look different depending on 
  8183.                the records data.  In some cases this can be better done by 
  8184.                updating the rexx "Column.?" array. 
  8185.  
  8186.                If you need multiple lines you can of course use "<?NewLine>" 
  8187.                where required. 
  8188.  
  8189.             -  WriteLineToTmpImportFile() 
  8190.                The passed data is written to the output file, any line feed 
  8191.                characters will indicate the end of a line. 
  8192.  
  8193.             -  RecordFilter 
  8194.                If you don't need to do any more filtering then you can clear 
  8195.                this variable.  This will improve performance. 
  8196.  
  8197.          DefineName_KEEP_TMP_FILE 
  8198.           Normally PPWIZARD keeps the temporary file it creates while importing 
  8199.           when debug is on. This option allows you to specify whether you do or 
  8200.           don't want the file kept (whether debug is on or off). 
  8201.  
  8202.          DefineName_DO_PASS_2 
  8203.           You would rarely wish to modify this value. It controls whether or 
  8204.           not the generated file is #included (pass 2), it's value defaults to 
  8205.           'Y'. You might wish to disable the processing if all your processing 
  8206.           can be done in pass one (for example you have imported a database 
  8207.           into memory. 
  8208.  
  8209.          DefineName_PROTECT_START 
  8210.           By default will be set to the value <?ProtectFromPpwStart>. If you 
  8211.           have filter code that wants to generate PPWIZARD commands then you 
  8212.           will need to override this value. Have a look at the multiple HTML 
  8213.           pages example. 
  8214.  
  8215.          DefineName_PROTECT_END 
  8216.            By default will be set to the value <?ProtectFromPpwEnd>. 
  8217.  
  8218.  You should also check out an example of importing a file into multiple HTML 
  8219.  pages based on the contents of one of the fields. 
  8220.  
  8221.  Example 
  8222.  
  8223.  Assume we have a file as follows (IMPORTME.FIX): 
  8224.  
  8225.       First Name         Last Name           Job
  8226.       Dennis             Bareis              Programmer
  8227.       Wendy              Buxton              Librarian
  8228.       Fred               Nerk                Idiot
  8229.  
  8230.  We note that it has the following fields: 
  8231.  
  8232.        1. First Name, starting in column 1 ending at 18 
  8233.        2. Last Name, starting in column 20 ending at 38 
  8234.        3. Job, starting in column 40 ending at end of line. 
  8235.  
  8236.  The following line would import the fields in order (into a completely default 
  8237.  table layout): 
  8238.  
  8239.       #import IMPORTME.FIX FIX- '' "{1,1-18}First Name" "{2,20-38}Last Name" "{3,40-}Job"
  8240.  
  8241.  
  8242. ΓòÉΓòÉΓòÉ 9.23.3. #import - Multi Line Records ΓòÉΓòÉΓòÉ
  8243.  
  8244. #import - Multi Line Records 
  8245.  
  8246. This type of #Import has clearly defined fields which you label. You would 
  8247. frequently wish to display these in a table (say in a HTML page) however 
  8248. nothing says that you need to do so. 
  8249.  
  8250. Field Information Parameters 
  8251.  
  8252. On these types of imports "FieldInfo" follows the "DefineName" parameter on the 
  8253. #import command line. 
  8254.  
  8255. For each field you have defined in your database you must specify field 
  8256. information. The field information is of the format: 
  8257.  
  8258.   {*,FieldName[,FieldOptions]}TitleText 
  8259.  
  8260. In place of the '*' you could specify the column number you wish to place the 
  8261. field but it's usually easier to simply reorder the fields. 
  8262.  
  8263. The "field name" specifies the name you use in your database.  It can contain 
  8264. virtually any characters but must of course not contain the delimiter character 
  8265. ('=' by default).  Like all PPWIZARD names the name can contain international 
  8266. characters. 
  8267.  
  8268. You can optionally specify some field options which vary the way individual 
  8269. fields are processed.  Each field option is separated by a comma, valid options 
  8270. are: 
  8271.  
  8272.          REQUIRED 
  8273.           This field is required. You can supply a blank value. This validation 
  8274.           occurs whether or not the field is dropped. 
  8275.  
  8276.          NONBLANK 
  8277.           This field if supplied must be non blank. If not supplied its value 
  8278.           will become blank unless "REQUIRED" option was also specified. This 
  8279.           validation occurs whether or not the field is dropped. 
  8280.  
  8281.          NOASIS 
  8282.           By default all files go through AsIs() replacements, this option 
  8283.           allows you to prevent this occuring on particular fields if required. 
  8284.  
  8285.  The "title text" specifies the value for the field in the header record. Since 
  8286.  all fields must be defined we use a blank "title" to indicate that we don't 
  8287.  require a field and it should be dropped. 
  8288.  
  8289.  DEFINITIONS/OPTIONS 
  8290.  
  8291.  If you can't understand how these options work then I suggest you try using 
  8292.  /debug or #debug to watch what variables the import uses etc. 
  8293.  
  8294.          DefineName_BLANK_FIELD 
  8295.           Normally a blank field will be displayed as blank. You may wish to 
  8296.           display '-' instead. Another possiblity is to display a 1 by 1 
  8297.           transparent gif so as to have table borders around blank fields look 
  8298.           better. 
  8299.  
  8300.           For even more control (probably rare requirement): 
  8301.  
  8302.             -  DefineName_BLANK_COLUMN_? 
  8303.                This allows you to specify different blank replacement values 
  8304.                for each column. 
  8305.  
  8306.          DefineName_TAB_CHAR 
  8307.           Normally tabs are ignored by the import process.  This variable 
  8308.           allows you to replace them with something else. 
  8309.  
  8310.          DefineName_ASIS_TAGGING 
  8311.           This option can be used to adjust the conversion of what may be 
  8312.           problem characters (such as '<' in HTML). By default importing does 
  8313.           not handle/convert international characters such as umlauts to html 
  8314.           symbols but there is nothing preventing you from doing so. 
  8315.  
  8316.           This definition lists zero, one or more names as used on previous 
  8317.           "#AsIs SETUP" commands (seperated by whitespace). Clear this 
  8318.           definition to prevent all ASIS conversions. 
  8319.  
  8320.           Note that you will probably need to override this value (maybe others 
  8321.           as well) if you wished to expand any macros that the imported data 
  8322.           might contain (by default this is not done). 
  8323.  
  8324.          DefineName_BEFORE 
  8325.           You would probably only use this define if you didn't want to 
  8326.           generate a table at all. You may specify the string "{$Columns}" 
  8327.           which will get replaced with the number of fields to be displayed. If 
  8328.           this define is not used then you can use the following: 
  8329.  
  8330.             -  DefineName_TABLE_ATTRIBS 
  8331.                This value allows you to specify all HTML attributes of the 
  8332.                table apart from the number of columns. 
  8333.  
  8334.          DefineName_HEADER 
  8335.           This is used to control the "code" which handles the "heading" 
  8336.           record, <B>this does not have to be a html table</B>. You can specify 
  8337.           the string {$Column?} to represent a fields value (? = number of 
  8338.           field where 1 is the first). 
  8339.  
  8340.           If this define is not used then you can use the following: 
  8341.  
  8342.             -  DefineName_HEADING_COLUMNS 
  8343.                This value allows you to specify the column (HTML "<TH>" tags) 
  8344.                information to change alignment or colours of columns. This 
  8345.                value becomes the default for all columns. 
  8346.  
  8347.             -  DefineName_HEADING_COLUMN_? 
  8348.                This value allows you to specify the column (HTML "<TH>" tags) 
  8349.                information to change alignment or colours of specific columns. 
  8350.                Another use for this would be to specify the width of a column. 
  8351.                This value is only used for column number '?'. 
  8352.  
  8353.             -  DefineName_HEADING_BEFORE_DATA 
  8354.                This value allows you to specify some text to be placed in front 
  8355.                of the fields data, for example if you wish to change the font 
  8356.                size for each column you might used the value "<FONT SIZE=-1>". 
  8357.                This value becomes the default for all columns. 
  8358.  
  8359.             -  DefineName_HEADING_BEFORE_DATA_? 
  8360.                This value allows you to specify leading data on a column by 
  8361.                column basis. 
  8362.  
  8363.             -  DefineName_HEADING_AFTER_DATA 
  8364.                This value allows you to specify some text to be placed after 
  8365.                the fields data, for example if you wish to change the font size 
  8366.                for each column you might used the value "</FONT>" to close the 
  8367.                previous font tag. This value becomes the default for all 
  8368.                columns. 
  8369.  
  8370.             -  DefineName_HEADING_AFTER_DATA_? 
  8371.                This value allows you to specify trailing data on a column by 
  8372.                column basis. 
  8373.  
  8374.          DefineName_RECORD 
  8375.           This is used to control the "code" for each record, <B>this does not 
  8376.           have to be a html table</B>. You would definately define this option 
  8377.           if you didn't want a html table, you might wish to create s series of 
  8378.           #defines or maybe you are not generating html at all and need to 
  8379.           generate an IPF table. You can specify the string {$Column?} to 
  8380.           represent a fields value (? = number of field where 1 is the first). 
  8381.  
  8382.           If this define is not used then you can use the following: 
  8383.  
  8384.             -  DefineName_RECORD_COLUMNS 
  8385.                This value allows you to specify the column (HTML "<TD>" tags) 
  8386.                information to change alignment or colours of columns. This 
  8387.                value becomes the default for all columns. 
  8388.  
  8389.             -  DefineName_RECORD_COLUMN_? 
  8390.                This value allows you to specify the column (HTML "<TD>" tags) 
  8391.                information to change alignment or colours of specific columns. 
  8392.                Another use for this would be to specify the width of a column. 
  8393.                This value is only used for column number '?'. 
  8394.  
  8395.             -  DefineName_RECORD_BEFORE_DATA 
  8396.                This value allows you to specify some text to be placed in front 
  8397.                of the fields data, for example if you wish to change the font 
  8398.                size for each column you might used the value "<FONT SIZE=-1>". 
  8399.                This value becomes the default for all columns. 
  8400.  
  8401.             -  DefineName_RECORD_BEFORE_DATA_? 
  8402.                This value allows you to specify leading data on a column by 
  8403.                column basis. 
  8404.  
  8405.             -  DefineName_RECORD_AFTER_DATA 
  8406.                This value allows you to specify some text to be placed after 
  8407.                the fields data, for example if you wish to change the font size 
  8408.                for each column you might used the value "</FONT>" to close the 
  8409.                previous font tag. This value becomes the default for all 
  8410.                columns. 
  8411.  
  8412.             -  DefineName_RECORD_AFTER_DATA_? 
  8413.                This value allows you to specify trailing data on a column by 
  8414.                column basis. 
  8415.  
  8416.          DefineName_AFTER 
  8417.           Unless you are not creating a table you are unlikely to want to 
  8418.           change the codes that end the table. 
  8419.  
  8420.          DefineName_RECORD_FILTER 
  8421.           The contents of this variable should be one or more rexx expressions. 
  8422.  
  8423.           Normally all records are displayed. A filter can examine all column 
  8424.           variables and modify them or tell PPWIZARD to ignore the record.  The 
  8425.           filter is not called for the heading record. 
  8426.  
  8427.           The following rexx variables and functions are relevant: 
  8428.  
  8429.             -  Remove 
  8430.                If this variable is set to any non blank value then the record 
  8431.                will be dropped, the variables value is shown when debugging so 
  8432.                it is recommended that the value be the reason for dropping the 
  8433.                record. 
  8434.  
  8435.                If the contents starts with 'EOF:' then the current record and 
  8436.                ALL following are dropped. 
  8437.  
  8438.             -  Column.? 
  8439.                The "Column" array holds the data for each field (that you are 
  8440.                interested in) of the current record in the order you provided. 
  8441.                For example "Column.2" holds the 2nd column's data. Note that 
  8442.                "Column.0" holds the number of fields in the array. 
  8443.  
  8444.             -  Dropped.? 
  8445.                The "Dropped" array holds the data for each field (that you 
  8446.                dropped) of the current record in the order that they were 
  8447.                dropped. For example "Dropped.1" holds the first dropped field. 
  8448.                Note that "Dropped.0" holds the number of fields in the array. 
  8449.  
  8450.             -  ThisRecordsCodes 
  8451.                This variable gets initialized for each record with the value 
  8452.                that you defined (or allowed to default) for the 
  8453.                "DefineName_RECORD" option.  You can add to or modify this 
  8454.                record in any way. The value of "{$Column1}" gets replaced with 
  8455.                the contents of the rexx variable "Column.1" etc. 
  8456.  
  8457.                If all your records are processed the same way then you should 
  8458.                not need to modify this variable.  It is useful where you might 
  8459.                want the output ( row of table) to look different depending on 
  8460.                the records data.  In some cases this can be better done by 
  8461.                updating the rexx "Column.?" array. 
  8462.  
  8463.                If you need multiple lines you can of course use "<?NewLine>" 
  8464.                where required. 
  8465.  
  8466.             -  WriteLineToTmpImportFile() 
  8467.                The passed data is written to the output file, any line feed 
  8468.                characters will indicate the end of a line. 
  8469.  
  8470.             -  GetMlField() 
  8471.                This routine can be called to obtain the value of a field (the 
  8472.                name of which is passed). You can access the fields data in a 
  8473.                more efficient manner using the "Column" and "Dropped" arrays 
  8474.                however this routine allows you to access a variable knowing its 
  8475.                name. 
  8476.  
  8477.             -  RecordFilter 
  8478.                If you don't need to do any more filtering then you can clear 
  8479.                this variable.  This will improve performance. 
  8480.  
  8481.          DefineName_DELIMITER 
  8482.           This is the character(s) that separate the name of a field from its 
  8483.           value. 
  8484.  
  8485.          DefineName_STRIP_LEADING 
  8486.           This indicates whether or not leading whitespace on a fields value 
  8487.           should be removed. The default is 'Y', if 'N' one only space is 
  8488.           removed if it exists (to allow for a space after the delimiter). 
  8489.  
  8490.          DefineName_SEPARATOR 
  8491.           If you continue a field over onto a following line (the continued 
  8492.           line has no field name) then what are the two components "stitched" 
  8493.           together with? The default is a space. 
  8494.  
  8495.          DefineName_LINE_COMMENT_CHAR 
  8496.           This is the character that can be used to start a line for commenting 
  8497.           your file.  It defaults to the current PPWIZARD line comment 
  8498.           character. 
  8499.  
  8500.          DefineName_LINE_FILTER 
  8501.           The contents of this variable should be one or more rexx expressions. 
  8502.  
  8503.           If an expression is supplied for this option then the filter code 
  8504.           will be called for each non comment line found.  This allows you to 
  8505.           build extra smarts into the processing of records if you wish (for 
  8506.           example breaking a table into sections. 
  8507.  
  8508.           The following rexx variables are relevant: 
  8509.  
  8510.             -  MultiLine 
  8511.                This is the current line without leading and trailing 
  8512.                whitespace.  You may modify the contents if you need to. 
  8513.  
  8514.             -  Remove 
  8515.                If this variable is set to any non blank value then the line 
  8516.                will be dropped, the variables value is shown when debugging so 
  8517.                it is recommended that the value be the reason for dropping the 
  8518.                line. 
  8519.  
  8520.                If the contents starts with 'EOF:' then the current line and ALL 
  8521.                following are dropped. 
  8522.  
  8523.             -  LineFilter 
  8524.                If you don't need to do any more filtering then you can clear 
  8525.                this variable.  This will improve performance. 
  8526.  
  8527.          DefineName_KEEP_TMP_FILE 
  8528.           Normally PPWIZARD keeps the temporary file it creates while importing 
  8529.           when debug is on. This option allows you to specify whether you do or 
  8530.           don't want the file kept (whether debug is on or off). 
  8531.  
  8532.          DefineName_DO_PASS_2 
  8533.           You would rarely wish to modify this value. It controls whether or 
  8534.           not the generated file is #included (pass 2), it's value defaults to 
  8535.           'Y'. You might wish to disable the processing if all your processing 
  8536.           can be done in pass one (for example you have imported a database 
  8537.           into memory. 
  8538.  
  8539.          DefineName_PROTECT_START 
  8540.           By default will be set to the value <?ProtectFromPpwStart>. If you 
  8541.           have filter code that wants to generate PPWIZARD commands then you 
  8542.           will need to override this value. Have a look at the multiple HTML 
  8543.           pages example. 
  8544.  
  8545.          DefineName_PROTECT_END 
  8546.            By default will be set to the value <?ProtectFromPpwEnd>. 
  8547.  
  8548.  You should also check out an example of importing a file into multiple HTML 
  8549.  pages based on the contents of one of the fields. 
  8550.  
  8551.  Example - Multi Line Import 
  8552.  
  8553.  Lets assume you have created a database (called "WEBLINKS.ML") similar to: 
  8554.  
  8555.   ;--- First record ------------------------
  8556.      Name     :  Dennis
  8557.               :  Bareis
  8558.      Email    :  db0@anz.com
  8559.      Web Page :  www.labyrinth.net.au
  8560.      Comment  :  Really good site!
  8561.  
  8562.   ;--- Second record -----------------------
  8563.       Name:  Fredric Bald
  8564.    Comment:  This comment contains LT=< & GT=> characters
  8565.   Web Page:  www.somewhere.com
  8566.      Email:  fred@anz.com
  8567.  
  8568.  Note that in the above sample data the first "name" field spans two lines to 
  8569.  demonstrate line continuation. 
  8570.  
  8571.  Then you can import the data and convert the email and web addresses into 
  8572.  hypertext links with: 
  8573.  
  8574.   <HTML><BODY>
  8575.   #DefineRexx ML_RECORD_FILTER
  8576.               Column.2 = "<A HREF='mailto:" || Column.2 || "'>" || Column.2 || "</A>"
  8577.               Column.3 = "<A HREF='http://" || Column.3 || "'>" || Column.3 || "</A>"
  8578.   #DefineRexx
  8579.   #define ML_DELIMITER      :
  8580.   #import WEBLINKS.ML ML  "" "{*,Name}Name" "{*,EMail}Email<BR>Address" "{*,Web Page}http://" "{*,Comment}Comment"
  8581.   </BODY></HTML>
  8582.  
  8583.  The following code imports the same database but demonstrates field reordering 
  8584.  (unusual requirement), field dropping (email address is not required) and 
  8585.  requiring all fields to be specified and non-blank: 
  8586.  
  8587.   <HTML><BODY>
  8588.   #define THIS1_RECORD_FILTER                                                         \
  8589.           Column.2 = "<A HREF='http://" || Column.2 || "'>" || Column.2 || "</A>"
  8590.   #define THIS1_DELIMITER      :
  8591.   #import WEBLINKS.ML ML  "THIS1"  "{2,Web Page,required,nonblank}http://"  \
  8592.                                    "{3,Comment,required,nonblank}Comment"   \
  8593.                                    "{1,Name,required,nonblank}Name"         \
  8594.                                    "{*,email}"
  8595.   </BODY></HTML>
  8596.  
  8597.  
  8598. ΓòÉΓòÉΓòÉ 9.23.4. #import - SQL ΓòÉΓòÉΓòÉ
  8599.  
  8600. #import - SQL 
  8601.  
  8602. This type of #Import directly accesses SQL databases such as MS Access 2000, MS 
  8603. SQL Server, mSQL or DB/2. 
  8604.  
  8605. It requires a free 3rd party product called REXXSQL which can be obtained from 
  8606. Mark Hessling's site at "http://www.lightlink.com/hessling/REXXSQL/". To 
  8607. install RexxSQL you will need to follow its instructions but under Windows I 
  8608. simply copied the 2 DLLs into the system directory. PPWIZARD will inform you if 
  8609. it has problems finding the DLL. 
  8610.  
  8611. This command is of course only supported on those operating systems that 
  8612. "RexxSQL" runs on (currently Windows, OS/2 and Unix). Check out Mark's pages 
  8613. for more details on the databases supported however this is a list (may not be 
  8614. complete) of databases known to work with RexxSQL: 
  8615.  
  8616.          IBM's DB2 
  8617.          EasySoft ODBC-ODBC Bridge 
  8618.          Generic ODBC (probably covers most!) 
  8619.             -  Microsoft Access 
  8620.             -  Microsoft Excel spreadsheets 
  8621.             -  Microsoft SQL Server 
  8622.             -  CSV (and other text formats) 
  8623.             -  FoxPro 
  8624.             -  Paradox 
  8625.             -  DBase 
  8626.          Mini SQL (1.0.16, 2.0+) 
  8627.          My SQL 
  8628.          Openlink UDBC 
  8629.          Oracle (7.x, 8.x) 
  8630.          PostgreSQL 
  8631.          Raima Velocis 
  8632.          Solid 
  8633.          Sybase System 10/11 
  8634.          Sybase SQL Anywhere 
  8635.  
  8636.  This form of SQL import should be able to handle all or nearly all of your 
  8637.  needs but if you need something more complex then you should check out the 
  8638.  accessing SQL in rexx page. 
  8639.  
  8640.  If debug mode is on a lot of SQL related information is generated including a 
  8641.  dump of all column information available on the columns returned by your 
  8642.  query. PPWIZARD's debug mode (by default) also turns on REXXSQL debug so it 
  8643.  should be quite easy to diagnose any problems you might have. 
  8644.  
  8645.  Field Information Parameters 
  8646.  
  8647.  The SQL import requires "FieldInfo" following the "DefineName" parameter. 
  8648.  
  8649.  You must specify field information for each column you want to handle from the 
  8650.  data returned by your SQL query. 
  8651.  
  8652.  The field information is of the format "{ColName}TitleText". 
  8653.  
  8654.  The optional "ColName" parameter specifies the column name returned by your 
  8655.  query while "TitleText" specifies the value for the title in the header 
  8656.  record. 
  8657.  
  8658.  If a "ColName" is not specified then the "TitleText" is used for the column 
  8659.  name as well. This would probably only be done if you either did not care 
  8660.  about the title text in the header or you did not have a header. 
  8661.  
  8662.  DEFINITIONS/OPTIONS 
  8663.  
  8664.  If you can't understand how these options work then I suggest you try using 
  8665.  /debug or #debug to watch what variables the import uses etc. 
  8666.  
  8667.          DefineName_SQL_DEBUG 
  8668.           This value is used to set the RexxSQL "DEBUG" variable. It only takes 
  8669.           effect when debug mode is on and by default all available information 
  8670.           is output (use "0" for none). Note that RexxSQL debug output is not 
  8671.           captured by /ConsoleFile but must be redirected. 
  8672.  
  8673.          DefineName_SQL_USERID 
  8674.           Your database may require a user ID for access. 
  8675.  
  8676.          DefineName_SQL_USERPW 
  8677.           Your database may require a password for access. 
  8678.  
  8679.          DefineName_SQL_DATABASE 
  8680.           This specfies a database. It probably does not specify the database 
  8681.           file name but the value has probably been defined somewhere, for 
  8682.           example under Windows 2000, to access a database via ODBC the name 
  8683.           used here must first be defined in 
  8684.           "Start->Control Panel->Administrative Tools->Data Sources (ODBC)". 
  8685.  
  8686.          DefineName_SQL_SERVER 
  8687.           Another field which might be required to establish a database 
  8688.           connection. 
  8689.  
  8690.          DefineName_SQL_COMMANDS 
  8691.           Use this option to execute SQL commands after a connection has been 
  8692.           established but before your query has been run. You specify a list of 
  8693.           macros (which contain the actual commands) separated by spaces. A 
  8694.           command should begin with "-" if errors from it should be ignored. 
  8695.  
  8696.          DefineName_SQL_QUERY 
  8697.           This is the actual query itself. 
  8698.  
  8699.          DefineName_BLANK_FIELD 
  8700.           Normally a blank field will be displayed as blank. You may wish to 
  8701.           display '-' instead. Another possiblity is to display a 1 by 1 
  8702.           transparent gif so as to have table borders around blank fields look 
  8703.           better. 
  8704.  
  8705.           For even more control (probably rare requirement): 
  8706.  
  8707.             -  DefineName_BLANK_COLUMN_? 
  8708.                This allows you to specify different blank replacement values 
  8709.                for each column. 
  8710.  
  8711.          DefineName_DROP_BLANK_LINES 
  8712.           You can specify whether or not blank lines (or lines where all fields 
  8713.           are blank) are significant.  The default is 'Y' to drop blank lines, 
  8714.           specify 'N' to prevent this. 
  8715.  
  8716.          DefineName_NEWLINE_CHAR 
  8717.           This can be used to determine what newlines within fields should be 
  8718.           replaced with ("<BR>" by default). 
  8719.  
  8720.          DefineName_TAB_CHAR 
  8721.           Normally tabs are ignored by the import process.  This variable 
  8722.           allows you to replace them with something else. 
  8723.  
  8724.          DefineName_ASIS_TAGGING 
  8725.           This option can be used to adjust the conversion of what may be 
  8726.           problem characters (such as '<' in HTML). By default importing does 
  8727.           not handle/convert international characters such as umlauts to html 
  8728.           symbols but there is nothing preventing you from doing so. 
  8729.  
  8730.           This definition lists zero, one or more names as used on previous 
  8731.           "#AsIs SETUP" commands (seperated by whitespace). Clear this 
  8732.           definition to prevent all ASIS conversions. 
  8733.  
  8734.           Note that you will probably need to override this value (maybe others 
  8735.           as well) if you wished to expand any macros that the imported data 
  8736.           might contain (by default this is not done). 
  8737.  
  8738.          DefineName_DROP_LINE_COUNT 
  8739.           If we are dropping lines (TAB- command etc), then how many should be 
  8740.           dropped.  The default is one. 
  8741.  
  8742.          DefineName_BEFORE 
  8743.           You would probably only use this define if you didn't want to 
  8744.           generate a table at all. You may specify the string "{$Columns}" 
  8745.           which will get replaced with the number of fields to be displayed. If 
  8746.           this define is not used then you can use the following: 
  8747.  
  8748.             -  DefineName_TABLE_ATTRIBS 
  8749.                This value allows you to specify all HTML attributes of the 
  8750.                table apart from the number of columns. 
  8751.  
  8752.          DefineName_HEADER 
  8753.           This is used to control the "code" which handles the "heading" 
  8754.           record, <B>this does not have to be a html table</B>. You can specify 
  8755.           the string {$Column?} to represent a fields value (? = number of 
  8756.           field where 1 is the first). 
  8757.  
  8758.           If this define is not used then you can use the following: 
  8759.  
  8760.             -  DefineName_HEADING_COLUMNS 
  8761.                This value allows you to specify the column (HTML "<TH>" tags) 
  8762.                information to change alignment or colours of columns. This 
  8763.                value becomes the default for all columns. 
  8764.  
  8765.             -  DefineName_HEADING_COLUMN_? 
  8766.                This value allows you to specify the column (HTML "<TH>" tags) 
  8767.                information to change alignment or colours of specific columns. 
  8768.                Another use for this would be to specify the width of a column. 
  8769.                This value is only used for column number '?'. 
  8770.  
  8771.             -  DefineName_HEADING_BEFORE_DATA 
  8772.                This value allows you to specify some text to be placed in front 
  8773.                of the fields data, for example if you wish to change the font 
  8774.                size for each column you might used the value "<FONT SIZE=-1>". 
  8775.                This value becomes the default for all columns. 
  8776.  
  8777.             -  DefineName_HEADING_BEFORE_DATA_? 
  8778.                This value allows you to specify leading data on a column by 
  8779.                column basis. 
  8780.  
  8781.             -  DefineName_HEADING_AFTER_DATA 
  8782.                This value allows you to specify some text to be placed after 
  8783.                the fields data, for example if you wish to change the font size 
  8784.                for each column you might used the value "</FONT>" to close the 
  8785.                previous font tag. This value becomes the default for all 
  8786.                columns. 
  8787.  
  8788.             -  DefineName_HEADING_AFTER_DATA_? 
  8789.                This value allows you to specify trailing data on a column by 
  8790.                column basis. 
  8791.  
  8792.          DefineName_RECORD 
  8793.           This is used to control the "code" for each record, <B>this does not 
  8794.           have to be a html table</B>. You would definately define this option 
  8795.           if you didn't want a html table, you might wish to create s series of 
  8796.           #defines or maybe you are not generating html at all and need to 
  8797.           generate an IPF table. You can specify the string {$Column?} to 
  8798.           represent a fields value (? = number of field where 1 is the first). 
  8799.  
  8800.           If this define is not used then you can use the following: 
  8801.  
  8802.             -  DefineName_RECORD_COLUMNS 
  8803.                This value allows you to specify the column (HTML "<TD>" tags) 
  8804.                information to change alignment or colours of columns. This 
  8805.                value becomes the default for all columns. 
  8806.  
  8807.             -  DefineName_RECORD_COLUMN_? 
  8808.                This value allows you to specify the column (HTML "<TD>" tags) 
  8809.                information to change alignment or colours of specific columns. 
  8810.                Another use for this would be to specify the width of a column. 
  8811.                This value is only used for column number '?'. 
  8812.  
  8813.             -  DefineName_RECORD_BEFORE_DATA 
  8814.                This value allows you to specify some text to be placed in front 
  8815.                of the fields data, for example if you wish to change the font 
  8816.                size for each column you might used the value "<FONT SIZE=-1>". 
  8817.                This value becomes the default for all columns. 
  8818.  
  8819.             -  DefineName_RECORD_BEFORE_DATA_? 
  8820.                This value allows you to specify leading data on a column by 
  8821.                column basis. 
  8822.  
  8823.             -  DefineName_RECORD_AFTER_DATA 
  8824.                This value allows you to specify some text to be placed after 
  8825.                the fields data, for example if you wish to change the font size 
  8826.                for each column you might used the value "</FONT>" to close the 
  8827.                previous font tag. This value becomes the default for all 
  8828.                columns. 
  8829.  
  8830.             -  DefineName_RECORD_AFTER_DATA_? 
  8831.                This value allows you to specify trailing data on a column by 
  8832.                column basis. 
  8833.  
  8834.          DefineName_AFTER 
  8835.           Unless you are not creating a table you are unlikely to want to 
  8836.           change the codes that end the table. 
  8837.  
  8838.          DefineName_RECORD_FILTER 
  8839.           The contents of this variable should be one or more rexx expressions. 
  8840.  
  8841.           Normally all records are displayed. A filter can examine all column 
  8842.           variables and modify them or tell PPWIZARD to ignore the record.  The 
  8843.           filter is not called for the heading record. 
  8844.  
  8845.           The following rexx variables and functions are relevant: 
  8846.  
  8847.             -  Remove 
  8848.                If this variable is set to any non blank value then the record 
  8849.                will be dropped, the variables value is shown when debugging so 
  8850.                it is recommended that the value be the reason for dropping the 
  8851.                record. 
  8852.  
  8853.                If the contents starts with 'EOF:' then the current record and 
  8854.                ALL following are dropped. 
  8855.  
  8856.             -  Column.? 
  8857.                The "Column" array holds the data for each field (that you are 
  8858.                interested in) of the current record in the order you provided. 
  8859.                For example "Column.2" holds the 2nd column's data. Note that 
  8860.                "Column.0" holds the number of fields in the array. 
  8861.  
  8862.             -  Dropped.? 
  8863.                The "Dropped" array holds the data for each field (that you 
  8864.                dropped) of the current record in the order that they were 
  8865.                dropped. For example "Dropped.1" holds the first dropped field. 
  8866.                Note that "Dropped.0" holds the number of fields in the array. 
  8867.  
  8868.             -  ThisRecordsCodes 
  8869.                This variable gets initialized for each record with the value 
  8870.                that you defined (or allowed to default) for the 
  8871.                "DefineName_RECORD" option.  You can add to or modify this 
  8872.                record in any way. The value of "{$Column1}" gets replaced with 
  8873.                the contents of the rexx variable "Column.1" etc. 
  8874.  
  8875.                If all your records are processed the same way then you should 
  8876.                not need to modify this variable.  It is useful where you might 
  8877.                want the output (row of table) to look different depending on 
  8878.                the records data.  In some cases this can be better done by 
  8879.                updating the rexx "Column.?" array. 
  8880.  
  8881.                If you need multiple lines you can of course use "<?NewLine>" 
  8882.                where required. 
  8883.  
  8884.             -  WriteLineToTmpImportFile() 
  8885.                The passed data is written to the output file, any line feed 
  8886.                characters will indicate the end of a line. 
  8887.  
  8888.             -  RecordFilter 
  8889.                If you don't need to do any more filtering then you can clear 
  8890.                this variable.  This will improve performance. 
  8891.  
  8892.          DefineName_KEEP_TMP_FILE 
  8893.           Normally PPWIZARD keeps the temporary file it creates while importing 
  8894.           when debug is on. This option allows you to specify whether you do or 
  8895.           don't want the file kept (whether debug is on or off). 
  8896.  
  8897.          DefineName_DO_PASS_2 
  8898.           You would rarely wish to modify this value. It controls whether or 
  8899.           not the generated file is #included (pass 2), it's value defaults to 
  8900.           'Y'. You might wish to disable the processing if all your processing 
  8901.           can be done in pass one (for example you have imported a database 
  8902.           into memory. 
  8903.  
  8904.          DefineName_PROTECT_START 
  8905.           By default will be set to the value <?ProtectFromPpwStart>. If you 
  8906.           have filter code that wants to generate PPWIZARD commands then you 
  8907.           will need to override this value. Have a look at the multiple HTML 
  8908.           pages example. 
  8909.  
  8910.          DefineName_PROTECT_END 
  8911.            By default will be set to the value <?ProtectFromPpwEnd>. 
  8912.  
  8913.  Example - Import From MS Access 2000 (ODBC) 
  8914.  
  8915.  Here is some sample code which accesses a access database via ODBC and creates 
  8916.  a table of the contents (all default look and feel): 
  8917.  
  8918.       ;--- Specify the query (this determines the rows and their columns) ---------
  8919.       #define IMPORT_SQL_QUERY                                   \
  8920.               SELECT * FROM [FullDetails]                        \
  8921.               WHERE DeptSeqNo > 4  and DeptSeqNo < 11            \
  8922.               ORDER BY Department.DepartmentDescription
  8923.  
  8924.       ;--- Perform the SQL import -------------------------------------------------
  8925.       #define IMPORT_SQL_DATABASE   PHASE2
  8926.       #import "" SQL ""                                              \
  8927.               "{DepartmentDescription}Department's<BR>Description"   \
  8928.               "{DeptSeqNo}Department<BR>Sequence<BR>Number"
  8929.  
  8930.  The first parameter on the import command is normally a filename but for SQL 
  8931.  this parameter should be "". 
  8932.  
  8933.  The following shows how you could have executed a couple of commands prior to 
  8934.  the above query to generate the view that the above uses (not the best way, 
  8935.  but good for an example): 
  8936.  
  8937.       ;--- Define a query (probably better hardcoded in database but...) ----------
  8938.       #define DELETE_VIEW                                    \
  8939.               -drop table FullDetails
  8940.       #define CREATE_VIEW                                    \
  8941.               CREATE VIEW FullDetails AS                     \
  8942.               SELECT *                                       \
  8943.               FROM Department
  8944.  
  8945.       ;--- Do the above 2 commands after connecting to the database ---------------
  8946.       #define IMPORT_SQL_COMMANDS   \
  8947.               DELETE_VIEW           \
  8948.               CREATE_VIEW
  8949.  
  8950.  Example - Import From MS Excel Spread Sheet (ODBC) 
  8951.  
  8952.  This was tested under Windows 2000 using Excel 2000. You need to do the 
  8953.  following (otherwise it is like any other SQL import): 
  8954.  
  8955.        1. As for all ODBC imports you need to define the database as a "ODBC 
  8956.           Data Source". 
  8957.  
  8958.        2. The first row of the spread sheet needs to contain the SQL field 
  8959.           names. 
  8960.  
  8961.        3. You need to define the sql "table", you do this by defining a range 
  8962.           in Excel (Insert->Name). 
  8963.  
  8964.           Not being an Excel expert in my testing I hard coded a range, this 
  8965.           would be a problem if you added records which extended the number of 
  8966.           rows past the end of the range. You could make it cover a really 
  8967.           large number of rows and have the SQL query drop blank records or if 
  8968.           you know how to define the range better then please let me know! 
  8969.  
  8970.  Your query might look like: 
  8971.  
  8972.       SELECT * FROM ODBC_TABLE
  8973.  
  8974.  Example - Import From Comma Seperated Value File (ODBC) 
  8975.  
  8976.  This was tested under Windows 2000. You need to do the following (otherwise it 
  8977.  is like any other SQL import): 
  8978.  
  8979.        1. As for all ODBC imports you need to define the database as a "ODBC 
  8980.           Data Source". 
  8981.  
  8982.        2. The first line of the text file must contain the SQL field names. 
  8983.  
  8984.        3. The table name in your query is simply the name of the file you are 
  8985.           importing. 
  8986.  
  8987.  Your query might look like: 
  8988.  
  8989.       SELECT * FROM simple.csv WHERE AGE > 10 ORDER by AGE
  8990.  
  8991.  Example - Create One Page Per Record From Template) 
  8992.  
  8993.  In this case we wish to read an SQL database and generate a page for each 
  8994.  record using a template file. The template file refers to SQL data via 
  8995.  PPWIZARD macros which we will get the import to set up. 
  8996.  
  8997.       ;--- Specify database (WIN32 ACCESS DATABASE defined in Control Panel -> ODBC Data Sources) ---
  8998.       #define IMPORT_SQL_DATABASE   DefinedInControlPanelOdbc
  8999.  
  9000.       ;--- Specify the query (this determines the rows and their columns) ---------
  9001.       #define+ IMPORT_SQL_QUERY                                   \
  9002.                SELECT * FROM inventory_test                       \
  9003.                ORDER BY short_description
  9004.  
  9005.       ;--- Set up the format of the data the import will generate -----------------
  9006.       #define  IMPORT_HEADER
  9007.       #define  IMPORT_BEFORE
  9008.       #define  IMPORT_AFTER
  9009.       #define  IMPORT_PROTECT_START
  9010.       #define  IMPORT_PROTECT_END
  9011.       #define  IMPORT_RECORD                                            \
  9012.                ;--- Create PPWIZARD macros from SQL record's data ---  -\
  9013.                #define+  item            {$Column1}                    -\
  9014.                #define+  desc            {$Column2}                    -\
  9015.                #define+  price_r         {$Column3}                    -\
  9016.                #define+  price_o         {$Column4}                    -\
  9017.                #define+  desc_s          {$Column5}                    -\
  9018.                                                                        -\
  9019.                ;--- Create new file and include HTML template -------  -\
  9020.                #output   "<$item>.htm"   ;;New HTML file               -\
  9021.                #include  "master.htm"    ;;Include template            -\
  9022.                #output                   ;;Close file
  9023.  
  9024.       ;--- Perform the SQL import -------------------------------------------------
  9025.       #(
  9026.          #import "" SQL ""
  9027.                  "{product_no}Product Number"                ;;Column 1
  9028.                  "{short_description}Description (short)"    ;;Column 2
  9029.                  "{long_description}Description (long)"      ;;Column 3
  9030.                  "{price_4}Price 4"                          ;;Column 4
  9031.                  "{our_retail}Our Price"                     ;;Column 5
  9032.       #)
  9033.  
  9034.  
  9035. ΓòÉΓòÉΓòÉ 9.23.5. #import - T2H ΓòÉΓòÉΓòÉ
  9036.  
  9037. #import - T2H 
  9038.  
  9039. This is a text to HTML #import mode (please read the #import documentation 
  9040. before trying to understand this section. This is a recent addition so please 
  9041. consider this import type "beta code" 
  9042.  
  9043. Sometimes you will wish to simply convert a a number of text files to a equal 
  9044. number of html files.  In this case you will probably wish to use the /Template 
  9045. switch and create a template for your background colors, titles, headers and 
  9046. footers that you require. 
  9047.  
  9048. TEXT SPECIFIC DEFINITIONS/OPTIONS 
  9049.  
  9050. These definitions are specific to the "T2H" import mode.  If you can't 
  9051. understand how they work then I suggest you try using /debug or #debug to watch 
  9052. what variables the import uses etc. 
  9053.  
  9054.          DefineName_BEFORE 
  9055.           These tags are used to set up any tags before the file is included. 
  9056.           By default the font size is decreased and "<PRE>" (preformated text) 
  9057.           mode is set up.  Modify or set to blank (to do nothing) if you wish. 
  9058.  
  9059.          DefineName_AFTER 
  9060.           These tags are used to set up any tags that are required after the 
  9061.           file is included.  This normally undoes anything you started using 
  9062.           the previous define. 
  9063.  
  9064.          DefineName_BLANK_LINES_TO 
  9065.           When text is processed in "PRE" mode (see above) you want to leave 
  9066.           blank lines as they are.  If however you set up the before tags to be 
  9067.           "<P>" and cleared the after tags then you could convert blank lines 
  9068.           to "<P>, in this way a blank line indicates the end of a paragraph. 
  9069.  
  9070.          DefineName_ASIS_TAGGING 
  9071.           This option can be used to adjust the conversion of what may be 
  9072.           problem characters (such as '<' in HTML). By default importing does 
  9073.           not handle/convert international characters such as umlauts to html 
  9074.           symbols but there is nothing preventing you from doing so. 
  9075.  
  9076.           This definition lists zero, one or more names as used on previous 
  9077.           "#AsIs SETUP" commands (seperated by whitespace). Clear this 
  9078.           definition to prevent all ASIS conversions. 
  9079.  
  9080.           Note that you will probably need to override this value (maybe others 
  9081.           as well) if you wished to expand any macros that the imported data 
  9082.           might contain (by default this is not done). 
  9083.  
  9084.          DefineName_TAB_CHAR 
  9085.           Normally tabs are ignored by the import process.  This variable 
  9086.           allows you to replace them with something else. 
  9087.  
  9088.          DefineName_HTTP_LINK 
  9089.           The import mode looks for "http:" type web addresses and by default 
  9090.           converts the URL into a hypertext link.  You may not wish this so you 
  9091.           could clear this variable.  You might wish to simply highlight the 
  9092.           URL. 
  9093.  
  9094.          DefineName_FTP_LINK 
  9095.           The import mode looks for "ftp:" type ftp addresses and by default 
  9096.           converts the URL into a hypertext link.  Otherwise as per the 
  9097.           "_HTTP_LINK" option. 
  9098.  
  9099.          DefineName_RECORD_FILTER 
  9100.           This option allows you to modify records before they are written to 
  9101.           the intermediate file for processing.  The value you supply for this 
  9102.           option is a rexx expression that can be interpreted.  You could use 
  9103.           this to simply drop lines or the data can be modified by you. 
  9104.  
  9105.           The following rexx variables are relevant: 
  9106.  
  9107.             -  Remove 
  9108.                If this variable is set to any non blank value then the line 
  9109.                will be dropped, the variables value is shown when debugging so 
  9110.                it is recommended that the value be the reason for dropping the 
  9111.                record. 
  9112.  
  9113.                If the contents starts with 'EOF:' then the current record and 
  9114.                ALL following are dropped. 
  9115.  
  9116.             -  T2hLineNumber 
  9117.                This is the line number of the current line. Do not modify this 
  9118.                variable. 
  9119.  
  9120.             -  T2hFileLine 
  9121.                This is the line as read from the file. Do not modify this 
  9122.                variable. 
  9123.  
  9124.             -  T2hNewLine 
  9125.                This is the read in line converted to something that will 
  9126.                display well in HTML. May have had email addresses etc tagged. 
  9127.                This variable may be modified. 
  9128.  
  9129.             -  T2hFilter 
  9130.                If you don't need to do any more filtering then you can clear 
  9131.                this variable.  This will improve performance. 
  9132.  
  9133.          DefineName_PROTECT_START 
  9134.           By default will be set to the value <?ProtectFromPpwStart>. If you 
  9135.           have filter code that wants to generate PPWIZARD commands then you 
  9136.           will need to override this value. Have a look at the multiple HTML 
  9137.           pages example. 
  9138.  
  9139.          DefineName_PROTECT_END 
  9140.            By default will be set to the value <?ProtectFromPpwEnd>. 
  9141.  
  9142.  EXAMPLE 
  9143.  
  9144.  This example imports a file and also extends the translation it will perform 
  9145.  to include 2 international characters. For no real reason we will also prevent 
  9146.  email addresses becoming "mailto" links and simply highlight email addresses 
  9147.  in a different color. 
  9148.  
  9149.       ;--- Save current Autotag state, set up international conversion, restore state ---
  9150.       #AutoTagState +
  9151.       #AutoTag      '╨ö'    'ä'
  9152.       #AutoTag      '╨Ö'    'ë'              ;;Only 2 for this example
  9153.       #AsIs         SETUP  INTERNATIONAL_SYMBOLS
  9154.       #AutoTagState -
  9155.  
  9156.       ;--- Update option so as to use the international chars as well as usual conversions -
  9157.       #define T2H_ASIS_TAGGING     IMPORT_HTML_BASIC                   \
  9158.                                    IMPORT_HTML_BOXGRAPHIC_TO_BOXTEXT   \
  9159.                                    INTERNATIONAL_SYMBOLS
  9160.  
  9161.       ;--- Simply for demonstrate puroses, remove email links and make "olive" ---
  9162.       #define T2H_MAILTO_LINK      <FONT COLOR=OLIVE>{$Url}</FONT>
  9163.  
  9164.       ;--- Import the text file ---
  9165.       #import README.TXT T2H       ""
  9166.  
  9167.  
  9168. ΓòÉΓòÉΓòÉ 9.23.6. #import - WRAP ΓòÉΓòÉΓòÉ
  9169.  
  9170. #import - WRAP 
  9171.  
  9172. This is a specialised #import facility. 
  9173.  
  9174. WRAP DEFINITIONS/OPTIONS 
  9175.  
  9176. These definitions are specific to the "WRAP" import mode.  If you can't 
  9177. understand how they work then I suggest you try using /debug or #debug to watch 
  9178. what variables the import uses etc. 
  9179.  
  9180.          DefineName_DROP_BLANK_LINES 
  9181.           You can specify whether or not blank lines (or lines where all fields 
  9182.           are blank) are significant.  The default is 'Y' to drop blank lines, 
  9183.           specify 'N' to prevent this. 
  9184.  
  9185.          DefineName_TAB_CHAR 
  9186.           Normally tabs are ignored by the import process.  This variable 
  9187.           allows you to replace them with something else. 
  9188.  
  9189.          DefineName_ASIS_TAGGING 
  9190.           This option can be used to adjust the conversion of what may be 
  9191.           problem characters (such as '<' in HTML). By default importing does 
  9192.           not handle/convert international characters such as umlauts to html 
  9193.           symbols but there is nothing preventing you from doing so. 
  9194.  
  9195.           This definition lists zero, one or more names as used on previous 
  9196.           "#AsIs SETUP" commands (seperated by whitespace). Clear this 
  9197.           definition to prevent all ASIS conversions. 
  9198.  
  9199.           Note that you will probably need to override this value (maybe others 
  9200.           as well) if you wished to expand any macros that the imported data 
  9201.           might contain (by default this is not done). 
  9202.  
  9203.          DefineName_RECORD_FILTER 
  9204.           This option switches between 2 alternative ways of handling each line 
  9205.           of data as follows: 
  9206.  
  9207.             1. Option Not used 
  9208.                The macro you identify with the "DefineName" parameter is passed 
  9209.                each line in turn (line passed as the macro parameter "Line"). 
  9210.  
  9211.                The line is passed as a rexx statement which when executed will 
  9212.                restore the line. 
  9213.  
  9214.                Your macro can do anything it likes as it determines what if 
  9215.                anything get generated. 
  9216.  
  9217.             2. Option used 
  9218.                The rexx code that you specify is called for each line. 
  9219.  
  9220.                The following rexx variables are relevant: 
  9221.  
  9222.                  -  Remove 
  9223.                     If this variable is set to any non blank value then the 
  9224.                     line will be dropped, the variables value is shown when 
  9225.                     debugging so it is recommended that the value be the reason 
  9226.                     for dropping the record. 
  9227.  
  9228.                     If the contents starts with 'EOF:' then the current record 
  9229.                     and ALL following are dropped. 
  9230.  
  9231.                  -  WrapLineNumber 
  9232.                     This is the line number of the current line. Do not modify 
  9233.                     this variable. 
  9234.  
  9235.                  -  WrapLine 
  9236.                     This is the line as read from the file.  You would normally 
  9237.                     modify this variable. 
  9238.  
  9239.  Example of WRAP Import 
  9240.  
  9241.  Assume "PEOPLE.TXT" contains people data of the following form (each record 
  9242.  spans 3 lines with blank lines being ignored and little validation of data): 
  9243.  
  9244.      Harry
  9245.      18
  9246.      male
  9247.  
  9248.  
  9249.      Lisa
  9250.      20
  9251.      female
  9252.  
  9253.  Then we could create a simple HTML table as follows: 
  9254.  
  9255.      ;--- Define some macros to handle the imported data ----------------------
  9256.      #define InitMultiLineFieldImport             \
  9257.              #RexxVar RxFieldCount = 0
  9258.      #define TermMultiLineFieldImport                                                     \
  9259.              #if [RxFieldCount <> 0]                                                      \
  9260.                  #error "Incorrectly specified record, have <??RxFieldCount> of 3 fields" \
  9261.              #endif
  9262.      #define EachLine                                                                     \
  9263.              ;--- "read" the line (no blank lines) -------                                \
  9264.              #evaluate+ ''  ^ThisLine = strip({$Line})^                                   \
  9265.                                                                                           \
  9266.              ;--- Save information -----------------------                                \
  9267.              #RexxVar RxFieldCount + 1                                                    \
  9268.              #RexxVar RxField_<??RxFieldCount> = ThisLine                                 \
  9269.                                                                                           \
  9270.              ;--- If end of record then output it --------                                \
  9271.              #if [RxFieldCount = 3]                                                       \
  9272.                  <TR><TD><??RxField_1> is <??RxField_3> and <??RxField_2> years old       \
  9273.                  #RexxVar RxFieldCount = 0                                                \
  9274.              #endif
  9275.  
  9276.  
  9277.      ;--- Start the table -----------------------------------------------------
  9278.      <$InitMultiLineFieldImport>
  9279.      <BR>
  9280.      <CENTER>
  9281.      <TABLE COLS=3 BORDER=1>
  9282.  
  9283.      ;--- Import the data (leaving default at dropping blank lines) -----------
  9284.      #import "PEOPLE.TXT" WRAP EachLine
  9285.  
  9286.      ;--- End The table -------------------------------------------------------
  9287.      </TABLE>
  9288.      </CENTER>
  9289.      <$TermMultiLineFieldImport>
  9290.  
  9291.  
  9292. ΓòÉΓòÉΓòÉ 9.24. #include ΓòÉΓòÉΓòÉ
  9293.  
  9294. #include 
  9295.  
  9296. A #include can be used to include another (external) file for processing. This 
  9297. allows you to split a very large complicated html file into smaller logical 
  9298. pieces or more commonly to include standard 'header' files which contain all or 
  9299. most of the common definitions/text. This is a very common method for code 
  9300. reuse and is like the SSI (Server Side Includes) include "virtual" or "file" 
  9301. commands (but can also include fragments or parts of files and is less limiting 
  9302. on the external files location). 
  9303.  
  9304. You can nest to any level however each level adds to the number of open files 
  9305. (unless you use the /Inc2Cache switch) so in reality the nesting level is 
  9306. system dependant. Another problem may be that the rexx intrepreter will have 
  9307. its own limit on how far you can nest files. On OS/2 (and probably other 
  9308. operating systems) there are mechanisms for increasing the numbers of file 
  9309. handles if required. For example on OS/2 version 4 fixpack 6 onwards to 
  9310. increase the numbers of available handles by 30 add "SET SHELLHANDLESINC=30" to 
  9311. your config.sys file. 
  9312.  
  9313. You can call the included file anything you like (including the extension) 
  9314. however I recommend the use of conventions for extensions as this can make it 
  9315. easier to determine the context under which a file is expected to be used. The 
  9316. convention for extensions that I use are as follows: 
  9317.  
  9318.          .IT   - Internet Text  (source code) 
  9319.          .IH   - Internet Header (source code) 
  9320.          .HTM  - Generated HTML 
  9321.          .D    - Document Main  (source code) 
  9322.          .DH   - Document Header (source code) 
  9323.  
  9324.  It is possible for a header file to validate the release of a preprocessor if 
  9325.  it needs to use a feature which may not be available in older release, please 
  9326.  see the #require command. 
  9327.  
  9328.  Note that there are times when you might wish to share a file between 'C' code 
  9329.  and PPWIZARD, you might just wish access to some of the values defined with 
  9330.  #define statements. If you can't ensure that all commands (and their 
  9331.  parameters) that the 'C' code uses are valid in PPWIZARD then you could: 
  9332.  
  9333.        1. Conditionally include portions (example "#ifndef _PPWIZARD_"). Note 
  9334.           that "_PPWIZARD_" is automatically defined by PPWIZARD. 
  9335.  
  9336.        2. Use the #autotag commands to modify the contents on the file (on the 
  9337.           fly - not on disk!) to convert invalid statements to valid ones (bit 
  9338.           of a hack but would work). 
  9339.  
  9340.  It is also possible to include a part of the identified file if you can 
  9341.  identify some text which marks the start and end of the parts you wish. 
  9342.  
  9343.  The following locations are searched in order, using FindFileInPath(): 
  9344.  
  9345.        1. The Current Directory 
  9346.        2. /INCLUDEPATH.BR Any locations specified with the/IncludePath switch.
  9347.        3. PPWIZARD_INCLUDE environment variable.
  9348.        4. INCLUDE environment variable.
  9349.        5. PPWIZARD Install Directory 
  9350.  
  9351.  Syntax 
  9352.  
  9353.       [WhiteSpace]#include  ["|']FileName["|']  [["]Fragment["]]    OR
  9354.       [WhiteSpace]#include  <FileName>  [["]Fragment["]]
  9355.  
  9356.  The "FileName" specifies the file to be included. If the filename is or 
  9357.  contains #defined variables they will be replaced.  Note that the "<" & ">" 
  9358.  quoted form is to make it compatible with existing "C" headers so you can use 
  9359.  these if you require. 
  9360.  
  9361.  The optional "Fragment" parameter can be used to indicate the start and end of 
  9362.  the portion of an included file you wish to process.  The text must exist on 
  9363.  the line immediately before and immediately after the part you need.  Note 
  9364.  that the comparison is case sensitive on unfiltered text. This parameter 
  9365.  allows you to create a single include file from what might have been tens of 
  9366.  very small files (fragments).  I will use this parameter to contain all my 
  9367.  example code for my documentation. 
  9368.  
  9369.  Example 
  9370.  
  9371.       #include "common.ih"
  9372.  
  9373.       #include 'common.ih'     ^<CounterExample>^
  9374.  
  9375.       #include <common.h>
  9376.  
  9377.  
  9378. ΓòÉΓòÉΓòÉ 9.25. #Info ΓòÉΓòÉΓòÉ
  9379.  
  9380. #Info 
  9381.  
  9382. A #Info command allows you to display an informative message to the user. 
  9383.  
  9384. Similar commands are: 
  9385.  
  9386.        1. #Error 
  9387.        2. #Warning 
  9388.  
  9389.  Syntax 
  9390.  
  9391.       [WhiteSpace]#Info  [']InfoMessage[']
  9392.  
  9393.  The "InfoMessage" specifies the text to be displayed. 
  9394.  
  9395.  Example 
  9396.  
  9397.  Stupid example follows: 
  9398.  
  9399.       #Info "The value "fred" is fine."
  9400.  
  9401.  
  9402. ΓòÉΓòÉΓòÉ 9.26. #intercept ΓòÉΓòÉΓòÉ
  9403.  
  9404. #intercept 
  9405.  
  9406. This command allows you to filter a block of lines as they are read from the 
  9407. input file before ppwizard has done any real processing on them (for example 
  9408. before comments and blank lines have been removed). You can not nest intercept 
  9409. blocks. 
  9410.  
  9411. When defining the start of the block you specify the name of a macro containing 
  9412. the rexx code to be executed for each line. 
  9413.  
  9414. Great care must be taken if the intercept commands are used directly in an 
  9415. input file rather than via a macro as ppwizard will not detect the end of the 
  9416. block unless you are careful. When read from a file the end block command must 
  9417. be in the same case as the start block command (you can use this fact to your 
  9418. advantage if you wish to process ppwizard code which itself might contain the 
  9419. command!). When the end block command appears outside of a macro not only must 
  9420. be case be correct but the line must NOT have any inline comments. 
  9421.  
  9422. The rexx code is passed the "current" line in the FileLine rexx variable. 
  9423.  
  9424. The rexx code may modify the line and can include "<?NewLine>" codes to cause 
  9425. line breaks in the generated output file. If you had used newline codes 
  9426. ("d2c(10)") instead then any generated ppwizard commands after the first 
  9427. newline will be executed but these will not cause newlines to be generated in 
  9428. the output file. 
  9429.  
  9430. Syntax 
  9431.  
  9432.     [WhiteSpace]#intercept  [["]MacroContainingCodeName["]]
  9433.  
  9434. If the single parameter exists then this marks the start of the block, if 
  9435. missing it marks the end of the block. To start the block you need to supply 
  9436. the name of the macro that contains the transformation code. 
  9437.  
  9438. Example #1 
  9439.  
  9440. Silly example but shows the basics: 
  9441.  
  9442.     ;--- Define the rexx code ---
  9443.     #DefineRexx DoubleUp
  9444.                 ;--- Stupid example to create 2nd line based on that from file ---
  9445.                 FileLine = Fileline || '<?NewLine>   2nd Copy=>' || FileLine;
  9446.     #DefineRexx
  9447.  
  9448.     ;--- Start block / 3 lines / End block ----
  9449.     #IntercepT DoubleUp
  9450.       aaaa
  9451.       bbbb
  9452.       cccc
  9453.     #IntercepT
  9454.  
  9455. You should note the leading whitespace that was not removed on the second 
  9456. lines. 
  9457.  
  9458. Example #2 
  9459.  
  9460. This shows how (bit primative maybe) you could use the existing example 
  9461. inclusion macros but ensure that long lines get wrapped (this might allow 
  9462. source code displayed in a browser to be printed without losing line ends). 
  9463.  
  9464.     ;--- Configuration ----------------------------------------------------------
  9465.     #define     SPLIT_MAX_POS        90
  9466.     #define     SPLIT_MIN_POS        <$SPLIT_MAX_POS>-30       ;;Look back for space how far
  9467.     #define     SplitEndOld          <FONT COLOR="RED"><<<(line continued)</FONT>
  9468.     #define     SplitStartNew        <FONT COLOR="RED">>>></FONT>
  9469.     #define     SplitStartNewChars   3         ;;Represents space used in chars
  9470.  
  9471.     ;--- Define the rexx code ------------------------------------------------------------------------------------------------------------
  9472.     #DefineRexx BreakupLongLines
  9473.                 ;--- Incorrect packing would probably occur due to macros -------
  9474.                 #Option PUSH AllowPack=NO
  9475.  
  9476.                 ;--- QUICK check to see if any change required ------------------
  9477.                 if length(FileLine) > <$SPLIT_MAX_POS> then
  9478.                 do
  9479.                    ;--- Work out indenting of this line -------------------------
  9480.                    NsPos = verify(FileLine, '2009'x);        ;;Skip past spaces and tabs
  9481.                    if  NsPos <= 1 then
  9482.                        LineIndent = '';                      ;;No indent
  9483.                    else
  9484.                        LineIndent = left(FileLine, NsPos-1); ;;Use same whitespace (to ensure same tabs/spaces)
  9485.  
  9486.                    ;--- Fudge set indent ----------------------------------------
  9487.                    LineIndent = copies(' ', 4) || LineIndent;
  9488.  
  9489.                    ;--- Now set up line breaks ----------------------------------
  9490.                    Left   = '';
  9491.                    Right  = FileLine;
  9492.                    MinLng = <$SPLIT_MIN_POS>;
  9493.                    MaxLng = <$SPLIT_MAX_POS>;
  9494.                    do while length(Right) > MaxLng
  9495.                        ;--- Get left part of long line (try to break at space) --
  9496.                        LeftBit = left(Right, MaxLng);
  9497.                        SpcPos  = lastpos(' ', LeftBit);
  9498.                        if SpcPos >= MinLng then
  9499.                           BreakPos = SpcPos;           ;;Break at the space (Note I decided to not trim whitespace either side)
  9500.                        else
  9501.                           BreakPos = MaxLng;           ;;Can't break at a space
  9502.  
  9503.                        ;--- Need to split the line further ----------------------
  9504.                        Left  = Left || left(Right, BreakPos) || '*LineBreak*' || LineIndent || '*LineRest*';
  9505.                        Right = substr(Right, BreakPos+1);
  9506.  
  9507.                        ;--- Take care of 3 added chars that mark line continuation ---
  9508.                        MinLng = <$SPLIT_MIN_POS> - <$SplitStartNewChars>;
  9509.                        MaxLng = <$SPLIT_MAX_POS> - <$SplitStartNewChars>;
  9510.                    end;
  9511.                    FileLine = Left || Right;
  9512.                 end;
  9513.                 #Option POP
  9514.     #DefineRexx
  9515.  
  9516.     ;--- After "<" and other chars converted, translate markers to tags etc -----
  9517.     #AutoTagState +
  9518.     #AutoTag      '*LineBreak*'    '<$SplitEndOld $$SQx2><?Newline>'
  9519.     #AutoTag      '*LineRest*'     '<$SplitStartNew $$SQx2>'
  9520.     #AsIs         SETUP  FixLineContinuation
  9521.     #AutoTagState -
  9522.  
  9523.  
  9524.     ;--- Include header for example support -------------------------------------
  9525.     #include "HTMLPRE.IH"
  9526.  
  9527.     ;--- Include the example (long lines get wrapped) ---------------------------
  9528.     #IntercepT "BreakupLongLines"      ;;Note following line must be not be too long!!!!!
  9529.     <$ExampleFile FILE="2.in" STATE=REMEMBER ASIS=FixLineContinuation>
  9530.     #IntercepT
  9531.  
  9532.  
  9533. ΓòÉΓòÉΓòÉ 9.27. #MacroSpace ΓòÉΓòÉΓòÉ
  9534.  
  9535. #MacroSpace 
  9536.  
  9537. A #MacroSpace command allows you to add or drop rexx procedures from the rexx 
  9538. macro space.  This can be useful if you have some rexx code which you 
  9539. frequently call in #if or #Evaluate commands as they should execute faster if 
  9540. they are available in the macro space. 
  9541.  
  9542. Syntax 
  9543.  
  9544.     [WhiteSpace]#MacroSpace  ["]Command["]  ["]RexxSourceFile["]  [["]FunctionName["] ]
  9545.  
  9546. The "Command" should be "ADD" to add to the macro space or "DROP" to remove. 
  9547. It is not an error to ADD or DROP the same code more than once (even in a row). 
  9548. Also note that unless you perform a drop when you have finished using it it 
  9549. will take up space until you reboot OS/2. 
  9550.  
  9551. The "RexxSourceFile" is the name of a rexx source file. It should be a relative 
  9552. or absolute filename that currently exists. The path is not searched. 
  9553.  
  9554. If the optional "FunctionName" is not supplied then the function name is the 
  9555. "RexxSourceFile" without path or extension. 
  9556.  
  9557. Example 
  9558.  
  9559.     ;--- Load macro (routine called "ConfigInf" - any case) -----------------
  9560.     #MacroSpace   ADD    "CMD\CONFIGINF.CMD"
  9561.  
  9562.     #if ConfigInf('TCPIP_ADDRESS') = ''
  9563.         #Error "A TCPIP address is not available...."
  9564.     #endif
  9565.  
  9566.  
  9567. ΓòÉΓòÉΓòÉ 9.28. #NextId ΓòÉΓòÉΓòÉ
  9568.  
  9569. #NextId 
  9570.  
  9571. The #NextId command is designed to make it easy for you to generate code (for 
  9572. example rexx) with global variable names (rexx or ppwizard variables) that will 
  9573. not clash with others of the same name. It does this by creating a unique 
  9574. namespace. 
  9575.  
  9576. For example you may have a global variable called "string", it may be used in a 
  9577. number of locations (including called subroutines), if no care is taken you may 
  9578. "corrupt" the value. Now in rexx you could use the "procedure" command however 
  9579. there are reasons why you would not want to use it. This command allows you to 
  9580. call the variable by the name "@@string" and have the '@@' (or whatever 
  9581. characters you choose) replaced with a unique identifier. 
  9582.  
  9583. Note that there is only ever one ID in use at any time. Apart from the obvious 
  9584. use of having short unique variable names without risk of clashing with those 
  9585. defined elsewhere in your code you can also protect yourself from clashing with 
  9586. variables that ppwizard uses. 
  9587.  
  9588. Syntax #1 
  9589.  
  9590.     [WhiteSpace]#NextId  ["]ON["] | ["]OFF["]
  9591.  
  9592. This format of the command is to turn OFF (the default state) or ON the Next ID 
  9593. processing state. When turned on, processing resumes with the same counter and 
  9594. other information as specified when processing was turned off. 
  9595.  
  9596. Syntax #2 
  9597.  
  9598.     [WhiteSpace]#NextId  [["]ToReplace["]  [["]IdMask["]  [["]Counter["]]]]
  9599.  
  9600. This form of the command turns on Next ID processing. 
  9601.  
  9602. The "ToReplace" parameter can be any string (the default being "@@"). This 
  9603. string will be replaced in any line read from a file. A value of "" can be used 
  9604. to indicate that the last used or default value should be used. You must 
  9605. carefully pick this value so that you will never use it in your source code for 
  9606. any other reason (such as in a literal). The use of <?xXX> codes is one way of 
  9607. handling the odd occurance of the string when it is not a Next ID marker. 
  9608.  
  9609. The "IdMask" parameter is used to define how the replacement value should look. 
  9610. The mask would normally contain one "*" character to indicate where the unique 
  9611. number should be placed. A value of "" can be used to indicate that the last 
  9612. used or default should be used. PPWIZARD always adds an underscore to the end 
  9613. of a mask, this is to reduce the chance that they may clash with your normal 
  9614. variables! For example you could specify "GV*" which would generate "GV1_", 
  9615. "GV2_" etc. 
  9616.  
  9617. The "Counter" parameter can be used to supply an initial value for the counter 
  9618. (an integer). It is up to you to ensure that you either change the mask or 
  9619. don't reuse a number. 
  9620.  
  9621. Example 
  9622.  
  9623. The following shows some rexx fragments where I am using Next ID processing to 
  9624. ensure that each routine has it's own variables (which other routines don't 
  9625. also use). 
  9626.  
  9627.     ;=================
  9628.     Function1:
  9629.     ;=================
  9630.        #NextId
  9631.        #define @@FRED ...
  9632.        parse arg @@Parm1, @@Parm2
  9633.        ...
  9634.        @@Result = Function1(1, 2)
  9635.        return(@@Result || @@Parm1 || <$@@FRED>)
  9636.  
  9637.     ;=================
  9638.     Function2:
  9639.     ;=================
  9640.        #NextId
  9641.        #define @@FRED ...
  9642.        parse arg @@Parm1, @@Parm2
  9643.        ...
  9644.        @@Result = ...
  9645.        return(@@Result)
  9646.  
  9647. Note that the ppwizard variable "FRED" and the rexx variables "Parm1" and 
  9648. "Parm2" actually have different names between "function1" and " function2" and 
  9649. therefore do not overwrite each overs values. 
  9650.  
  9651.  
  9652. ΓòÉΓòÉΓòÉ 9.29. #OnExit ΓòÉΓòÉΓòÉ
  9653.  
  9654. #OnExit 
  9655.  
  9656. This command allows you to register some text which after all other processing 
  9657. is itself processed as if it were read from a file as well as specifying a 
  9658. command to be executed after ppwizard has successfully processed the file. 
  9659.  
  9660. This command is useful in standard header files where rather than requiring a 
  9661. user to use a macro before exiting it can be done automatically. An example of 
  9662. this might be in a common html header file where you use this command to 
  9663. automatically generate a standard footer at the end of your html. 
  9664.  
  9665. The processing does not occur if a fatal error was detected. 
  9666.  
  9667. Syntax 
  9668.  
  9669.     [WhiteSpace]#OnExit  [#Slot] TheText
  9670.  
  9671. The "Slot" parameter should be: 
  9672.  
  9673.          A number from 1 to 100 
  9674.           A slot (except the special slot 50) can not be reused. It is used to 
  9675.           enable you to tell PPWIZARD the order that 'TheText' should be 
  9676.           executed. To have your exit processing occur first use slot 1, to 
  9677.           have your processing last use slot 100. Processing occurs in order of 
  9678.           slot number and in the case of slot 50 in the order they were 
  9679.           specified. 
  9680.  
  9681.          Omitted 
  9682.           If not supplied a slot number of 50 is used. 
  9683.  
  9684.          The text "EXEC" 
  9685.           This is a ppwizard command which performs exactly the same function 
  9686.           as the /Validate switch. 
  9687.  
  9688.  The "TheText" parameter can contain macro references but it's meaning depends 
  9689.  on the slot parameter: 
  9690.  
  9691.          "EXEC" was used 
  9692.           Any macros are immediately expanded and information stored. Format is 
  9693.           as specified for the /Validate switch. 
  9694.  
  9695.          Normal Processing 
  9696.           Any macros and parameters etc are not expanded until exit processing 
  9697.           occurs. 
  9698.  
  9699.  If you require a specific slot number in code that others might use I suggest 
  9700.  that the slot number be configurable. Any change and all risks are then up to 
  9701.  the user. 
  9702.  
  9703.  EXAMPLE 
  9704.  
  9705.  The following is used in one of my header files: 
  9706.  
  9707.       ;--- Register checking macro ---
  9708.       #OnExit  <$NestingCheck>
  9709.  
  9710.  The following would generate an error as slot 1 is being reused: 
  9711.  
  9712.       ;--- Register checking macro ---
  9713.       #OnExit #1 <$NestingCheck1>
  9714.       #OnExit #1 <$NestingCheck2>
  9715.  
  9716.  
  9717. ΓòÉΓòÉΓòÉ 9.30. #option ΓòÉΓòÉΓòÉ
  9718.  
  9719. #option 
  9720.  
  9721. This command is used to change the state of all the PPWIZARD options that you 
  9722. might wish to modify within a compile.  Other options which are global and 
  9723. can't be modified can be specified on the command line. 
  9724.  
  9725. The command allows you to save and restore the current state as well as update 
  9726. one or more options at a time. 
  9727.  
  9728. Most if not all options allow you to reset to the default value, this can 
  9729. either be a value determined by PPWIZARD or overriden by you with the /option 
  9730. switch. Note that to restore the original values you should use the 'PUSH' and 
  9731. 'POP' options. 
  9732.  
  9733. Note that since you can define options using the /option switch and default 
  9734. switches can be set up in the environment, you can simply override any PPWIZARD 
  9735. defaults you don't like without having to change your source code (or even your 
  9736. command line!). 
  9737.  
  9738. Syntax #1 - Saving + Restoring State 
  9739.  
  9740.     [WhiteSpace]#option  PUSH | POP
  9741.  
  9742. This form of the command saves or restores all options controlled by the 
  9743. #option command.  This allows you to make the required option changes and 
  9744. restore the original situation if required (for example in a header file). 
  9745.  
  9746. Syntax #2 - Setting An Option 
  9747.  
  9748.     [WhiteSpace]#option  OptionName[WhiteSpace]=[WhiteSpace]["]NewValue["]  ...
  9749.  
  9750. You may have any number of options specified on one statement. While not shown 
  9751. in the syntax diagram above you can specify "PUSH" any number of times as well. 
  9752. The following options are currently available: 
  9753.  
  9754.          AllowPack 
  9755.          AllowSpell 
  9756.          AtChangeType 
  9757.          CsReplacement 
  9758.          DebugLevel 
  9759.          DefineMacroReplace 
  9760.          ExtraIndent 
  9761.          ExpandX 
  9762.          HashPrefix 
  9763.          KeepIndent 
  9764.          LeaveBlankLines 
  9765.          LineComment 
  9766.          LineContinuation 
  9767.          MacroParmTags 
  9768.          ParmVal 
  9769.          Replace 
  9770.          ReplacementTags 
  9771.          Tabs 
  9772.          Warnings 
  9773.          WhiteSpace 
  9774.  
  9775.  You may also wish to have a look at the rexx "OptionGet()" and "OptionSet()" 
  9776.  routines. 
  9777.  
  9778.  Example 
  9779.  
  9780.       #option PUSH                 ;;Save Current state (we don't need to know what it was - EXCEPT '#' = command prefix!)
  9781.       #define FRED   ****
  9782.       <$Fred>                      ;;Fred will be subsituted here
  9783.  
  9784.       #option ReplacementTags="[]$?"
  9785.       [$Fred]                      ;;Fred will be substituted here
  9786.       <$Fred>                      ;;Fred will NOT be subsituted here
  9787.       #option POP                  ;;Restore original state
  9788.  
  9789.  
  9790. ΓòÉΓòÉΓòÉ 9.30.1. AllowPack ΓòÉΓòÉΓòÉ
  9791.  
  9792. AllowPack=OnOrOff 
  9793.  
  9794. This #option command allows you indicate lines of code which are not allowed to 
  9795. be packed. The default is that packing is allowed. 
  9796.  
  9797. This option can not be used to turn packing on, it simply identifies areas that 
  9798. should not be packed when packing is enabled. Packing can be enabled using the 
  9799. /Pack switch when generating rexx code or when you begin a #DefineRexx block. 
  9800.  
  9801. This command is useful where there are some non-obvious reasons why code should 
  9802. not be packed, for example if a bug in the rexx interpreter causes the code to 
  9803. fail when packed. 
  9804.  
  9805. If the "OnOrOff" parameter is empty then it defaults to the current default 
  9806. value, otherwise one of the following is expected:
  9807.  
  9808.                 ON
  9809.                 OFF
  9810.                 YES
  9811.               NO
  9812.  
  9813.  
  9814. ΓòÉΓòÉΓòÉ 9.30.2. AllowSpell ΓòÉΓòÉΓòÉ
  9815.  
  9816. AllowSpell=OnOrOff 
  9817.  
  9818. This #option command allows you indicate lines of code which are or are not 
  9819. allowed to be spell checked. The default is that spelling is allowed. 
  9820.  
  9821. This option would allow you to indicate that spelling should not occur when you 
  9822. generate javascript etc. 
  9823.  
  9824. Note that there are currently some inter related restrictions: 
  9825.  
  9826.        1. You can only turn spell checking on or off for whole lines. 
  9827.  
  9828.        2. This option may not work in a macro depending on your macro. 
  9829.  
  9830.  If the "OnOrOff" parameter is empty then it defaults to the current default 
  9831.  value, otherwise one of the following is expected:
  9832.  
  9833.                 ON
  9834.                 OFF
  9835.                 YES
  9836.               NO
  9837.  
  9838.  
  9839. ΓòÉΓòÉΓòÉ 9.30.3. AtChangeType ΓòÉΓòÉΓòÉ
  9840.  
  9841. AtChangeType=["]ChangeType["] 
  9842.  
  9843. This #option command lets you alter the way #AsIs and #AutoTag commands will 
  9844. perform replacements. The default method is a simple case sensitive replacement 
  9845. of text. 
  9846.  
  9847. Note that this command actually changes the way the #AutoTag stores the change 
  9848. and will only affect the replacement of those changes defined after this option 
  9849. was used. 
  9850.  
  9851. This command allows new alternative search and replace mechanisms to be slotted 
  9852. in without affecting any existing ones (clashing syntax etc). This method was 
  9853. chosen so that PPWIZARD could remain as fast as possible (it is written in rexx 
  9854. and so keeping performance reasonable sometimes takes compromises). 
  9855.  
  9856. The "ChangeType" parameter can be one of the following: 
  9857.  
  9858.        1. "" (blank) 
  9859.           This returns to the "default" mode. 
  9860.  
  9861.        2. CaseSensitive 
  9862.           The ReplaceString() routine is used. This is PPWIZARD's default mode 
  9863.           as it's also the fastest. 
  9864.  
  9865.        3. CaseInsensitive 
  9866.           The ReplaceStringCI() routine is used. 
  9867.  
  9868.        4. Fixed 
  9869.           The CompareReplaceFixed() routine is used. 
  9870.  
  9871.  If you have some fantastic free PURE REXX search and replace code then I can 
  9872.  include it as a new PPWIZARD extension if you send me the code! 
  9873.  
  9874.  Example 1 
  9875.  
  9876.       #AutoTag "AAAA"   "XXXX"           ;;Change upper case "AAAA" only (assuming default mode)
  9877.  
  9878.       ;--- Use ReplaceStringCI() ---------------
  9879.       #option  PUSH AtChangeType=CaseInsensitive
  9880.       #AutoTag "BBBB"   "YyYy"           ;;Change "bbbb" in any case
  9881.       #AutoTag "CCCC"   "({*})"          ;;If "cccc" in any case is found then surround it by brackets
  9882.  
  9883.       ;--- Use CompareReplaceFixed() -----------
  9884.       #option AtChangeType="FIXED"
  9885.       #AutoTag      '@=,1=^HTML^@=,5=+x+'       'REM CS->@$1,*;'        ;;Case sensitive compare for "HTML" then "x"
  9886.       #AutoTag      '!i@=,1=^HTML^!S@=,-1=+x+'  'REM CI->@$1,*;'        ;;Case insensitive comapre for "HTML" + sensitive compare for "x"
  9887.       #AutoTag      '!L!i@=,1=^HTML^!S@=,5=+x+' 'REM CI+spaces->@$1,*;' ;;Same as above but ignoring whitespace (leading)
  9888.       #option  POP                       ;;Restore mode (PUSH/POP useful where original mode unknown etc)
  9889.  
  9890.  
  9891. ΓòÉΓòÉΓòÉ 9.30.4. CsReplacement ΓòÉΓòÉΓòÉ
  9892.  
  9893. CsReplacement=OnOrOff 
  9894.  
  9895. This #option command lets you alter the way ppwizard performs macro 
  9896. replacement. By default ppwizard macro names and macro parameter names are case 
  9897. insensitive. 
  9898.  
  9899. This command allows you to specify that case matters. This will give ppwizard 
  9900. more flexability when generating certain languages (such as XML or XHTML). 
  9901.  
  9902. Note that Standard Definitions and rexx variable names are always case 
  9903. insensitive. 
  9904.  
  9905. You will need to be careful how you use this option (if not used early in the 
  9906. piece). Any macros created while this option was off were created in upper 
  9907. case, while any parameters within the definition don't matter until the 
  9908. replacement takes place. 
  9909.  
  9910. If the "OnOrOff" parameter is empty then it defaults to the current default 
  9911. value, otherwise one of the following is expected:
  9912.  
  9913.                 ON
  9914.                 OFF
  9915.                 YES
  9916.               NO
  9917.  
  9918.  Example 
  9919.  
  9920.       #option CsReplacement=ON
  9921.       #define AAAA   1111
  9922.       #define aaaa   2222
  9923.  
  9924.       ;--- Test Macro Replacement ---
  9925.       1. <$AAAA>     ;;Expect "1111"
  9926.       2. <$aaaa>     ;;Expect "2222"
  9927.       3. <$AAaa>     ;;Expect ppwizard to fail here
  9928.  
  9929.  
  9930. ΓòÉΓòÉΓòÉ 9.30.5. DebugLevel ΓòÉΓòÉΓòÉ
  9931.  
  9932. DebugLevel=["]Command1,Command2,...["] 
  9933.  
  9934. This #option command allows you to modify the output generated by /debug and 
  9935. #debug. 
  9936.  
  9937. PPWIZARD generates quite a bit of debug information when debug is on, this is 
  9938. fine for small source files but could easily become hundreds of thousands of 
  9939. lines in more complex situations.  If you are debugging a specific issue you 
  9940. may want to turn off debugging of unrelated events (this could also speed 
  9941. things up).  Of course being more selective about placement of #debug commands 
  9942. is another very good option (why debug the whole process?). 
  9943.  
  9944. Note that you can turn off almost all debugging output, doing so could make it 
  9945. very difficult to determine what is going on as statements such as #AutoTag 
  9946. could transform lines in what appears to be a magical manner. It's up to you to 
  9947. determine what level you require. 
  9948.  
  9949. The Commands 
  9950.  
  9951. You may specify any numbers of commands, each separated by a comma. A command 
  9952. may begin with a '-' (to turn off) or '+' (turn on - default) the debug 
  9953. facility.  By default all debug output is generated. 
  9954.  
  9955. Valid debug facilities are: 
  9956.  
  9957.          ALL 
  9958.           This represents all debug options. This less "USER?" is the default 
  9959.           situation when PPWIZARD starts. 
  9960.  
  9961.          AFTERREPLACE 
  9962.           All display of lines after some sort of replacement such as that by 
  9963.           #AsIs commands or your macros. 
  9964.  
  9965.          ASIS 
  9966.           Debug the #AsIs command. 
  9967.  
  9968.          AUTOTAG 
  9969.           Debug the #AutoTag command. 
  9970.  
  9971.          CONDITIONAL 
  9972.           #if, #endif output etc. 
  9973.  
  9974.          DEFINING 
  9975.           Output related to defining variables/macros. 
  9976.  
  9977.          EVALUATE 
  9978.           This debugs PPWIZARD functions that can be used in #evaluate or #if 
  9979.           commands etc. 
  9980.  
  9981.          FOUNDVAR 
  9982.           Output to do with individual processing of your macros. 
  9983.  
  9984.          FOUNDVARPARMS 
  9985.           Output to do with individual processing of your macro's parameters. 
  9986.  
  9987.          FOUNDSTDVAR 
  9988.           Output to do with processing of individual Standard Macros. 
  9989.  
  9990.          IMPORT 
  9991.           Debug any IMPORT statements PPWIZARD performs.  This will also 
  9992.           automatically adjust "MACROVALORDEF". 
  9993.  
  9994.          INTERPRET 
  9995.           Debug any INTERPRET statements PPWIZARD performs.  PPWIZARD does not 
  9996.           trace all but will show ones from #if and #evaluate commands. 
  9997.  
  9998.          MACROVALORDEF 
  9999.           PPWIZARD allows some things to be defined via a macro, there is 
  10000.           usually a default value.  This debugs these situations. 
  10001.  
  10002.          OPTIONS 
  10003.           Any output related to #option command. 
  10004.  
  10005.          OPSYS 
  10006.           Debug commands executed by operating system. 
  10007.  
  10008.          QUOTING 
  10009.           Debug the calls that grab quoted values. 
  10010.  
  10011.          REXXVAR 
  10012.           Debug the #RexxVar command. 
  10013.  
  10014.          REXXTRACE 
  10015.           Turn on rexx's inbuilt tracing for the execution of any rexx code 
  10016.           that gets executed by commands such as #if, #evaluate and #import. 
  10017.           This can be quite extensive so you might want to turn it off or lower 
  10018.           its level (see below) for general debugging. The format of the output 
  10019.           is described below. 
  10020.  
  10021.           The PPWIZARD macro "REXXTRACE" can be used to control the level of 
  10022.           rexx debugging.  The default level is "INTERMEDIATES" with "RESULTS" 
  10023.           generating less output while still being useful. The value you 
  10024.           specified is used in the rexx "TRACE ???" command. 
  10025.  
  10026.           Preceeding the value with '?' (as in "?Results") turns on interactive 
  10027.           trace.  You can execute any rexx commands to display or modify 
  10028.           values. 
  10029.  
  10030.          SPELLING 
  10031.           Show all spelling related output? 
  10032.  
  10033.          USER1 & USER2 
  10034.           Nothing in ppwizard itself makes use of these debug states, you can 
  10035.           make use these for your own purposes. You can use these two flags 
  10036.           either as a number (ranging from 0 to 3) for as 2 options (on or 
  10037.           off). To test the current state you need to call IsDebugOn(). 
  10038.  
  10039.           The value of USER bit one is 1 and USER bit two is 2. 
  10040.  
  10041.           Note that you could define your own debug "flags" using "/define 
  10042.           depending on the type of debug. The disadvantage on using these bits 
  10043.           is the mimimum extra debug output is the contents of each line as it 
  10044.           is processed. 
  10045.  
  10046.  REXXTRACE Output 
  10047.  
  10048.  This debug output is supplied by the rexx interpreter. The output from Regina 
  10049.  is much inferior to that of OS/2 however it's still very useful. For an 
  10050.  alternative way of debugging rexx code have a look at the /$Trace switch. The 
  10051.  following can be used as a guide to understanding the output: 
  10052.  
  10053.          Every clause traced will be displayed with automatic formatting 
  10054.           (indentation) according to its logical depth of nesting and so on, 
  10055.           and the results (if requested) are indented an extra two spaces and 
  10056.           are enclosed in double quotation marks so that leading and trailing 
  10057.           blanks are apparent. 
  10058.  
  10059.          All lines displayed during tracing have a three-character prefix to 
  10060.           identify the type of data being traced.  The prefixes and their 
  10061.           definitions are the following: 
  10062.  
  10063.             -  *-* 
  10064.                Identifies the source of a single clause, that is, the data 
  10065.                actually in the program. 
  10066.  
  10067.             -  +++ 
  10068.                Identifies a trace message.  This can be the nonzero return code 
  10069.                from a command, the prompt message when interactive debug is 
  10070.                entered, an indication of a syntax error when in interactive 
  10071.                debug, or the traceback clauses after a syntax error in the 
  10072.                program. 
  10073.  
  10074.             -  >>> 
  10075.                Identifies the result of an expression (for TRACE R) or the 
  10076.                value assigned to a variable during parsing, or the value 
  10077.                returned from a subroutine call. 
  10078.  
  10079.             -  >.> 
  10080.                Identifies the value assigned to a placeholder during parsing. 
  10081.  
  10082.             -  >C> 
  10083.                The data traced is the name of a compound variable, traced after 
  10084.                substitution and before use, provided that the name had the 
  10085.                value of a variable substituted into it. 
  10086.  
  10087.             -  >F> 
  10088.                The data traced is the result of a function call. 
  10089.  
  10090.             -  >L> 
  10091.                The data traced is a literal (string or constant symbol). 
  10092.  
  10093.             -  >O> 
  10094.                The data traced is the result of an operation on two terms. 
  10095.  
  10096.             -  >P> 
  10097.                The data traced is the result of a prefix operation. 
  10098.  
  10099.             -  >V> 
  10100.                The data traced is the contents of a variable. 
  10101.  
  10102.  Example 
  10103.  
  10104.  Lets turn off all optional debugging except CONDITIONAL and OPTIONS: 
  10105.  
  10106.       #option DebugLevel=~-ALL,+CONDITIONAL,OPTIONS~
  10107.  
  10108.  
  10109. ΓòÉΓòÉΓòÉ 9.30.6. DefineMacroReplace ΓòÉΓòÉΓòÉ
  10110.  
  10111. DefineMacroReplace=OnOrOff 
  10112.  
  10113. This #option command allows you to modify the way #define and #DefineRexx 
  10114. commands are processed. 
  10115.  
  10116. Normally no replacement of any macros within it's parameters are performed. 
  10117. This has its good points (which is why it's the default) but at times you may 
  10118. wish to override this behavior.  Apart from anything else in some cases this 
  10119. may speed things up. 
  10120.  
  10121. If the "OnOrOff" parameter is empty then it defaults to the current default 
  10122. value, otherwise one of the following is expected:
  10123.  
  10124.                 ON
  10125.                 OFF
  10126.                 YES
  10127.               NO
  10128.  
  10129.  Example 
  10130.  
  10131.  
  10132.       #define  AAAA   ValueAAAAOld
  10133.       #define  BBBB   <$AAAA>          ;;Macro AAAA was not replaced
  10134.       #option  DefineMacroReplace=ON   ;;When #define command executes replace any references to macros straight away.
  10135.       #define  CCCC   <$AAAA>          ;;Macro AAAA was replaced
  10136.       #define+ AAAA   ValueAAAANew     ;;Change Value of "AAAA"
  10137.       #option DefineMacroReplace=''    ;;Set to the default value
  10138.  
  10139.       ;--- Use macros defined above -----------------------------------------------
  10140.       <$BBBB>                          ;;Will generate "ValueAAAANew"
  10141.       <$CCCC>                          ;;Will generate "ValueAAAAOld"
  10142.  
  10143.  Example - Overcoming PPWIZARD Hang 
  10144.  
  10145.  The following is a fragment of a rexx program that supports a number of 
  10146.  standard rexx operators (but not all). It is trying to build up a list of 
  10147.  valid operators to display if the user chooses an unsupported one. 
  10148.  
  10149.  Because of the fact that by default a #define does not replace macros the 
  10150.  following example would fail with an infinite loop (if the #option commands 
  10151.  were removed). 
  10152.  
  10153.       /*--- Now compare --------------------------------------------*/
  10154.       #define CompRepOperator                                    \
  10155.               when   sr_Operator = '{$Operator}' then           %\
  10156.                      srCompRc = sr_bit {$Operator} sr_CompWith; -\
  10157.               #ifndef CSR_ValidList                             -\
  10158.                       #define  CSR_ValidList  {$Operator}       -\
  10159.               #elseif                                           -\
  10160.                       ;--- Careful or this line causes infinite loop ---    -\
  10161.                       #define+ CSR_ValidList  <$CSR_ValidList>, {$Operator} -\
  10162.               #endif
  10163.       select
  10164.           /*--- Test for supported compare operators ---------------------------*/
  10165.           #option PUSH DefineMacroReplace="ON"   ;;Used push/pop - Making no assumptions about current state
  10166.           <$CompRepOperator Operator='='>
  10167.           <$CompRepOperator Operator='<>'>
  10168.           <$CompRepOperator Operator='=='>
  10169.           <$CompRepOperator Operator='\=='>
  10170.           #option POP
  10171.  
  10172.           /*--- Not Valid ------------------------------------------------------*/
  10173.           otherwise
  10174.               Die("Unsupported operator of '" || sr_Operator || "' used", 'ONLY "<$CSR_ValidList>" are valid');
  10175.       end;
  10176.  
  10177.  
  10178. ΓòÉΓòÉΓòÉ 9.30.7. ExtraIndent ΓòÉΓòÉΓòÉ
  10179.  
  10180. ExtraIndent=["]IndentCmd["] 
  10181.  
  10182. Whenever "KeepIndent" mode is on the current indent value is added to the start 
  10183. of each line. The default extra indent is none. 
  10184.  
  10185. The "IndentCmd" parameter is a rexx command which produces a string value which 
  10186. will be used for extra indenting. 
  10187.  
  10188. Example 
  10189.  
  10190. The following command would increase any indenting by 10 spaces for following 
  10191. lines: 
  10192.  
  10193.     #option ExtraIndent=^copies(' ', 10)^  KeepIndent=ON
  10194.  
  10195.  
  10196. ΓòÉΓòÉΓòÉ 9.30.8. ExpandX ΓòÉΓòÉΓòÉ
  10197.  
  10198. ExpandX=["]CompleteList["] 
  10199.  
  10200. Normally <?xXX> codes are only expanded just before the data is written to the 
  10201. file (ie "LATE"). 
  10202.  
  10203. You may wish to vary when the replacement occurs. You can choose "COMMAND" to 
  10204. have replacements occur when a PPWIZARD command's parameters are expanded or 
  10205. "EARLY" to expand early on lines that are not PPWIZARD commands. 
  10206.  
  10207. The CompleteList parameter is a complete list of all the locations you wish 
  10208. expandion to occur on (COMMAND,EARLY,LATE) or "NONE" to completely turn off the 
  10209. expansion or "" to use default state. 
  10210.  
  10211. Example 
  10212.  
  10213.     ;--- Turn off all expansion ---
  10214.     #option ExpandX="NONE"
  10215.  
  10216.     ;--- Expand everywhere --------
  10217.     #option ExpandX="EARLY,LATE,COMMAND"
  10218.  
  10219.     ;--- Just expand early --------
  10220.     #option ExpandX="EARLY"
  10221.  
  10222.  
  10223. ΓòÉΓòÉΓòÉ 9.30.9. HashPrefix ΓòÉΓòÉΓòÉ
  10224.  
  10225. HashPrefix=["]NewPrefix["] 
  10226.  
  10227. This #option command allows you to modify the characters which tell PPWIZARD 
  10228. that a line contains a ppwizard command.  The default is that PPWIZARD commands 
  10229. begin with '#'. 
  10230.  
  10231. The NewPrefix parameter if empty sets the default value or specifies the new 
  10232. character or characters that preceed all commands. 
  10233.  
  10234. This command is useful if the language or file you are processing already uses 
  10235. the '#' character for its own reasons.  Rather than using many <?HashPrefix> 
  10236. codes it is much easier to move PPWIZARD out of the way. 
  10237.  
  10238. Example 
  10239.  
  10240.     #include "FILE1.IH"
  10241.     #option   hashprefix='!'        ;;Set prefix to '!'
  10242.     !include "FILE2.IH"
  10243.     !option   hashprefix=''         ;;Set prefix to default value
  10244.     #include "FILE3.IH"
  10245.  
  10246.  
  10247. ΓòÉΓòÉΓòÉ 9.30.10. KeepIndent ΓòÉΓòÉΓòÉ
  10248.  
  10249. KeepIndent=OnOrOff 
  10250.  
  10251. This #option command lets you determine whether or not leading whitespace is 
  10252. removed from lines that are read from a file. 
  10253.  
  10254. If you wish to keep whitespace you can also use the ExtraIndent option to 
  10255. indent each line if you wish. 
  10256.  
  10257. An alternative to this command is to use "<?Space>" to create whitespace as 
  10258. required. 
  10259.  
  10260. If the "OnOrOff" parameter is empty then it defaults to the current default 
  10261. value, otherwise one of the following is expected:
  10262.  
  10263.                 ON
  10264.                 OFF
  10265.                 YES
  10266.               NO
  10267.  
  10268.  Example 
  10269.  
  10270.       #Option  keepindent=ON
  10271.          Want Indent on this line
  10272.          As well as this line
  10273.       #Option  keepindent=OFF
  10274.  
  10275.  Example - Alternative way 
  10276.  
  10277.  The way demonstrated here can make it easier to format your source code so 
  10278.  it's easy to read.  The following example will generate the same 2 lines as 
  10279.  the previous example: 
  10280.  
  10281.          <?Space>  Want Indent on this line
  10282.              <?Space>  As well as this line
  10283.  
  10284.  
  10285. ΓòÉΓòÉΓòÉ 9.30.11. LeaveBlankLines ΓòÉΓòÉΓòÉ
  10286.  
  10287. LeaveBlankLines=OnOrOff 
  10288.  
  10289. This #option command lets you determine whether or not blank lines are ignored. 
  10290. By default they are. 
  10291.  
  10292. If the "OnOrOff" parameter is empty then it defaults to the current default 
  10293. value, otherwise one of the following is expected:
  10294.  
  10295.                 ON
  10296.                 OFF
  10297.                 YES
  10298.               NO
  10299.  
  10300.  Example 
  10301.  
  10302.       #Option  LeaveBlankLines=ON      ;;Don't drop blank lines
  10303.  
  10304.  
  10305. ΓòÉΓòÉΓòÉ 9.30.12. LineComment ΓòÉΓòÉΓòÉ
  10306.  
  10307. LineComment=["]ASingleChar["] 
  10308.  
  10309. This #option command allows you to specify an alternative character (to ';') 
  10310. for starting comments. 
  10311.  
  10312. If NULL is specified for ASingleChar then comment removal is disabled. An empty 
  10313. value will set it back to the default, otherwise the character becomes the new 
  10314. comment character. The same character doubled up becomes the inline comment 
  10315. indicator. 
  10316.  
  10317. Example 
  10318.  
  10319.     ;--- This is a comment ---
  10320.     <B>         ;;Make the following text appear bold
  10321.     #option linecomment='@'
  10322.     </B>        @@Remove the bold attribute
  10323.  
  10324.     @--- This is a comment ---
  10325.  
  10326.     ;--- This is NO LONGER a comment ---
  10327.  
  10328.     @--- Restore default value (without hard coding it) ---
  10329.     #option linecomment=''             @@Better way is to use push/pop
  10330.  
  10331.     ;--- This is a comment (no comments after the following line executed) ---
  10332.     #option linecomment='NULL'         ;;Better way is to use push/pop
  10333.  
  10334.     ;--- This IS NOT a comment as comments disabled above --------------------
  10335.  
  10336.  
  10337. ΓòÉΓòÉΓòÉ 9.30.13. LineContinuation ΓòÉΓòÉΓòÉ
  10338.  
  10339. LineContinuation=["]FullOrPartialSpecification["] 
  10340.  
  10341. This #option command allows you to alter the current Line Continuation 
  10342. characters or indeed turn it off altogether. 
  10343.  
  10344. The "FullOrPartialSpecification" parameter can be one of the following: 
  10345.  
  10346.        1. NULL 
  10347.           In this case line continuation is turned off. 
  10348.  
  10349.        2. "" 
  10350.           An empty value means use the default value. 
  10351.  
  10352.        3. exactly one character 
  10353.           A single character value replaces the meaning of the '\' character. 
  10354.  
  10355.        4. exactly five characters 
  10356.           This replaces all special characters used for line continuation as 
  10357.           follows: 
  10358.  
  10359.             a. Replacement for '\'. 
  10360.             b. Replacement for down arrow character. 
  10361.             c. Replacement for '-'. 
  10362.             d. Replacement for '+'. 
  10363.             e. Replacement for space. 
  10364.  
  10365.  See the Line Continuation section of this document for more details. Your 
  10366.  editor may not like the low ascii down arrow character (or you may hate it!), 
  10367.  this option allows you to easily change it to another character of your 
  10368.  choice. 
  10369.  
  10370.  Example 1 
  10371.  
  10372.  We just wish to change the '\' so that we use '~' instead, so that we would 
  10373.  use '-~' etc: 
  10374.  
  10375.       #option LineContinuation="~"
  10376.  
  10377.  Example 2 
  10378.  
  10379.  Get rid of the down arrow variation, otherwise stick with defaults: 
  10380.  
  10381.       #option LineContinuation="\@-+ "   ;;'@\' now used for "newline" continuation
  10382.  
  10383.  Example 3 
  10384.  
  10385.  This example changes the down arrow character to the ASCII character decimal 
  10386.  20, no real reason however it does demonstrate a more complex possibility: 
  10387.  
  10388.       #evaluate  NewDownArrow  'd2c(20)'
  10389.       #option    LineContinuation=%\<$NewDownArrow>-+ ^
  10390.  
  10391.  
  10392. ΓòÉΓòÉΓòÉ 9.30.14. MacroParmTags ΓòÉΓòÉΓòÉ
  10393.  
  10394. MacroParmTags=["]NewTags["] 
  10395.  
  10396. This #option command is used to control the tags used within a macro definition 
  10397. to specify the location where a parameter replacement occurs.  Use with care. 
  10398. You would normally only use once at the start of your code - think about the 
  10399. impact on any existing macros. 
  10400.  
  10401. If an empty parameter is supplied then the default is restored otherwise the 
  10402. parameter must have exactly 3 characters in it.  The characters are in order: 
  10403.  
  10404.        1. Replacement for '{'. 
  10405.        2. Replacement for '}'. 
  10406.        3. Replacement for '$'. 
  10407.  
  10408.  Example 
  10409.  
  10410.       #option MacroParmTags="()%"   ;;Parameters now start with '(%' and end with ')'
  10411.       #option MacroParmTags=""      ;;Set to default values
  10412.  
  10413.  
  10414. ΓòÉΓòÉΓòÉ 9.30.15. ParmVal ΓòÉΓòÉΓòÉ
  10415.  
  10416. ParmVal=["]Value["] 
  10417.  
  10418. This #option command lets you control the macro parameter validation taking 
  10419. place. Parameter validation is used to ensure that all parameters passed to a 
  10420. macro are used, the reason for this is that if they are not you probably 
  10421. misspelt it! 
  10422.  
  10423. The "Value" parameter can be one of the following: 
  10424.  
  10425.        1. ON 
  10426.           This means that parameter validation is always performed. 
  10427.  
  10428.        2. OFF 
  10429.           This means that parameter validation is never performed. This turns 
  10430.           off any "{$!}" validation you might have. This might be required in 
  10431.           some cases where someone has designed some macros for you however 
  10432.           your use of this or coding style means that the validation is causing 
  10433.           you problems. 
  10434.  
  10435.        3. SOME 
  10436.           Only validations indicated by the use of "{$!}" tag are performed. 
  10437.           <P> This is the default state. 
  10438.  
  10439.        4. "" 
  10440.           An empty value indicates that the default value for the build should 
  10441.           be restored. 
  10442.  
  10443.  
  10444. ΓòÉΓòÉΓòÉ 9.30.16. Replace ΓòÉΓòÉΓòÉ
  10445.  
  10446. Replace=OnOrOff 
  10447.  
  10448. This #option command lets you to temporarily suspend replacement of definitions 
  10449. (and <?xXX> symbols).  This allows you to pass through some complex lines 
  10450. without having to spend ages working out how you can tag it so as not to expand 
  10451. out (or fail trying). 
  10452.  
  10453. It is recommended that you turn off substitution for as short a time as you 
  10454. require it. Use with care. 
  10455.  
  10456. This command could be very handy if you needed to create a variable with a 
  10457. "#evaluate" command but you didn't want all the variables in the contents 
  10458. replaced straight away. 
  10459.  
  10460. If the "OnOrOff" parameter is empty then it defaults to the current default 
  10461. value, otherwise one of the following is expected:
  10462.  
  10463.                 ON
  10464.                 OFF
  10465.                 YES
  10466.               NO
  10467.  
  10468.  Example 
  10469.  
  10470.  The following is extracted out of a real macro that I had to set up, I was 
  10471.  having trouble with '<$endExample>' expanding out when what I really want is 
  10472.  the literal text: 
  10473.  
  10474.       #Option        REPLACE=OFF                        \
  10475.       #AutoTag       '<$endExample>'  '~$endExample>'   \
  10476.       #AutoTag       '<'              '<?xLT>'          \
  10477.       #AutoTag       '#'              '#'               \
  10478.       #AutoTag       '~$endExample>'  '<$endExample>'   \
  10479.       #Option        REPLACE=ON                         \
  10480.  
  10481.  
  10482. ΓòÉΓòÉΓòÉ 9.30.17. ReplacementTags ΓòÉΓòÉΓòÉ
  10483.  
  10484. ReplacementTags=["]NewTags["] 
  10485.  
  10486. This #option command is used to control the tags that are required to tell 
  10487. PPWIZARD that you wish macro substitution to occur.  Use with care. You would 
  10488. normally only use once at the start of your code - think about the impact on 
  10489. any existing macros. 
  10490.  
  10491. If an empty parameter is supplied then the default is used otherwise the 
  10492. parameter must have exactly 4 characters in it.  The characters are in order: 
  10493.  
  10494.        1. Replacement for '<'. 
  10495.        2. Replacement for '>'. 
  10496.        3. Replacement for '$'. 
  10497.        4. Replacement for '?'. 
  10498.  
  10499.  Example 
  10500.  
  10501.       #define FRED   ****
  10502.       <$Fred>                      ;;Fred will be subsituted here
  10503.  
  10504.       #option ReplacementTags="[]$?"
  10505.       [$Fred]                      ;;Fred will be subsituted here
  10506.       <$Fred>                      ;;Fred will NOT be subsituted here
  10507.       #option ReplacementTags=""   ;;Set to default values
  10508.  
  10509.  
  10510. ΓòÉΓòÉΓòÉ 9.30.18. Tabs ΓòÉΓòÉΓòÉ
  10511.  
  10512. Tabs=["]HowToHandle["] 
  10513.  
  10514. This #option command can be used to adjust the way that PPWIZARD processes tab 
  10515. characters (ascii 9). 
  10516.  
  10517. The "HowToHandle" parameter controls how tabs if found are handled. Valid 
  10518. options are: 
  10519.  
  10520.          Ignore 
  10521.           Don't do anything, just ignore, this may cause preprocessor to fail 
  10522.           (depending on where tabs are located). 
  10523.  
  10524.          ToSpaces 
  10525.           Each tab is converted to one only space. 
  10526.  
  10527.          Warnings 
  10528.           Each tab is converted to one only space and a warning is generated. 
  10529.           This is the default condition. 
  10530.  
  10531.          A Number 
  10532.           This option is useful where your source uses a fixed tab stop (of 8 
  10533.           is very common). Each tab is expanded to the correct number of spaces 
  10534.           for the tabs position. 
  10535.  
  10536.  
  10537. ΓòÉΓòÉΓòÉ 9.30.19. Warnings ΓòÉΓòÉΓòÉ
  10538.  
  10539. Warnings=["]IgnoreWhich["] 
  10540.  
  10541. This #option command allows you to have control of the handling of individual 
  10542. (or groups of) messages. You can choose to completely ignore particular 
  10543. messages or you can "promote" them into fatal errors. 
  10544.  
  10545. Warnings can come from PPWIZARD, the #warning command or the Warning() 
  10546. function. 
  10547.  
  10548. By default no warnings are ignored or "promoted". The "IgnoreWhich" parameter 
  10549. can be one of the following: 
  10550.  
  10551.        1. NULL 
  10552.           No warnings will be ignored or "promoted". 
  10553.  
  10554.        2. "" 
  10555.           An empty value means use the default value. 
  10556.  
  10557.        3. All Warnings Listed 
  10558.           This should be one or more match specification strings each separated 
  10559.           by ';' (use ':' under unix). 
  10560.  
  10561.           Each match specification may begin one of the following characters: 
  10562.  
  10563.               '-' 
  10564.                This means ignore any warnings that match the specification. As 
  10565.                far as you are concerned there is no issue. This is the default 
  10566.                action. 
  10567.  
  10568.               '+' 
  10569.                This means promote any warnings that match the specification to 
  10570.                a fatal error. 
  10571.  
  10572.               '!' 
  10573.                This means treat any warnings that match the specification as 
  10574.                we'd normally would. This can be used to handle messages that 
  10575.                might overwise match a following specification. 
  10576.  
  10577.  All messages match "*". It will also match if the text of a warning message 
  10578.  contains the specification string (case insensitive check). 
  10579.  
  10580.  If a message is dropped then you can still see the message in debug mode as 
  10581.  well as the reason it normally gets dropped (that is the specification string 
  10582.  it matched). 
  10583.  
  10584.  The warning message text which is searched includes the line number as well as 
  10585.  the warning ID, basically the exact text that you would normally see so you 
  10586.  could prevent warnings down to a particular line number if you wish (although 
  10587.  this is not recommended). 
  10588.  
  10589.  Warning IDs and text are not documented so you need to wait for one to occur 
  10590.  before deciding how to drop it. 
  10591.  
  10592.  If you wish to see warning messages but still want a zero return code you 
  10593.  should check out the /WarningsRc switch. 
  10594.  
  10595.  Example 
  10596.  
  10597.  The following example lines show how you can treat any warning message that 
  10598.  contains "tabs" (in any case) as a fatal error and completely ignore all other 
  10599.  warnings that don't contain "FRED". 
  10600.  
  10601.       #option Warnings="+tabs;!FRED;*"
  10602.  
  10603.  
  10604. ΓòÉΓòÉΓòÉ 9.30.20. WhiteSpace ΓòÉΓòÉΓòÉ
  10605.  
  10606. WhiteSpace=["]ExtraWhiteSpaceCharacters["] 
  10607.  
  10608. This #option command can be used to adjust the characters that PPWIZARD treats 
  10609. as whitespace.  A space is always treated as whitespace.  Each extra character 
  10610. you define will be converted to a real space as lines are read from files. 
  10611.  
  10612. The default whitespace for unix will ensure that PC based files whose lines end 
  10613. with carriage return then linefeed and may have end of file characters embedded 
  10614. in the file can be read without conversion. 
  10615.  
  10616. Example 
  10617.  
  10618. The following example shows how to define the "~" and form feed (hex code '0C') 
  10619. characters as whitespace.  In a unix environment we have removed the default 
  10620. whitespace conversions. 
  10621.  
  10622.     PPWIZARD INPUT.IT /Option:WhiteSpace="{x0C}~"
  10623.  
  10624.  
  10625. ΓòÉΓòÉΓòÉ 9.31. #output ΓòÉΓòÉΓòÉ
  10626.  
  10627. #output 
  10628.  
  10629. In most situations you would read one or more input files to generate a single 
  10630. output file.  There are situations where you'd like more control so that you 
  10631. can generate multiple files. 
  10632.  
  10633. You can nest to any level as only one output file is open at any time so file 
  10634. resources are not wasted. 
  10635.  
  10636. Syntax 
  10637.  
  10638.     [WhiteSpace]#output  ["]OutputName["]  [AsIs] [Append] [NoHeader] [HTML|REXX|OTHER]
  10639.  
  10640. If "AsIs" was specified then the "OutputName" specifies the name of the output 
  10641. file otherwise the value is passed through the output specification provided 
  10642. with the "/Output" switch.  If the "OutputName" parameter is not specified at 
  10643. all then the previous output file is restored. 
  10644.  
  10645. Note that files specified for use "AsIs" do not have their case adjusted as 
  10646. specified on the /FileNames switch, if you require the case to be adjusted you 
  10647. will need to make use of the EnsureFileHasCorrectCase routine. 
  10648.  
  10649. If "Append" was specified then the output file is not deleted if it already 
  10650. exists. 
  10651.  
  10652. If "NoHeader" was specified then if the file would normally have an output 
  10653. header then this is disabled (see /OutHeader). 
  10654.  
  10655. In some circumstances you may wish to generate a new file in a different 
  10656. processing mode to the current one, if this applies to you then choose on of 
  10657. "HTML", "REXX" or "OTHER". 
  10658.  
  10659. When a previous file is restored (no parameters) then new data is appended, 
  10660. otherwise the file is erased before writing the first line. 
  10661.  
  10662. Example 
  10663.  
  10664.     Line 1 of file 1
  10665.     Line 2 of file 1
  10666.     #output  '2nd'
  10667.        Line 1 of file 2
  10668.        Line 2 of file 2
  10669.        #output  'c:\path\3nd.ext' AsIs
  10670.            Line 1 of file 3
  10671.        #output
  10672.        Line 3 of file 2
  10673.     #output
  10674.     Line 3 of file 1
  10675.  
  10676. Example - Relative Filenames 
  10677.  
  10678. The following example show how you can calculate filenames which are relative 
  10679. to the directory where output normally goes (as determined by the /OUTPUT 
  10680. switch: 
  10681.  
  10682.     ;--- Macro to calculate filename relative to output directory ---------------
  10683.     #evaluate ""                       ^OutputDir = EnsureFileHasCorrectCase(_filespec('location', '<?OutputFile>'))^  ;;Only need to determine once!
  10684.     #define   FileRelativeToOutputDir  <??OutputDir>{$File}
  10685.  
  10686.     ;--- Test macro -------------------------------------------------------------
  10687.     InOutput.OUT         = <$FileRelativeToOutputDir FILE="InOutput.OUT">
  10688.     SubDir\InOutput.OUT  = <$FileRelativeToOutputDir FILE="SubDir\InOutput.OUT">
  10689.     ..\Parents.OUT       = <$FileRelativeToOutputDir FILE="..\Parents.OUT">
  10690.  
  10691. Example - Dropping output 
  10692.  
  10693. There may be time when you wish to drop some lines, for example you might be 
  10694. processing a file in a number of passes, this shows how you can do this under 
  10695. windows and OS/2: 
  10696.  
  10697.     #dependsOn TEMP "NUL"       ;;Don't add to dependancy file!
  10698.     #output "NUL" ASIS APPEND   ;;Drop output!
  10699.     This line gets dropped
  10700.     #output                     ;;Stop dropping output!
  10701.  
  10702.  
  10703. ΓòÉΓòÉΓòÉ 9.32. #OutputHold ΓòÉΓòÉΓòÉ
  10704.  
  10705. #OutputHold 
  10706.  
  10707. This command allows you to hold output lines in a buffer rather than writing 
  10708. them directly to the current output file. There are two main reasons why you 
  10709. might wish to do this as follows: 
  10710.  
  10711.        1. You wish to drop a number of lines for some reason (maybe in a macro 
  10712.           that makes multiple passes over some data). 
  10713.  
  10714.        2. You wish to modify the data in some way that is not known at the time 
  10715.           of output generation. As an example "OL_DOC.DH" when generating the 
  10716.           "Next" link at the top of each html page does not know what the next 
  10717.           page is (where to link to)! 
  10718.  
  10719.  The output is held only for a single output file so that when a new output 
  10720.  file is started (with the #Output command) it's output lines are not held. 
  10721.  These blocks can't be nested within a single output file! 
  10722.  
  10723.  The held output is formatted exactly as it would be if it were not held and 
  10724.  had been written to the file, so each line is separated from the next by the 
  10725.  currently defined line termination characters (see /CrLf). 
  10726.  
  10727.  Syntax 
  10728.  
  10729.       [WhiteSpace]#OutputHold  [["]MacroContainingCodeName["]] | ["]DROP["]]
  10730.  
  10731.  The command without any parameters indicates the start of the block, and if 
  10732.  the single parameter exists then this marks the end of the block. 
  10733.  
  10734.  The single parameter is either "DROP" to drop the output or the name of a 
  10735.  macro containing rexx code. The held output is held in the "HeldOutput" 
  10736.  variable. 
  10737.  
  10738.  Example 
  10739.  
  10740.  This is a useless example, but does show how it all works: 
  10741.  
  10742.       ;--- Define code that modifies the output lines we will hold ----------------
  10743.       #DefineRexx ModifyHeldLines
  10744.                   ;--- Stupid change just as example ------------------------------
  10745.                   HeldOutput = ReplaceString(HeldOutput, "line", "****");
  10746.       #DefineRexx
  10747.  
  10748.       ;--- The following lines go to the output file ------------------------------
  10749.       line 1
  10750.       line 2
  10751.       line 3
  10752.       line 4
  10753.       #OutputHold                        ;;Start holding output
  10754.       line 5
  10755.       line 6
  10756.       line 7
  10757.       line 8
  10758.       ;#OutputHold "DROP"                ;;Drop lines
  10759.       #OutputHold "ModifyHeldLines"      ;;Call rexx code to modify output
  10760.       line 9
  10761.       line 10
  10762.  
  10763.  
  10764. ΓòÉΓòÉΓòÉ 9.33. #push ΓòÉΓòÉΓòÉ
  10765.  
  10766. #push 
  10767.  
  10768. This command can be used to save macros or rexx variables onto a stack. This is 
  10769. useful for recursive type applications. 
  10770.  
  10771. Syntax 
  10772.  
  10773.     [WhiteSpace]#push  ["]Type["]  ["]Item["] ...
  10774.  
  10775. The "Type" parameter is used to indicate what sort of information is being 
  10776. pushed. This should be "MACRO" for macro values or "REXXVAR" for rexx 
  10777. variables. 
  10778.  
  10779. You may specify one or more "Item" parameters. These are pushed (with 
  10780. StackPush()) onto a stack from left to right. 
  10781.  
  10782. Example 
  10783.  
  10784.     ;---Set rexx variable and Save ---
  10785.     #RexxVar RxVar = 'Demonstating overlap'
  10786.     #push RexxVar RxVar
  10787.  
  10788.     ;--- Set macros and save value ---
  10789.     #define  FirstMacro   Something1
  10790.     #define  SecondMacro  Something2
  10791.     #push macro FirstMacro SecondMacro
  10792.  
  10793.     ;--- Restore The rexx variable ---
  10794.     #pop RexxVar RxVar
  10795.  
  10796.     ;--- Change Value ---
  10797.     #define  FirstMacro   SomethingElse1
  10798.  
  10799.     ;--- Restore Values ---
  10800.     #pop macro FirstMacro SecondMacro
  10801.  
  10802.  
  10803. ΓòÉΓòÉΓòÉ 9.34. #pop ΓòÉΓòÉΓòÉ
  10804.  
  10805. #pop 
  10806.  
  10807. This command can be used to restore macros or rexx variables from a stack. This 
  10808. is useful for recursive type applications. 
  10809.  
  10810. Syntax 
  10811.  
  10812.     [WhiteSpace]#pop  ["]Type["]  ["]Item["] ...
  10813.  
  10814. The "Type" parameter is used to indicate what sort of information is being 
  10815. popped. This should be "MACRO" for macro values or "REXXVAR" for rexx 
  10816. variables. 
  10817.  
  10818. You may specify one or more "Item" parameters. These are popped (with 
  10819. StackPop()) off the stack in reverse order (from right to left). The reason for 
  10820. the reverse order is so that you do not have to manually reverse them yourself 
  10821. and possibly making a mistake. 
  10822.  
  10823. Example 
  10824.  
  10825.     ;---Set rexx variable and Save ---
  10826.     #RexxVar RxVar = 'Demonstating overlap'
  10827.     #push RexxVar RxVar
  10828.  
  10829.     ;--- Set macros and save value ---
  10830.     #define  FirstMacro   Something1
  10831.     #define  SecondMacro  Something2
  10832.     #push macro FirstMacro SecondMacro
  10833.  
  10834.     ;--- Restore The rexx variable ---
  10835.     #pop RexxVar RxVar
  10836.  
  10837.     ;--- Change Value ---
  10838.     #define  FirstMacro   SomethingElse1
  10839.  
  10840.     ;--- Restore Values ---
  10841.     #pop macro FirstMacro SecondMacro
  10842.  
  10843.  
  10844. ΓòÉΓòÉΓòÉ 9.35. #Require ΓòÉΓòÉΓòÉ
  10845.  
  10846. #Require 
  10847.  
  10848. This is a simple command (Y2000 safe) which checks that the PPWIZARD 
  10849. preprocessor is capable of processing your code.  You would probably put this 
  10850. command in a header file that you distribute to users.  It will validate that 
  10851. the preprocessor they are using is new enough to handle your header file. 
  10852.  
  10853. Syntax 
  10854.  
  10855.     [WhiteSpace]#Require  ["]MinVersion["]  [["]MaxVersion["]]
  10856.  
  10857. The "MinVersion" specifies the minimum version number of PPWIZARD. The 
  10858. preprocessing will abort if the preprocessor is too old. 
  10859.  
  10860. The "MaxVersion" would rarely be required or specified. It would be used if the 
  10861. newer version of ppwizard does not handle your older source files and you don't 
  10862. wish to modify them so that it does, in this case I highly recommend specifying 
  10863. the maximum version and commenting the reason so you don't get confused at some 
  10864. later stage. 
  10865.  
  10866. Example 
  10867.  
  10868.     #require  98.216               ;;Want PPWIZARD version 98.216 or greater
  10869.  
  10870.  
  10871. ΓòÉΓòÉΓòÉ 9.36. #RexxVar ΓòÉΓòÉΓòÉ
  10872.  
  10873. #RexxVar 
  10874.  
  10875. This command allows you to manipulate rexx variables.  You can assign values to 
  10876. rexx variables, save them on a stack or give them the result of simple 
  10877. expressions which can be calculated much faster than with a #evaluate command. 
  10878.  
  10879. Note that you should try to pick unusual rexx variable names otherwise you 
  10880. might overwrite one that PPWIZARD uses.  It could cause very strange behaviour. 
  10881.  
  10882. Syntax #1 - Set Up "X" Variable 
  10883.  
  10884.     [WhiteSpace]#RexxVar  ["]VariableName["]  =x=   [']ItsValue[']
  10885.  
  10886. This command allows you to set up "<?xXX>" codes. 
  10887.  
  10888. The "VariableName" parameter is the name of the 'x' variable and can contain 
  10889. virtually any character. 
  10890.  
  10891. The "ItsValue" parameter is the value which the rexx variable is to contain. 
  10892. Unlike the "#evaluate" command the new value is not first interpreted.  It is 
  10893. taken as is.  In practice I recommend using a quote character such as "^" as 
  10894. it's unlikely to appear in the text, this may make it easier to follow in debug 
  10895. mode etc. This parameter can be a variables name (if unquoted). 
  10896.  
  10897. Syntax #2 - Assign to Rexx Variable 
  10898.  
  10899.     [WhiteSpace]#RexxVar  ["]VariableName["]  =   [']ItsValue[']
  10900.  
  10901. This form of the command lets you assign text directly to a rexx variable.  It 
  10902. is very useful in macros as you don't have to worry about quote issues while 
  10903. manipulating the data.  For example you would find it very difficult to 
  10904. uppercase some text (probably passed as a macro parameter) if it contained both 
  10905. a single quote and a double quote and in fact how would you know which if any 
  10906. it contained? 
  10907.  
  10908. The "VariableName" parameter is the full name of the rexx variable to be set. 
  10909.  
  10910. The "ItsValue" parameter is the value which the rexx variable is to contain. 
  10911. Unlike the "#evaluate" command the new value is not first interpreted.  It is 
  10912. taken as is.  In practice I recommend using a quote character such as "^" as 
  10913. it's unlikely to appear in the text, this may make it easier to follow in debug 
  10914. mode etc.  This parameter can be a variables name (if unquoted). 
  10915.  
  10916. Syntax #3 - Save/Restore Variable on Stack 
  10917.  
  10918.     [WhiteSpace]#RexxVar  Operator ["]VariableName1["] ...   ;;New Format
  10919.     [WhiteSpace]#RexxVar  ["]VariableName["] Operator        ;;Old Format
  10920.  
  10921. The "VariableName" parameter(s) are the names of all variables being pushed or 
  10922. popped (saved or restored). 
  10923.  
  10924. The "Operator" parameter should be one of the following: 
  10925.  
  10926.        1. PUSH, Save rexx variable on stack. 
  10927.        2. POP, get last saved value from stack. 
  10928.  
  10929.  For each variable pushed there must be a corresponding pop.  It allows you to 
  10930.  use the same variable names in multiple places without danger of the value 
  10931.  getting modified (say by a #included file). 
  10932.  
  10933.  The variable parameters of the pop command are processed in reverse order so 
  10934.  that if you have push and pop commands with the more than one variable the 
  10935.  variable lists do not need to be reversed by you! 
  10936.  
  10937.  Syntax #3 - Simple Variable Manipulation 
  10938.  
  10939.       [WhiteSpace]#RexxVar  ["]VariableName["] Operator  Value2  [SourceValue1]
  10940.  
  10941.  This form of the command lets you perform some simple operations.  These will 
  10942.  be much faster than performing the same operation using #evaluate. 
  10943.  
  10944.  The "VariableName" parameter is the full name of the rexx variable.  In this 
  10945.  format the variable will be given the result of a simple expression.  The 
  10946.  value is calculated as follows: 
  10947.  
  10948.       VariableName = SourceValue1 {Operator} Value2;
  10949.  
  10950.  The "Operator" parameter should be one of the following: 
  10951.  
  10952.        1. +, Addition. 
  10953.        2. -, Subtraction. 
  10954.        3. *, Multiply. 
  10955.        4. /, Divide. 
  10956.        5. //, Divide, want remainder. 
  10957.        6. %, Divide, want whole number. 
  10958.        7. || Concatenate. 
  10959.  
  10960.  The "Value2" is the value which would be added, subtracted etc from the source 
  10961.  value. 
  10962.  
  10963.  The "SourceValue1" parameter is the the source value.  By default the value 
  10964.  comes from "VariableName". 
  10965.  
  10966.  Both Value2 & SourceValue1 can be one of the following: 
  10967.  
  10968.          A rexx number. 
  10969.          A rexx variable. 
  10970.          A rexx literal. 
  10971.  
  10972.  Example 
  10973.  
  10974.  The following is sets the rexx variable "MyVar" to the literal "ABC" (as it's 
  10975.  quoted): 
  10976.  
  10977.       #RexxVar       'MyVar'  =  /ABC/
  10978.  
  10979.  The following is sets the rexx variable "MyVar" to the contents of the 
  10980.  variable "ABC" (as it's unquoted): 
  10981.  
  10982.       #RexxVar       'MyVar'  =  ABC
  10983.  
  10984.  The following two lines both set the rexx variable "MyVar" to the value 0: 
  10985.  
  10986.       #RexxVar       'MyVar'  =  0
  10987.       #RexxVar       MyVar    =  '0'
  10988.  
  10989.  The following is sets the rexx variable "MyVar" to the 3 chars (single quote, 
  10990.  space then double quote): 
  10991.  
  10992.       #RexxVar       'MyVar'  =  "' ""
  10993.  
  10994.  Notice that in the above example double quotes are used to contain a value 
  10995.  that contains a double quote.  This is a common reason for using the 
  10996.  "#RexxVar" command when accepting parameters in a macro. 
  10997.  
  10998.  The following is one line out of a larger macro, note that we have absolutely 
  10999.  no idea what text the parameter may expand to (for example it could easily 
  11000.  contain single quotes): 
  11001.  
  11002.       #RexxVar       'MyVar'  =  '{$Text}'
  11003.  
  11004.  The following lines all add one to the "Counter": 
  11005.  
  11006.       #RexxVar       Counter  +  1               ;;Counter = Counter +  1
  11007.       #RexxVar       Counter  +  1 Counter       ;;Counter = Counter +  1
  11008.       #RexxVar       Counter  -  "-1"            ;;Counter = Counter - -1
  11009.  
  11010.  A stupid example: 
  11011.  
  11012.       #RexxVar       Three    +  1 2             ;;Three = 2 + 1
  11013.  
  11014.  The following lines append to the end of the rexx variable "Grow": 
  11015.  
  11016.       #RexxVar       Grow  ||  ", a string"     ;;Grow = Grow || ", a string"
  11017.       #RexxVar       Grow  ||  AVariable        ;;Grow = Grow || AVariable
  11018.  
  11019.  The following lines could be used in a rexx header file to skip over any 
  11020.  subroutines the header contains after all header initialization has taken 
  11021.  place: 
  11022.  
  11023.       ;--- Initialization ---------------------------------------------------------
  11024.       HeaderVar1 = "Value1";
  11025.       HeaderVar2 = "Value2";
  11026.  
  11027.       ;--- Jump around code -------------------------------------------------------
  11028.       #RexxVar   "SkipName"   =     "SkipSubroutine_<?IncludeLevel>_<?Unique>"
  11029.       signal     <??SkipName>;                    ;;Jump past functions
  11030.       #RexxVar   PUSH "SkipName"                  ;;Save name of label
  11031.  
  11032.       HeaderFunction1:
  11033.          return('Value');
  11034.  
  11035.       ;----------------------------------------------------------------------------
  11036.       ;--- End of code ------------------------------------------------------------
  11037.       ;----------------------------------------------------------------------------
  11038.       #RexxVar   POP  "SkipName"                  ;;Restore saved value
  11039.       <??SkipName>:                               ;;Create label to mark end of code
  11040.  
  11041.  
  11042. ΓòÉΓòÉΓòÉ 9.37. #transform ΓòÉΓòÉΓòÉ
  11043.  
  11044. #transform 
  11045.  
  11046. This command allows you to define a block of lines for which transformations 
  11047. (that you define) should take place. 
  11048.  
  11049. I got the idea when creating some javascript to output html (using javascript's 
  11050. "document.writeln()" routine), this can be hard as the html code becomes less 
  11051. readable and you have problems with handling quotes. 
  11052.  
  11053. I needed to use javascript to generate HTML controls that should only be 
  11054. available if the javascript they need can also be available. 
  11055.  
  11056. What I wanted was an automated way of adding the "document.writeln()" code and 
  11057. taking care of any content issues such as handling quote characters. This way I 
  11058. just edit the easily readable html code and not worry about which quotes I'm 
  11059. allowed to use or what to do when I need both! 
  11060.  
  11061. A transformation is one of the last things to occur before a line is generated 
  11062. into the output file. 
  11063.  
  11064. To perform transformations you must first define the rexx code to modify the 
  11065. "current" line (in the FileLine variable). An example of code which handles the 
  11066. problem described above follows: 
  11067.  
  11068.     #DefineRexx DOC_WRITELN
  11069.                 ;--- Escape any escape characters -------------------------------
  11070.                 FileLine = ReplaceString(FileLine, "\", "\\");
  11071.  
  11072.                 ;--- Escape any single quotes (we use this below) ---------------
  11073.                 FileLine = ReplaceString(FileLine, "'", "\'");
  11074.  
  11075.                 ;--- Now wrap in javascript code to write it out ----------------
  11076.                 FileLine = "document.writeln('" || FileLine || "')";
  11077.     #DefineRexx
  11078.  
  11079. Once you have defined the transformation code you can then mark the start and 
  11080. end of the block of lines that get transformed on output. You can not nest 
  11081. transformation blocks. 
  11082.  
  11083. Syntax 
  11084.  
  11085.     [WhiteSpace]#Transform  [["]MacroContainingCodeName["]]
  11086.  
  11087. If the single parameter exists then this marks the start of the block, if 
  11088. missing it marks the end of the block. To start the block you need to supply 
  11089. the name of the macro that contains the transformation code. 
  11090.  
  11091. Example #1 
  11092.  
  11093. I used this code in some VB Script in a Windows HTA (HTML application) to 
  11094. create "document.writeln" calls automatically and take care of quoting issues: 
  11095.  
  11096.     ;--- Define how to convert HTML code into VB "document.writeln()" code ------
  11097.     #DefineRexx DOC_WRITELN_IN_VB
  11098.            FileLine = ReplaceString(FileLine, '"', '""');       ;;Double up double quote characters
  11099.            FileLine = 'document.writeln("' || FileLine || '")'  ;;Wrap in VB code to create the HTML or code
  11100.     #DefineRexx
  11101.  
  11102.     ;--- Create a couple of aliases to hopefully make code self explanatory -----
  11103.     #define WriteLn    \
  11104.             #Transform DOC_WRITELN_IN_VB
  11105.     #define WriteLnEnd \
  11106.             #Transform
  11107.  
  11108.  
  11109.     ;############################################################################
  11110.     sub AddFooter()
  11111.     ;
  11112.     ;   Graphics from
  11113.     ;   ~~~~~~~~~~~~~
  11114.     ;   http://www.iconbazaar.com/alphabets/animated/great_stars/pg01.html
  11115.     ;############################################################################
  11116.        #define Bsd                                 \
  11117.                <img src="AnimatedStar-{$#1}.gif"   \
  11118.                  border="0"                        \
  11119.                  height="20"                       \
  11120.                   width="20"                      -\
  11121.                >
  11122.        <$WriteLn>
  11123.            <p>
  11124.            <hr size="1" color="red">
  11125.            <center>
  11126.            PRINTQS v<$PGM_VERSION>
  11127.            <BR>
  11128.        <$WriteLnEnd>
  11129.            document.writeln(FormatDateTime(date(), vbLongDate) & " at " & FormatDateTime(time(), vbLongTime))
  11130.        <$WriteLn>
  11131.            <BR>
  11132.            <a href="http://www.anz/intranet/bsd/bsd_home.htm"     \
  11133.               target="_blank"                                     \
  11134.                title="Developed by Branch Systems Development     \
  11135.                       (Melbourne Australia).                      \
  11136.                       Click to open browser at BSD homepage."    -\
  11137.            >                                                     -\
  11138.                <$Bsd "B">                                        -\
  11139.                <$Bsd "S">                                        -\
  11140.                <$Bsd "D">                                        -\
  11141.            </a>
  11142.            </center>
  11143.        <$WriteLnEnd>
  11144.     end sub
  11145.  
  11146. Example #2 
  11147.  
  11148. This code show another larger chunk of rexx code being used to transform some 
  11149. html: 
  11150.  
  11151.  
  11152.     ;--- Turn tracing off (or hugh debug output) --------------------------------
  11153.     #define     REXXTRACE OFF
  11154.  
  11155.     ;--- Define some transformation code ----------------------------------------
  11156.     #DefineRexx HIDE_HTML
  11157.                 ;--- Convert into codes -----------------------------------------
  11158.                 Before = FileLine;
  11159.                 After  = '';
  11160.                 do Posn = 1 to length(Before)
  11161.                    ;--- Get the next byte ---------------------------------------
  11162.                    ThisByte = substr(Before, Posn, 1);     ;;Byte As Character
  11163.  
  11164.                    ;--- Want Hex or Octal codes (Hex is default)? ---------------
  11165.                    #ifndef  HIDE_HTML_IN_OCTAL
  11166.                        ;--- Calculate HEX code ----------------------------------
  11167.                        Code = '\x' || c2x(ThisByte);       ;;Byte As Hex code
  11168.                    #elseif
  11169.                        ;--- Convert to code (octal) -----------------------------
  11170.                        ThisByte = c2d(ThisByte);           ;;Byte As ASCII
  11171.                        Code = '';
  11172.                        do  while ThisByte <> 0
  11173.                            ;--- Add next digit ----------------------------------
  11174.                            Code = Code || (ThisByte // 8);
  11175.  
  11176.                            ;--- Prepare for next loop ---------------------------
  11177.                            ThisByte = ThisByte % 8;
  11178.                        end;
  11179.  
  11180.                        ;--- Add escape and put digits in correct order ----------
  11181.                        Code = left(Code, 3, '0');          ;;MUST be 3 digits
  11182.                        Code = '\' || reverse(Code);        ;;Byte As Octal code
  11183.                    #endif
  11184.  
  11185.                    ;--- Add to output (note I don't check max literal length!) --
  11186.                    After = After || Code;
  11187.                 end;
  11188.  
  11189.                 ;--- Now wrap in javascript code to write it out ----------------
  11190.                 FileLine = "document.writeln('" || After || "')";
  11191.     #DefineRexx
  11192.  
  11193.     ;--- Start HTML -------------------------------------------------------------
  11194.     <HTML>
  11195.     <BODY>
  11196.  
  11197.     ;--- Now create encoded body ------------------------------------------------
  11198.     <SCRIPT LANGUAGE=JavaScript>
  11199.        #transform  HIDE_HTML
  11200.                    <H1>Simplest Hidden code Possible</H1>
  11201.  
  11202.                    <P>This is a sample of the simplest way to
  11203.                    hide code, of course it only works if user's
  11204.                    browser can handle javascript.
  11205.  
  11206.                    <P>You could get much more complicated and
  11207.                    encrypt the code however anything you do can
  11208.                    still be undone as of course while the codes
  11209.                    can't be read directly the javascript can, one
  11210.                    way out of this might be to include the javascript
  11211.                    at runtime.
  11212.  
  11213.                    <P>Note I have since realised that not all browsers
  11214.                    show the source code, they show the "resultant"
  11215.                    code instead, however this is still good demonstration
  11216.                    code!
  11217.        #transform
  11218.     </SCRIPT>
  11219.  
  11220.     ;--- Show something if no javascript ----------------------------------------
  11221.     <NOSCRIPT>
  11222.        <P>Sorry your browser does not handle
  11223.        javascript or you have it turned off!
  11224.     </NOSCRIPT>
  11225.  
  11226.     ;--- End of HTML ------------------------------------------------------------
  11227.     </BODY>
  11228.     </HTML>
  11229.  
  11230. Example #3 
  11231.  
  11232. I wanted to be able to show as an example the output of a macro, however it 
  11233. generated html/xml code and would therefore not display correctly in a browser 
  11234. (it also generated characters that upset IPF code). 
  11235.  
  11236. What I needed to do was "transform" the end result, this is what I did: 
  11237.  
  11238.     ;--- Define required IPF & HTML transformations -----------------------------
  11239.     #DefineRexx "MAKE_HTML_VIEWABLE"
  11240.        #if ['<$DocType>' = 'HTML']
  11241.            FileLine = ReplaceString(FileLine, '<', '<');     ;;Hide HTML from browser
  11242.        #elseif
  11243.            FileLine = ReplaceString(FileLine, ':', '&colon.');  ;;For IPF - Hide ':'
  11244.        #endif
  11245.     #DefineRexx
  11246.  
  11247.     ;--- Show example -----------------------------------------------------------
  11248.     <$ExampleFormatted>
  11249.     #transform MAKE_HTML_VIEWABLE
  11250.     <$WantToSeeWhatItExpandsTo>
  11251.     #transform
  11252.     <$eExampleFormatted>
  11253.  
  11254.  
  11255. ΓòÉΓòÉΓòÉ 9.38. #undef ΓòÉΓòÉΓòÉ
  11256.  
  11257. #undef 
  11258.  
  11259. A #undef command allows you to remove a definition so that it can be redefined 
  11260. without producing the warning message it normally will generate. 
  11261.  
  11262. Syntax 
  11263.  
  11264.     [WhiteSpace]#define  Variable
  11265.  
  11266. The "Variable" indicates which variable is to be removed (macro references are 
  11267. first replaced). 
  11268.  
  11269. Example 
  11270.  
  11271.     #define Fred   Its value
  11272.     #undef  Fred;
  11273.     #define Fred   Its new value
  11274.  
  11275.  
  11276. ΓòÉΓòÉΓòÉ 9.39. #Warning ΓòÉΓòÉΓòÉ
  11277.  
  11278. #Warning 
  11279.  
  11280. A #Warning command is used to inform the user of an unusual situation. You 
  11281. would probably have extracted information (maybe from an environment variable) 
  11282. and found that all is not right.  This command allows you to warn the user but 
  11283. continue processing (you will get a return code of 1). 
  11284.  
  11285. The #Error command is similar but halts processing. 
  11286.  
  11287. Syntax 
  11288.  
  11289.     [WhiteSpace]#Warning  [']WarningId[']  [']WarningMessage[']
  11290.  
  11291. The "WarningId" parameter specifies a warning ID which can be used to help 
  11292. identify message (for example if you wished to use the Warnings option). You 
  11293. can supply an empty ID in case no ID is used. An ID can be as short or long as 
  11294. you wish. 
  11295.  
  11296. The "WarningMessage" parameter specifies the text of the warning to be 
  11297. displayed. 
  11298.  
  11299. Example 
  11300.  
  11301.     #if GetEnv('FRED') <> 1 & GetEnv('FRED') <> 2
  11302.         #Warning ^IV00^ "Invalid value for variable 'FRED', processing will continue"
  11303.     #endif
  11304.  
  11305.  
  11306. ΓòÉΓòÉΓòÉ 9.40. #Unknown Commands ΓòÉΓòÉΓòÉ
  11307.  
  11308. #Unknown Commands 
  11309.  
  11310. Normally ppwizard dies if you specify an invalid command. PPWIZARD allows you 
  11311. to extend the range of available commands if you wish. 
  11312.  
  11313. One good reason why you might wish to do this is to create your own set of 
  11314. commands to integrate better with ppwizard, you don't wish to rely on a user 
  11315. specifying macros etc or you just feel the syntax is cleaner. 
  11316.  
  11317. The first time ppwizard finds an unknown command it will look for a macro with 
  11318. the name UNKNOWN_HASH_COMMANDS. This macro should contain the rexx code to be 
  11319. executed. 
  11320.  
  11321. The following rexx variables are significant: 
  11322.  
  11323.          HashCmd 
  11324.           Full name of command in upper case. You should call Error() if the 
  11325.           command is not one you handle. 
  11326.  
  11327.          HashParms 
  11328.           Everything on the line after the command name. 
  11329.  
  11330.          CmdGenerates 
  11331.           If your command generates any ppwizard commands or data for the 
  11332.           output file etc then it should update this variable. 
  11333.  
  11334.           If you wish to generate a newline which appears in the output file 
  11335.           then you should use "<?NewLine>" otherwise you should use a newline 
  11336.           character (ascii 10), to do this you can use d2c(10) or '0A'x (the 
  11337.           second form is faster as no function called). 
  11338.  
  11339.  Example 
  11340.  
  11341.   ;--- Define Handler for new #commands ---------------------------------------
  11342.   #DefineRexx 'UNKNOWN_HASH_COMMANDS'
  11343.               select
  11344.                  /*++++++++++++++++++++++++++++++++++++++++++++++*/
  11345.                  when HashCmd = HashPrefix || 'SET' then
  11346.                  /*++++++++++++++++++++++++++++++++++++++++++++++*/
  11347.                       CmdGenerates = HashParms || '<' || '?NewLine>' || HashParms;
  11348.                  /*++++++++++++++++++++++++++++++++++++++++++++++*/
  11349.                  when HashCmd = HashPrefix || 'EXECPPW' then
  11350.                  /*++++++++++++++++++++++++++++++++++++++++++++++*/
  11351.                       CmdGenerates = HashParms || d2c(10) || HashParms;
  11352.                  /*++++++++++++++++++++++++++++++++++++++++++++++*/
  11353.                  otherwise
  11354.                  /*++++++++++++++++++++++++++++++++++++++++++++++*/
  11355.                       Error('Unknown command of "' || HashCmd || '"');
  11356.               end;
  11357.   #DefineRexx
  11358.  
  11359.  
  11360.   ;--- Create macro to test use of unknown commands in a macro ----------------
  11361.   #define XXXX            \
  11362.           (START)        -\
  11363.           #SET 222222_   -\
  11364.           #SET 333333_   -\
  11365.           (END)
  11366.  
  11367.  
  11368.   ;--- Do some tests (in and out of macro) ------------------------------------
  11369.   1111111
  11370.   <$XXXX>
  11371.   4444444
  11372.   #SET 555555_
  11373.   #SET 666666_
  11374.  
  11375.  
  11376.   ;--- Test generation of ppwizard commands -----------------------------------
  11377.   #ExecPpw #define A B
  11378.  
  11379.   ;--- Next line does and should fail (unknown command) -----------------------
  11380.   #XXX .....
  11381.  
  11382.  
  11383. ΓòÉΓòÉΓòÉ 10. Standard Definitions ΓòÉΓòÉΓòÉ
  11384.  
  11385. Standard Definitions 
  11386.  
  11387. There are a number of "standard" definitions which have been predefined and can 
  11388. be placed almost anywhere in your source code.  The variable names can be 
  11389. specified in any case. They are: 
  11390.  
  11391.          <??RexxVariable> 
  11392.          <?=RexxExpression> 
  11393.          <?/> 
  11394.          <?BaseDir> 
  11395.          <?CgiStart> 
  11396.          <?CmdLineTotal> 
  11397.          <?CompileTime> 
  11398.          <?DebugOn> 
  11399.          <?DirSlash> 
  11400.          <?Dollar> 
  11401.          <?Hash> 
  11402.          <?HashPrefix> 
  11403.          <?IncludeLevel> 
  11404.          <?InputComponent> 
  11405.          <?InputComponentLine> 
  11406.          <?InputFile> 
  11407.          <?LessThan> 
  11408.          <?NewestFileDateTime> 
  11409.          <?NewLine> 
  11410.          <?NewLine?> 
  11411.          <?OpSys> 
  11412.          <?OpSysSpecific> 
  11413.          <?OutputFile> 
  11414.          <?OutputLevel> 
  11415.          <?OutputLine> 
  11416.          <?PpwizardAuthor> 
  11417.          <?PpwizardAuthorBaseWebDir> 
  11418.          <?PpwizardAuthorEmail> 
  11419.          <?PpwizardAuthorHomePage> 
  11420.          <?PpwizardGeneratorMetaTags> 
  11421.          <?PpwizardHomePage> 
  11422.          <?PpwizardPgm> 
  11423.          <?ProcessingMode> 
  11424.          <?ProtectFromPpwStart> 
  11425.          <?ProtectFromPpwEnd> 
  11426.          <?QuestionMark> 
  11427.          <?RestartLine> 
  11428.          <?RexxSkip> 
  11429.          <?RexxSkipTo> 
  11430.          <?SemiColon> 
  11431.          <?Space> 
  11432.          <?TemplateDataFile> 
  11433.          <?TotalOutputLines> 
  11434.          <?Unique> 
  11435.          <?Version> 
  11436.          <?xXX> 
  11437.  
  11438.  Hopefully you have noticed that quite a few of the REXX calls can easily be 
  11439.  called using the "<?=RexxExpression>" format listed above. 
  11440.  
  11441.  Note that you can define your own variations of "standard" variables with the 
  11442.  "#evaluate" command, for example, to create an alternative way to display the 
  11443.  Compile Time. 
  11444.  
  11445.  EXAMPLES OF CREATING VARIABLES 
  11446.  
  11447.       ;--- Capture some HTML output file information ------------------------------
  11448.       #evaluate ShortNameHtml            "_filespec('name', '<?OutputFile>')"  ;; Reference standard definition.
  11449.       #evaluate ShortNameHtmlLowerCase   "translate('<$ShortNameHtml>', 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
  11450.  
  11451.       ;--- Capture date/time information (<$DateTime> --> Friday March 27 1998 at 7<$colon>46pm ---
  11452.       #evaluate DateTime @date('WeekDay') || ' ' || date('Month') || ' ' || substr(date('Sorted'), 7, 2) || ' ' || left(date('Sorted'), 4) || ' at ' || time('Civil')@
  11453.  
  11454.       ;--- Determine the current directory ----------------------------------------
  11455.       The current directory is "<?=directory()>".                              ;; Shorthand invocation of REXX function.
  11456.  
  11457.       ;--- Create YY.DDD Version # (example "98.107") --------------------------------------
  11458.       #evaluate YYDDD    ~substr(date('Sorted'),3,2) || '.' || date('Days')~
  11459.  
  11460.      ;--- Outputs the size of a file (takes parameter "File") --------------------
  11461.      #define SizeOfFile                                                                                                         \
  11462.              #evaluate+  LocalFileName    ^ReplaceString("../{$File}", "/", "\")^                                               \
  11463.              #DependsOn  INPUT            "<$LocalFileName>"                                                                    \
  11464.              #evaluate+  TmpFileSize      ^AddCommasToDecimalNumber(stream("<$LocalFileName>", "c", "query size"))^             \
  11465.              #if "<$TmpFileSize>" = ""                                                                                          \
  11466.                  #error $Failed getting size of "<$LocalFileName>"$                                                             \
  11467.              #endif                                                                                                             \
  11468.              <$TmpFileSize>
  11469.      #define SizeOfFileInSmallFont   <FONT SIZE=-1>{$Before=""}<$SizeOfFile File=*{$File}*> bytes{$After=""}</FONT>
  11470.      #define (SizeOfFileInSmallFont) <$SizeOfFileInSmallFont File=*{$File}* Before='(' After=')'>
  11471.  
  11472.      ;--- Outputs the date (Ausi format... YES!) (takes parameter "File") --------
  11473.      #define DateOfFile                                                                                                                                \
  11474.              #evaluate+  LocalFileName    ^ReplaceString("../{$File}", "/", "\")^                                                                      \
  11475.              #DependsOn  INPUT            "<$LocalFileName>"                                                                                           \
  11476.              #evaluate+  TmpFileTime      ^stream("<$LocalFileName>", "c", "query datetime")^                                                          \
  11477.              #if "<$TmpFileTime>" = ""                                                                                                                 \
  11478.                  #error $Failed getting date/time of "<$LocalFileName>"$                                                                               \
  11479.              #endif                                                                                                                                    \
  11480.              #evaluate+ TmpFileDate       ~substr('<$TmpFileTime>', 4, 2) || '/' || left('<$TmpFileTime>', 2) || '/' || substr('<$TmpFileTime>', 7,2)~ \
  11481.              <$TmpFileDate>
  11482.      #define DateOfFileInSmallFont   <FONT SIZE=-1>{$Before=""}<$DateOfFile File=*{$File}*>{$After=""}</FONT>
  11483.  
  11484.  
  11485. ΓòÉΓòÉΓòÉ 10.1. <??RexxVariable> ΓòÉΓòÉΓòÉ
  11486.  
  11487. <??RexxVariable> 
  11488.  
  11489. It is possible to access REXX variables without first obtaining a copy of their 
  11490. value with the "#evaluate command.  Any symbol that starts with <?? and ends 
  11491. with > is a command to get the value of the REXX variable in between. 
  11492.  
  11493. This is a Standard Definition which always exists (you don't need to #define 
  11494. it).  Note that you can create your own variations or completely new ones (see 
  11495. the examples). 
  11496.  
  11497. Example 
  11498.  
  11499. The following is an example which creates <H1>, <H2> HTML tagging etc: 
  11500.  
  11501.     #RexxVar    HeadingLevel = 1                      ;;Create a rexx variable (set to 1)
  11502.     #RexxVar    HeadingLevel + 1                      ;;Increase value by 1
  11503.  
  11504.     <H<??HeadingLevel>>A heading</H<??HeadingLevel>>  ;;Use it
  11505.  
  11506.  
  11507. ΓòÉΓòÉΓòÉ 10.2. <?=RexxExpression> ΓòÉΓòÉΓòÉ
  11508.  
  11509. <?=RexxExpression> 
  11510.  
  11511. A "variable" of this type allows you to evaluate a REXX expression, without 
  11512. using a separate #evaluate command.  Each time you use it, a relatively slow 
  11513. REXX "interpret" command is required, so for performance reasons it is 
  11514. recommended that you: 
  11515.  
  11516.          Use "<??RexxVariable>" to obtain the contents of a single REXX 
  11517.           variable. 
  11518.  
  11519.          Use a single "#evaluate" command and store the result for reuse 
  11520.           rather than using the same REXX "variable" expression multiple times. 
  11521.  
  11522.  The REXX expression has the limitation that it must not contain the ">" 
  11523.  character! 
  11524.  
  11525.  This is a Standard Definition which always exists (you don't need to #define 
  11526.  it).  Note that you can create your own variations or completely new ones (see 
  11527.  the examples). 
  11528.  
  11529.  Example 
  11530.  
  11531.       ;--- 5 '*' chars ----
  11532.       <?=copies('*',2)||copies('*',3)>
  11533.  
  11534.       ;--- Next line is invalid (compile will fail) ---
  11535.       <?=copies('*',2)||copies('>',3)>
  11536.  
  11537.  
  11538. ΓòÉΓòÉΓòÉ 10.3. <?/> ΓòÉΓòÉΓòÉ
  11539.  
  11540. <?/> 
  11541.  
  11542. This variable contains the value established by the /XSLASH switch. This allows 
  11543. you to vary the format of generated HTML, creating the XHTML syntax if you 
  11544. prefer. 
  11545.  
  11546. This is a Standard Definition which always exists (you don't need to #define 
  11547. it).  Note that you can create your own variations or completely new ones (see 
  11548. the examples). 
  11549.  
  11550. Example 
  11551.  
  11552. The following is one way that this symbol can be used. In the example, the "HR" 
  11553. macro will generate either "<hr>" or "<hr />". 
  11554.  
  11555. NOTE: XHTML code has other syntactic requirements, but since these are 
  11556. compatable with HTML there is nothing stopping you from doing most of this now. 
  11557.  
  11558.     ;--- Define some HTML tags which vary from "HTML" to "XHTML" ---
  11559.     #define HR  <hr<?/>>
  11560.  
  11561.     ;--- More complex macro ---
  11562.     #define /P                                                    \
  11563.             ;--- I don't wish to generate TAG unless XHTML ---   -\
  11564.             #if ['<?/>' <> '']                                   -\
  11565.                 </p>                                             -\
  11566.             #endif
  11567.  
  11568.     ;--- User the "HR" & "/P" tags ---
  11569.     <$hr>
  11570.     <p>Hi ya<$/p>
  11571.  
  11572.  
  11573. ΓòÉΓòÉΓòÉ 10.4. <?BaseDir> ΓòÉΓòÉΓòÉ
  11574.  
  11575. <?BaseDir> 
  11576.  
  11577. Each input file has an associated "base directory", this is normally the 
  11578. directory used on the input mask but can be overriden with the /BaseDir switch. 
  11579.  
  11580. This is a Standard Definition which always exists (you don't need to #define 
  11581. it).  Note that you can create your own variations or completely new ones (see 
  11582. the examples). 
  11583.  
  11584.  
  11585. ΓòÉΓòÉΓòÉ 10.5. <?CgiStart> ΓòÉΓòÉΓòÉ
  11586.  
  11587. <?CgiStart> 
  11588.  
  11589. This variable expands to the following 2 lines: 
  11590.  
  11591.        1. Content-type: text/html 
  11592.  
  11593.        2. Blank line 
  11594.  
  11595.  These lines are required at the start of all CGI output. 
  11596.  
  11597.  This is a Standard Definition which always exists (you don't need to #define 
  11598.  it).  Note that you can create your own variations or completely new ones (see 
  11599.  the examples). 
  11600.  
  11601.  
  11602. ΓòÉΓòÉΓòÉ 10.6. <?CmdLineTotal> ΓòÉΓòÉΓòÉ
  11603.  
  11604. <?CmdLineTotal> 
  11605.  
  11606. This variable contains the complete command line being used. This does not 
  11607. include any /List or project files, as their contents (any parameters these 
  11608. specified) are included in the value. 
  11609.  
  11610. The value covers switches and parameters from all sources: environment, project 
  11611. files, and specified on the command line. Any spaces within a parameter have 
  11612. been replaced with {x20} codes. 
  11613.  
  11614. This is a Standard Definition which always exists (you don't need to #define 
  11615. it).  Note that you can create your own variations or completely new ones (see 
  11616. the examples). 
  11617.  
  11618.  
  11619. ΓòÉΓòÉΓòÉ 10.7. <?CompileTime> ΓòÉΓòÉΓòÉ
  11620.  
  11621. <?CompileTime> 
  11622.  
  11623. This variable contains the date and time the compile started. 
  11624.  
  11625. The date and time is of a fairly "pretty" format, but it is country dependant 
  11626. and subject to change at my whim. Basically, if you need a specific format then 
  11627. create your own, do not assume that this variable returns any specific format. 
  11628.  
  11629. This is a Standard Definition which always exists (you don't need to #define 
  11630. it).  Note that you can create your own variations or completely new ones (see 
  11631. the examples). 
  11632.  
  11633. Example Of Creating Your Own Format 
  11634.  
  11635.     #evaluate DateTime  @date('WeekDay') || ' ' || date('Month') || ' ' || substr(date('Sorted'), 7, 2) || ' ' || left(date('Sorted'), 4) || ' at ' || time('Civil')@
  11636.  
  11637.  
  11638. ΓòÉΓòÉΓòÉ 10.8. <?DebugOn> ΓòÉΓòÉΓòÉ
  11639.  
  11640. <?DebugOn> 
  11641.  
  11642. This variable will tell you whether debug is currently on or off by returning 
  11643. 'Y' (it's on) or 'N'. 
  11644.  
  11645. You could use this to add comments to generated output when debug is on, etc. 
  11646.  
  11647. You could also use the IsDebugOn() function to obtain similar information. 
  11648.  
  11649. This is a Standard Definition which always exists (you don't need to #define 
  11650. it).  Note that you can create your own variations or completely new ones (see 
  11651. the examples). 
  11652.  
  11653.  
  11654. ΓòÉΓòÉΓòÉ 10.9. <?DirSlash> ΓòÉΓòÉΓòÉ
  11655.  
  11656. <?DirSlash> 
  11657.  
  11658. This variable contains the character used to separate components of a path. 
  11659. For most operating systems this will be '\' however UNIX uses '/' instead. 
  11660.  
  11661. This is a Standard Definition which always exists (you don't need to #define 
  11662. it).  Note that you can create your own variations or completely new ones (see 
  11663. the examples). 
  11664.  
  11665.  
  11666. ΓòÉΓòÉΓòÉ 10.10. <?Dollar> ΓòÉΓòÉΓòÉ
  11667.  
  11668. <?Dollar> 
  11669.  
  11670. This variable will be replaced by a '$' character. You may need to use it in 
  11671. some situations, for example, where you wish to generate '<$' (otherwise 
  11672. PPWIZARD will interpret this as the start of macro replacement). 
  11673.  
  11674. This symbol actually expands to a <?xXX> code and not the '$' character 
  11675. directly. In some cases this may not be what you wish and you should either 
  11676. define your own alternative or use some other method (#define may be suitable 
  11677. in a lot of cases), depending on your need. 
  11678.  
  11679. This is a Standard Definition which always exists (you don't need to #define 
  11680. it).  Note that you can create your own variations or completely new ones (see 
  11681. the examples). 
  11682.  
  11683.  
  11684. ΓòÉΓòÉΓòÉ 10.11. <?Hash> ΓòÉΓòÉΓòÉ
  11685.  
  11686. <?Hash> 
  11687.  
  11688. This variable will be replaced by a '#' character. 
  11689.  
  11690. This symbol actually expands to a <?xXX> code and not the '#' character 
  11691. directly. In some cases this may not be what you wish and you should either 
  11692. define your own alternative or use some other method (#define may be suitable 
  11693. in a lot of cases), depending on your need. 
  11694.  
  11695. This is a Standard Definition which always exists (you don't need to #define 
  11696. it).  Note that you can create your own variations or completely new ones (see 
  11697. the examples). 
  11698.  
  11699.  
  11700. ΓòÉΓòÉΓòÉ 10.12. <?HashPrefix> ΓòÉΓòÉΓòÉ
  11701.  
  11702. <?HashPrefix> 
  11703.  
  11704. This variable will be replaced by the current hash prefix character(s), that 
  11705. is, whatever was set with the 'HashPrefix' option. 
  11706.  
  11707. This is a Standard Definition which always exists (you don't need to #define 
  11708. it).  Note that you can create your own variations or completely new ones (see 
  11709. the examples). 
  11710.  
  11711.  
  11712. ΓòÉΓòÉΓòÉ 10.13. <?IncludeLevel> ΓòÉΓòÉΓòÉ
  11713.  
  11714. <?IncludeLevel> 
  11715.  
  11716. This variable contains the level of file inclusion starting at 1.  For each 
  11717. #include it goes up by one and goes back down by 1 when processing of that file 
  11718. completes. 
  11719.  
  11720. This is a Standard Definition which always exists (you don't need to #define 
  11721. it).  Note that you can create your own variations or completely new ones (see 
  11722. the examples). 
  11723.  
  11724.  
  11725. ΓòÉΓòÉΓòÉ 10.14. <?InputComponent> ΓòÉΓòÉΓòÉ
  11726.  
  11727. <?InputComponent> 
  11728.  
  11729. This variable contains the full filename of the input file currently being 
  11730. processed. 
  11731.  
  11732. If you need to access the name of an input file other than the current one, 
  11733. then you will need to use the InputComponentLevel() routine. 
  11734.  
  11735. If you need the name of the base source file (determined from the InputMask 
  11736. specified on the command line), and you are obtaining the information within 
  11737. your standard header files, you will need to use "<?InputFile>" instead. 
  11738.  
  11739. If you require the path or short name component, then use the "#evaluate" 
  11740. command to subdivide the full name. 
  11741.  
  11742. This is a Standard Definition which always exists (you don't need to #define 
  11743. it).  Note that you can create your own variations or completely new ones (see 
  11744. the examples). 
  11745.  
  11746.  
  11747. ΓòÉΓòÉΓòÉ 10.15. <?InputComponentLine> ΓòÉΓòÉΓòÉ
  11748.  
  11749. <?InputComponentLine> 
  11750.  
  11751. This variable contains the current line number of the input file currently 
  11752. being processed. 
  11753.  
  11754. If you need to access the line number of other included files, then you will 
  11755. need to use the InputComponentLineLevel() routine. 
  11756.  
  11757. This is a Standard Definition which always exists (you don't need to #define 
  11758. it).  Note that you can create your own variations or completely new ones (see 
  11759. the examples). 
  11760.  
  11761.  
  11762. ΓòÉΓòÉΓòÉ 10.16. <?InputFile> ΓòÉΓòÉΓòÉ
  11763.  
  11764. <?InputFile> 
  11765.  
  11766. This variable contains the full filename of the base input file that was 
  11767. specified on the command line. 
  11768.  
  11769. This definition is useful to extract this information in your standard header 
  11770. files as "<?InputComponent>" could return the name of the header file! 
  11771.  
  11772. If you require the path or short name component, then use the "#evaluate" 
  11773. command to subdivide the full name. 
  11774.  
  11775. This is a Standard Definition which always exists (you don't need to #define 
  11776. it).  Note that you can create your own variations or completely new ones (see 
  11777. the examples). 
  11778.  
  11779.  
  11780. ΓòÉΓòÉΓòÉ 10.17. <?LessThan> ΓòÉΓòÉΓòÉ
  11781.  
  11782. <?LessThan> 
  11783.  
  11784. This variable will be replaced by a '<' character. 
  11785.  
  11786. This symbol actually expands to a <?xXX> code and not the '<' character 
  11787. directly. In some cases this may not be what you wish and you should either 
  11788. define your own alternative or use some other method (#define may be suitable 
  11789. in a lot of cases), depending on your need. 
  11790.  
  11791. This is a Standard Definition which always exists (you don't need to #define 
  11792. it).  Note that you can create your own variations or completely new ones (see 
  11793. the examples). 
  11794.  
  11795.  
  11796. ΓòÉΓòÉΓòÉ 10.18. <?NewestFileDateTime> ΓòÉΓòÉΓòÉ
  11797.  
  11798. <?NewestFileDateTime> 
  11799.  
  11800. This variable will return the newest source file's date/time (so far) allowing 
  11801. you to date/timestamp your output with this information and not the date/time 
  11802. of the compile. 
  11803.  
  11804. Note that the "compiler" (PPWIZARD) is considered to be a source file, as it 
  11805. also determines the format of the output. If the variable is used after the 
  11806. last #include to be processed, then the value returned must be the date/time of 
  11807. the latest file (so unless you are added the timestamp information near the end 
  11808. of your output you may not be able to make use of this variable). 
  11809.  
  11810. The information is returned in the same format as that returned by the 
  11811. "GetFileTimeStamp()" routine (except that -1 is not possible).  Also have a 
  11812. look at its example, as the macro it shows could be used with very minor 
  11813. modification.  It is possible to work out the day of the week if you use the 
  11814. basedate routine. 
  11815.  
  11816. This is a Standard Definition which always exists (you don't need to #define 
  11817. it).  Note that you can create your own variations or completely new ones (see 
  11818. the examples). 
  11819.  
  11820.  
  11821. ΓòÉΓòÉΓòÉ 10.19. <?NewLine> ΓòÉΓòÉΓòÉ
  11822.  
  11823. <?NewLine> 
  11824.  
  11825. This variable forces following text onto the next line. (This is true even if 
  11826. it is the first thing on a line, which will result in a blank line in the 
  11827. output. If you don't want that, use <?NewLine?>.) It can be useful if you need 
  11828. to pass the generated HTML through other tools which can't handle long lines. 
  11829. The code would typically be used in macros. 
  11830.  
  11831. Note that this variable is the only way to ensure that the line is terminated 
  11832. correctly as the "/CrLf" switch (and others) may vary the appropriate codes 
  11833. that need to be generated. 
  11834.  
  11835. This symbol actually expands to a <?xXX> code and not the 'newline' character 
  11836. directly. In some cases this may not be what you wish and you should either 
  11837. define your own alternative or use some other method (#define may be suitable 
  11838. in a lot of cases), depending on your need. 
  11839.  
  11840. This is a Standard Definition which always exists (you don't need to #define 
  11841. it).  Note that you can create your own variations or completely new ones (see 
  11842. the examples). 
  11843.  
  11844.  
  11845. ΓòÉΓòÉΓòÉ 10.20. <?NewLine?> ΓòÉΓòÉΓòÉ
  11846.  
  11847. <?NewLine?> 
  11848.  
  11849. The text following this code will begin on a new line. The code will only 
  11850. generate a newline if required (it is a conditional newline). 
  11851.  
  11852. This code can be very handy in macros or similar situations where you may have 
  11853. no idea as to whether or not you are at the start of a line (and, like me, you 
  11854. hate excessive numbers of blank lines). 
  11855.  
  11856. This is a Standard Definition which always exists (you don't need to #define 
  11857. it).  Note that you can create your own variations or completely new ones (see 
  11858. the examples). 
  11859.  
  11860.  
  11861. ΓòÉΓòÉΓòÉ 10.21. <?OpSys> ΓòÉΓòÉΓòÉ
  11862.  
  11863. <?OpSys> 
  11864.  
  11865. This variable indicates the generic operating system you are running on and is 
  11866. probably one of the following values: 
  11867.  
  11868.          OS/2 
  11869.          DOS 
  11870.          WIN32 (WIN95-WINXP) 
  11871.          UNIX  (FREEBSD, TSO ...) 
  11872.  
  11873.  If you need to know which version of Windows or UNIX etc you are on you will 
  11874.  need to look at the "<?OpSysSpecific>" symbol. 
  11875.  
  11876.  This is a Standard Definition which always exists (you don't need to #define 
  11877.  it).  Note that you can create your own variations or completely new ones (see 
  11878.  the examples). 
  11879.  
  11880.  
  11881. ΓòÉΓòÉΓòÉ 10.22. <?OpSysSpecific> ΓòÉΓòÉΓòÉ
  11882.  
  11883. <?OpSysSpecific> 
  11884.  
  11885. The "<?OpSys>" symbol holds a generic value, this symbol contains a specific 
  11886. operating system name, for example, if the generic operating system was "WIN32" 
  11887. then this symbol might contain: 
  11888.  
  11889.          WINXP 
  11890.          WIN2K 
  11891.          WINNT 
  11892.          WINME 
  11893.          WIN98 
  11894.          WIN95 
  11895.          ... 
  11896.  
  11897.  Note that regina 2.2 beta and earlier versions will not report all versions of 
  11898.  Windows correctly so for example Windows 2000 will be reported as "WINNT". 
  11899.  
  11900.  If the generic operating system was "UNIX" then this symbol might contain: 
  11901.  
  11902.          FREEBSD 
  11903.          BEOS 
  11904.          TSO 
  11905.          ... 
  11906.  
  11907.  The value returned by this symbol might be equal to that provided by 
  11908.  "<?OpSys>" if we can't get more specific. 
  11909.  
  11910.  This is a Standard Definition which always exists (you don't need to #define 
  11911.  it).  Note that you can create your own variations or completely new ones (see 
  11912.  the examples). 
  11913.  
  11914.  
  11915. ΓòÉΓòÉΓòÉ 10.23. <?OutputFile> ΓòÉΓòÉΓòÉ
  11916.  
  11917. <?OutputFile> 
  11918.  
  11919. This variable contains the full filename of the current output file. 
  11920.  
  11921. If you require the path or short name component, then use the "#evaluate" 
  11922. command to subdivide the full name. 
  11923.  
  11924. This is a Standard Definition which always exists (you don't need to #define 
  11925. it).  Note that you can create your own variations or completely new ones (see 
  11926. the examples). 
  11927.  
  11928.  
  11929. ΓòÉΓòÉΓòÉ 10.24. <?OutputLevel> ΓòÉΓòÉΓòÉ
  11930.  
  11931. <?OutputLevel> 
  11932.  
  11933. This variable contains the output nesting level.  When it is '1', the output 
  11934. goes to the default output file; each #Output with filename adds one, while a 
  11935. #output without filename subtracts one. 
  11936.  
  11937. This variable would be handy in complex macro sets where #output commands are 
  11938. automatically generated. 
  11939.  
  11940. This is a Standard Definition which always exists (you don't need to #define 
  11941. it).  Note that you can create your own variations or completely new ones (see 
  11942. the examples). 
  11943.  
  11944. Example 
  11945.  
  11946.     This line is at Output Level 1
  11947.     #output  '2nd'
  11948.        This line is at Output Level 2
  11949.        #output 'c<$colon>\path\3nd.ext' AsIs
  11950.                This line is at Output Level 3
  11951.        #output
  11952.        This line is at Output Level 2
  11953.     #output
  11954.     This line is at Output Level 1
  11955.  
  11956.  
  11957. ΓòÉΓòÉΓòÉ 10.25. <?OutputLine> ΓòÉΓòÉΓòÉ
  11958.  
  11959. <?OutputLine> 
  11960.  
  11961. This variable contains the line number of the next line to be generated ("this 
  11962. line") into the current output file. 
  11963.  
  11964. Note that if this definition is used within a macro then all occurrences within 
  11965. the macro will expand to the same value no matter how many lines the macro 
  11966. might generate. 
  11967.  
  11968. This is a Standard Definition which always exists (you don't need to #define 
  11969. it).  Note that you can create your own variations or completely new ones (see 
  11970. the examples). 
  11971.  
  11972.  
  11973. ΓòÉΓòÉΓòÉ 10.26. <?PpwizardAuthor> ΓòÉΓòÉΓòÉ
  11974.  
  11975. <?PpwizardAuthor> 
  11976.  
  11977. This variable contains the name of the developer of the PPWIZARD program. Use 
  11978. this if you wish to make mention of PPWIZARD on your homepages. 
  11979.  
  11980. This is a Standard Definition which always exists (you don't need to #define 
  11981. it).  Note that you can create your own variations or completely new ones (see 
  11982. the examples). 
  11983.  
  11984.  
  11985. ΓòÉΓòÉΓòÉ 10.27. <?PpwizardAuthorBaseWebDir> ΓòÉΓòÉΓòÉ
  11986.  
  11987. <?PpwizardAuthorBaseWebDir> 
  11988.  
  11989. This variable contains the name of the base directory of PPWIZARD's authors web 
  11990. page (this will end with a slash). 
  11991.  
  11992. This is a Standard Definition which always exists (you don't need to #define 
  11993. it).  Note that you can create your own variations or completely new ones (see 
  11994. the examples). 
  11995.  
  11996.  
  11997. ΓòÉΓòÉΓòÉ 10.28. <?PpwizardAuthorEmail> ΓòÉΓòÉΓòÉ
  11998.  
  11999. <?PpwizardAuthorEmail> 
  12000.  
  12001. This variable contains the e-mail address of the developer of the PPWIZARD 
  12002. program. Use this if you wish to make mention of PPWIZARD on your homepages. 
  12003.  
  12004. This is a Standard Definition which always exists (you don't need to #define 
  12005. it).  Note that you can create your own variations or completely new ones (see 
  12006. the examples). 
  12007.  
  12008.  
  12009. ΓòÉΓòÉΓòÉ 10.29. <?PpwizardAuthorHomePage> ΓòÉΓòÉΓòÉ
  12010.  
  12011. <?PpwizardAuthorHomePage> 
  12012.  
  12013. This variable contains the internet address of the computer home page of the 
  12014. developer of the PPWIZARD program. 
  12015.  
  12016. Note that I recommend that if you point to other pages of mine that you either 
  12017. use a #evaluate on this variable to obtain the base path or validate that it 
  12018. contains what you expect (and fail with #error if it doesn't).  This way, if I 
  12019. change my homepage you will be informed via a new version of PPWIZARD. 
  12020.  
  12021. This is a Standard Definition which always exists (you don't need to #define 
  12022. it).  Note that you can create your own variations or completely new ones (see 
  12023. the examples). 
  12024.  
  12025.  
  12026. ΓòÉΓòÉΓòÉ 10.30. <?PpwizardGeneratorMetaTags> ΓòÉΓòÉΓòÉ
  12027.  
  12028. <?PpwizardGeneratorMetaTags> 
  12029.  
  12030. This variable contains the default HTML meta tags for this program. 
  12031.  
  12032. This is a Standard Definition which always exists (you don't need to #define 
  12033. it).  Note that you can create your own variations or completely new ones (see 
  12034. the examples). 
  12035.  
  12036.  
  12037. ΓòÉΓòÉΓòÉ 10.31. <?PpwizardHomePage> ΓòÉΓòÉΓòÉ
  12038.  
  12039. <?PpwizardHomePage> 
  12040.  
  12041. This variable contains the address of this program's HTML home page. Use it if 
  12042. you wish to make mention of PPWIZARD on your homepages. 
  12043.  
  12044. This is a Standard Definition which always exists (you don't need to #define 
  12045. it).  Note that you can create your own variations or completely new ones (see 
  12046. the examples). 
  12047.  
  12048.  
  12049. ΓòÉΓòÉΓòÉ 10.32. <?PpwizardPgm> ΓòÉΓòÉΓòÉ
  12050.  
  12051. <?PpwizardPgm> 
  12052.  
  12053. This variable contains the full filename of the ppwizard program. The 
  12054. _filespec() routine would frequently be used to break the name apart, for 
  12055. example if you wished to know its home directory. 
  12056.  
  12057. This is a Standard Definition which always exists (you don't need to #define 
  12058. it).  Note that you can create your own variations or completely new ones (see 
  12059. the examples). 
  12060.  
  12061.  
  12062. ΓòÉΓòÉΓòÉ 10.33. <?ProcessingMode> ΓòÉΓòÉΓòÉ
  12063.  
  12064. <?ProcessingMode> 
  12065.  
  12066. This variable contains the current processing mode, which is one of the 
  12067. following: 
  12068.  
  12069.        1. HTML 
  12070.        2. REXX 
  12071.        3. OTHER 
  12072.  
  12073.  The mode can be set or specified in these situations: 
  12074.  
  12075.        1. /REXX 
  12076.        2. /HTML 
  12077.        3. /OTHER 
  12078.        4. #output 
  12079.  
  12080.  This is a Standard Definition which always exists (you don't need to #define 
  12081.  it).  Note that you can create your own variations or completely new ones (see 
  12082.  the examples). 
  12083.  
  12084.  
  12085. ΓòÉΓòÉΓòÉ 10.34. <?ProtectFromPpwStart> ΓòÉΓòÉΓòÉ
  12086.  
  12087. <?ProtectFromPpwStart> 
  12088.  
  12089. This variable expands to one or more commands that ensure that following lines 
  12090. are protected from change by PPWIZARD.  As examples, this prevents leading 
  12091. whitespace removal and text such as "#define" from being treated as commands. 
  12092. This is similar to the "#AsIs" command except that no "as is" tagging is 
  12093. performed and PPWIZARD commands are not processed. 
  12094.  
  12095. Note that this does not do any extra tagging such as that required to ensure 
  12096. that the text appears the same in a browser or IPF viewer, etc.  This must be 
  12097. taken care of by you ("#AutoTag"). 
  12098.  
  12099. You must use "<?ProtectFromPpwEnd>" at the end of the lines you wish to 
  12100. protect. 
  12101.  
  12102. This is a Standard Definition which always exists (you don't need to #define 
  12103. it).  Note that you can create your own variations or completely new ones (see 
  12104. the examples). 
  12105.  
  12106.  
  12107. ΓòÉΓòÉΓòÉ 10.35. <?ProtectFromPpwEnd> ΓòÉΓòÉΓòÉ
  12108.  
  12109. <?ProtectFromPpwEnd> 
  12110.  
  12111. This definition marks the end of a block of text to be protected from PPWIZARD 
  12112. processing. Please see "<?ProtectFromPpwStart>" for details. 
  12113.  
  12114. This is a Standard Definition which always exists (you don't need to #define 
  12115. it).  Note that you can create your own variations or completely new ones (see 
  12116. the examples). 
  12117.  
  12118.  
  12119. ΓòÉΓòÉΓòÉ 10.36. <?QuestionMark> ΓòÉΓòÉΓòÉ
  12120.  
  12121. <?QuestionMark> 
  12122.  
  12123. This variable will be replaced by a '?' character. 
  12124.  
  12125. This symbol actually expands to a <?xXX> code and not the '?' character 
  12126. directly. In some cases this may not be what you wish and you should either 
  12127. define your own alternative or use some other method (#define may be suitable 
  12128. in a lot of cases), depending on your need. 
  12129.  
  12130. This is a Standard Definition which always exists (you don't need to #define 
  12131. it).  Note that you can create your own variations or completely new ones (see 
  12132. the examples). 
  12133.  
  12134.  
  12135. ΓòÉΓòÉΓòÉ 10.37. <?RestartLine> ΓòÉΓòÉΓòÉ
  12136.  
  12137. <?RestartLine> 
  12138.  
  12139. By the time PPWIZARD macro replacement has taken place it is already decided 
  12140. that the line does not contain a PPWIZARD command.  If you wish to dynamically 
  12141. generate PPWIZARD commands, you need to use this variable at the start of every 
  12142. command (you could have more than one). 
  12143.  
  12144. Another possible reason for using this define is that PPWIZARD expands 
  12145. definitions in a single pass from left to right.  This means that you could not 
  12146. build up a reference to a variable from components unless you include this 
  12147. define. 
  12148.  
  12149. PPWIZARD will stop replacement of macros, etc. as soon as it has expanded the 
  12150. first define of this type on the line, so its position on a line can greatly 
  12151. affect the way expansion occurs. The use of this variable could cause other 
  12152. unwanted affects; it is up to you to test to ensure you are obtaining the 
  12153. results you require. 
  12154.  
  12155. This is a Standard Definition which always exists (you don't need to #define 
  12156. it).  Note that you can create your own variations or completely new ones (see 
  12157. the examples). 
  12158.  
  12159. Example 
  12160.  
  12161. In this example the intention is to create the macro variable "X": 
  12162.  
  12163.     ;--- "Command" contains the command we want executed ---
  12164.     #define Command  #define X XXXXXXXXXXXXXXXXXXXXX
  12165.  
  12166.     Attempt 1 - Fails
  12167.     ~~~~~~~~~~~~~~~~~
  12168.     <$Command>
  12169.  
  12170.     Attempt 2 - Works
  12171.     ~~~~~~~~~~~~~~~~~
  12172.     <?RestartLine><$Command>
  12173.  
  12174.     Test Definition
  12175.     ~~~~~~~~~~~~~~~
  12176.     Number of x's ==> <$X>
  12177.  
  12178.  
  12179. ΓòÉΓòÉΓòÉ 10.38. <?RexxSkip> ΓòÉΓòÉΓòÉ
  12180.  
  12181. <?RexxSkip> 
  12182.  
  12183. This symbol is used in conjunction with the "<?RexxSkipTo>" symbol to simplify 
  12184. the "skipping" of subroutines within a REXX header file. 
  12185.  
  12186. A header file will frequently include some initialization code followed by some 
  12187. routines.  The recommended place to include header files is at the start of 
  12188. your mainline code module.  To be able to hold common procedures in the header 
  12189. file you must skip over them after you have performed any required 
  12190. initialization. 
  12191.  
  12192. You could simply use a "signal EndRexxHeader" before the procedures and 
  12193. "EndRexxHeader:" after, however then you need to create a new label every time 
  12194. and it becomes difficult to include a header file more than once. 
  12195.  
  12196. This is a Standard Definition which always exists (you don't need to #define 
  12197. it).  Note that you can create your own variations or completely new ones (see 
  12198. the examples). 
  12199.  
  12200. Example - EXAMPLE.XH 
  12201.  
  12202.     /*--- Initialization for "EXAMPLE.XH" ---*/
  12203.     call InitStuff;
  12204.     <?RexxSkip>
  12205.  
  12206.     InitStuff:
  12207.        ...
  12208.        return;
  12209.  
  12210.     MoreCode:
  12211.        ...
  12212.        return;
  12213.  
  12214.     /*--- End of REXX header ---*/
  12215.     <?RexxSkipTo>
  12216.  
  12217.  
  12218. ΓòÉΓòÉΓòÉ 10.39. <?RexxSkipTo> ΓòÉΓòÉΓòÉ
  12219.  
  12220. <?RexxSkipTo> 
  12221.  
  12222. This symbol is used in conjunction with the "<?RexxSkip>" symbol to simplify 
  12223. the "skipping" of subroutines within a REXX header file. 
  12224.  
  12225. Every use of "<?RexxSkip>" must be followed by the use of the "<?RexxSkipTo>" 
  12226. symbol. 
  12227.  
  12228. This is a Standard Definition which always exists (you don't need to #define 
  12229. it).  Note that you can create your own variations or completely new ones (see 
  12230. the examples). 
  12231.  
  12232. Example 
  12233.  
  12234. See <?RexxSkip>. 
  12235.  
  12236.  
  12237. ΓòÉΓòÉΓòÉ 10.40. <?SemiColon> ΓòÉΓòÉΓòÉ
  12238.  
  12239. <?SemiColon> 
  12240.  
  12241. This variable will be replaced by a single semicolon (;) character.  It could 
  12242. be useful if you have the odd line that must begin with a semicolon.  The 
  12243. semicolon is the default character to begin a line comment. 
  12244.  
  12245. This symbol actually expands to a <?xXX> code and not the ';' character 
  12246. directly. In some cases this may not be what you wish and you should either 
  12247. define your own alternative or use some other method (#define may be suitable 
  12248. in a lot of cases), depending on your need. 
  12249.  
  12250. This is a Standard Definition which always exists (you don't need to #define 
  12251. it).  Note that you can create your own variations or completely new ones (see 
  12252. the examples). 
  12253.  
  12254.  
  12255. ΓòÉΓòÉΓòÉ 10.41. <?Space> ΓòÉΓòÉΓòÉ
  12256.  
  12257. <?Space> 
  12258.  
  12259. This variable will be replaced by a single space, it is most useful for 
  12260. ensuring that you have required spaces on lines that were continued using the 
  12261. '\' character. 
  12262.  
  12263. This symbol actually expands to a <?xXX> code and not the ' ' character 
  12264. directly. In some cases this may not be what you wish and you should either 
  12265. define your own alternative or use some other method (#define may be suitable 
  12266. in a lot of cases), depending on your need. 
  12267.  
  12268. This is a Standard Definition which always exists (you don't need to #define 
  12269. it).  Note that you can create your own variations or completely new ones (see 
  12270. the examples). 
  12271.  
  12272.  
  12273. ΓòÉΓòÉΓòÉ 10.42. <?TemplateDataFile> ΓòÉΓòÉΓòÉ
  12274.  
  12275. <?TemplateDataFile> 
  12276.  
  12277. If the "/Template" switch was not specified then this variable will return an 
  12278. empty value, otherwise the name of the data file is returned (the template 
  12279. typically processes this file). 
  12280.  
  12281. By using this variable a header file could determine whether or not template 
  12282. processing is occurring. 
  12283.  
  12284. Example 
  12285.  
  12286. A typical template file might begin like: 
  12287.  
  12288.     ;--- Load data file, this template specified on "/template" switch ---
  12289.     #include "<?TemplateDataFile>"
  12290.  
  12291.  
  12292. ΓòÉΓòÉΓòÉ 10.43. <?TotalOutputLines> ΓòÉΓòÉΓòÉ
  12293.  
  12294. <?TotalOutputLines> 
  12295.  
  12296. This variable contains the total number of lines generated into all output 
  12297. files. 
  12298.  
  12299. This is a Standard Definition which always exists (you don't need to #define 
  12300. it).  Note that you can create your own variations or completely new ones (see 
  12301. the examples). 
  12302.  
  12303.  
  12304. ΓòÉΓòÉΓòÉ 10.44. <?Unique> ΓòÉΓòÉΓòÉ
  12305.  
  12306. <?Unique> 
  12307.  
  12308. This variable will be replaced by a unique number every time it is used. 
  12309.  
  12310. This is a Standard Definition which always exists (you don't need to #define 
  12311. it).  Note that you can create your own variations or completely new ones (see 
  12312. the examples). 
  12313.  
  12314. Example of Creating Your Own Counter 
  12315.  
  12316. If you wanted to have a number of counters running so that each is consecutive 
  12317. (no gaps) then this is one possible and self documenting way: 
  12318.  
  12319.     ;--- Generic Counter ---
  12320.     #NextId
  12321.     #define      Counter                        \
  12322.                  <$Rexx4Counter {$?} $$RXEXEC>
  12323.     #DefineRexx  'Rexx4Counter'
  12324.        ;--- Inc the value (start with 1) ---
  12325.        @@CntVAR    = 'Counter_{$#1}'       ;;Generate Rexx var name unlikely to class with anything!
  12326.        @@NumDigits = '{$Digits=^3^}'       ;;By default padded to 3 digits
  12327.        if  symbol(@@CntVAR) <> 'VAR' then
  12328.            @@Val = 1;                      ;;Start with 1
  12329.        else
  12330.            @@Val = value(@@CntVAR) + 1;    ;;Incremented existing counter
  12331.        call value @@CntVAR, @@Val;         ;;Remember value
  12332.  
  12333.        ;--- Pad the value (NEVER truncate!). Can "enable" correct sorting ---
  12334.        if  length(@@Val) >= @@NumDigits then
  12335.            RxExec = @@Val;                          ;;Don't pad!
  12336.        else
  12337.            RxExec = right(@@Val, @@NumDigits, '0'); ;;Pad to left with zeros
  12338.     #DefineRexx
  12339.  
  12340.     ;--- Use the counter ---
  12341.     Counter X is now: <$Counter "X">
  12342.     Counter Y is now: <$Counter "Y">
  12343.     Counter X is now: <$Counter "X">
  12344.  
  12345. Note that I very carefully did not use #evaluate etc so that PPWIZARD would 
  12346. never complain about the counters use even if used on PPWIZARD commands (where 
  12347. it might overwise cause an error). Also note that you will still need to be 
  12348. careful about how the macro is used as it does not care about whether the 
  12349. number is generated into the output file, it just cares about macro expansion. 
  12350.  
  12351.  
  12352. ΓòÉΓòÉΓòÉ 10.45. <?Version> ΓòÉΓòÉΓòÉ
  12353.  
  12354. <?Version> 
  12355.  
  12356. This variable will be replaced by the version number of the program.  The 
  12357. version number is in the form "YY.DDD", examples are "98.001" (first day of 
  12358. 1998) and "00.123" (123rd day of 2000). 
  12359.  
  12360. This is a Standard Definition which always exists (you don't need to #define 
  12361. it).  Note that you can create your own variations or completely new ones (see 
  12362. the examples). 
  12363.  
  12364. Example 
  12365.  
  12366. The following code shows how you could ensure that a general purpose header 
  12367. file can only be used if the preprocessor's version number is greater than a 
  12368. particular value.  You would do this if the header file requires a particular 
  12369. feature which only became available in a specific release. 
  12370.  
  12371.     /*--- Get PPWIZARD version # as YYYY.DDD ------------------------------------*/
  12372.     #if    <?Version> < 98.000
  12373.             #evaluate PPWizardVersion  "2000.00 + <?Version>";
  12374.     #elseif
  12375.             #evaluate PPWizardVersion  "1900.00 + <?Version>";
  12376.     #endif
  12377.  
  12378.     /*--- Validate PPWIZARD VERSION (Y2K safe) ----------------------------------*/
  12379.     #define DEFINEIT_MIN_PPWIZARD_VERSION    1998.188       ;;Rely on changes made in specific PPWIZARD release
  12380.     #if    <$PPWizardVersion> < <$DEFINEIT_MIN_PPWIZARD_VERSION>
  12381.             #error 'PPWIZARD version of at least <$DEFINEIT_MIN_PPWIZARD_VERSION> is required, you have <$PPWizardVersion>'
  12382.     #endif
  12383.  
  12384.  
  12385. ΓòÉΓòÉΓòÉ 10.46. <?xXX> ΓòÉΓòÉΓòÉ
  12386.  
  12387. <?xXX> 
  12388.  
  12389. Any variable which starts with 'x' has a special characteristic in that it is 
  12390. not replaced until just before a line is written to the output file. The only 
  12391. invalid character in the name of the variable is '>'. 
  12392.  
  12393. The replacements are made in a single pass from left to right. The replacement 
  12394. contents may not itself contain codes you wish to be interpreted in any way, as 
  12395. the text will be output exactly as specified. You have some control over when 
  12396. the replacement occurs; see the ExpandX option. 
  12397.  
  12398. The name of the symbol represents a variable whose contents was previously 
  12399. defined with the '=x=' operator of the #RexxVar command (or via the SetXCode() 
  12400. routine). 
  12401.  
  12402. Variables of this type are useful if you wish to use characters that can't be 
  12403. entered by the editing tool you are using. They also provide an emergency way 
  12404. out which might get you past instances where the character might otherwise be 
  12405. interpreted in a manner other than you wish.  For example if you must have the 
  12406. string "<?Version>" in your output (and not have it replaced by the version 
  12407. number)!  Another example is that "<?x09>" is the only way to get a tab into 
  12408. the generated output. 
  12409.  
  12410. This is a Standard Definition which always exists (you don't need to #define 
  12411. it).  Note that you can create your own variations or completely new ones (see 
  12412. the examples). 
  12413.  
  12414. Codes <?x00> to <?xFF> 
  12415.  
  12416. The 256 REXX variables "x00" to "xFF" have been preset to represent their ASCII 
  12417. character codes.  This means that "<?x09>" would get replaced with a tab 
  12418. character and "<?x41>" would get replaced with "A". 
  12419.  
  12420. You could, if you wished, change the appropriate REXX variables to change the 
  12421. replacement value.  For example you could decide the code for "<" gets replaced 
  12422. by "<" instead. 
  12423.  
  12424. Note that it would generally be better to "name" your ASCII codes as they would 
  12425. then be easier to understand. For example "xTAB" is a lot easier to understand 
  12426. than "x09"! 
  12427.  
  12428. It is highly recommended that you do not use "<?x0A>" codes to generate 
  12429. newlines; you should use "<?NewLine>". 
  12430.  
  12431. Example - Using Predefined ASCII Codes 
  12432.  
  12433.     #define Tab    <?x09>
  12434.  
  12435.     Col1<$Tab>Col2<$Tab>Col3
  12436.  
  12437. Example - Creating Your Own Codes 
  12438.  
  12439.     #evaluate 'Tab'       "d2c(9)"
  12440.     #RexxVar  "TAB"  =x=  "<$Tab>"             ;;TAB Char
  12441.     #RexxVar  "LA"   =x=  "<"               ;;'<' Char
  12442.     #RexxVar  "RA"   =x=  ">"               ;;'>' Char
  12443.  
  12444.     Col1<?xTab>Col2<?xTab>Col3
  12445.     <?xLA> = Less    than
  12446.     <?xRA> = Greater than
  12447.  
  12448. I have written a script language which gets converted to VbScript code for 
  12449. execution. User parameters are converted to VB string literals with any double 
  12450. quotes being doubled up (VB escape mechanism). Now I created a macro which 
  12451. allows imbedding of VB statements or variables into these literals, to do that 
  12452. the VB statement must not include a double quote (or it will get doubled up as 
  12453. mentioned earlier), so I need to define something which will generate a double 
  12454. quote in the resulting VB: 
  12455.  
  12456.     ;--- Allows imbedding of VB statements/variables in "literals" --------------
  12457.     #RexxVar ^VbDq^ =x= ^"^     ;;Can't use double quotes directly
  12458.     #define  VBIMBED                                                       \
  12459.              <?xVbDq>      ;;End literal with double quote                 \
  12460.              &             ;;Concatenate user's VB statement/variable      \
  12461.              {$STAT}       ;;User's VB statement/variable                  \
  12462.              &             ;;Concatenate rest of literal                   \
  12463.              <?xVbDq>      ;;Start Literal
  12464.  
  12465.     ;--- Use the macro to set property in MSI -----------------------------------
  12466.     <$SetProperty NAME=^<$BSDPROP_BUILT_WSI_TIME>^ VALUE=^<$VbImbed STAT=~VbMadeTime~>^>
  12467.  
  12468.  
  12469. ΓòÉΓòÉΓòÉ 11. Rexx ΓòÉΓòÉΓòÉ
  12470.  
  12471. Rexx 
  12472.  
  12473. REXX is a very powerful interpreted programming language. While you don't need 
  12474. to know much about rexx to use PPWIZARD you will find that you can do so much 
  12475. more if you do. There is a lot of 3rd party support for rexx, not only for OS/2 
  12476. but for windows as well. 
  12477.  
  12478. You can get a (slighty out of date) regina rexx manual from 
  12479. http://sites.netscape.net/ssatguru, this has HTML and compiled Windows Help 
  12480. formats for download. 
  12481.  
  12482. This program is written in rexx and has specific commands that allow you to 
  12483. embed rexx code. The following situations allow you to execute rexx code (some 
  12484. other minor situations as well): 
  12485.  
  12486.        1. #if commands. 
  12487.        2. #evaluate commands. 
  12488.        3. #import filters. 
  12489.        4. <?=RexxExpression> "standard definition". 
  12490.        5. In the CompareReplaceFixed() routine. 
  12491.  
  12492.  For OS/2 users an online rexx manual was installed for you (by OS/2 install 
  12493.  process).  Otherwise you can get a copy of the regina documentation from 
  12494.  http://www.lightlink.com/hessling/ 
  12495.  
  12496.  There is a DebugLevel option of REXXTRACE that you can turn on or off to 
  12497.  control level of debugging output from the rexx commands you execute. 
  12498.  Regina's debugging is not as good as OS/2's native debugging but it's still a 
  12499.  help. 
  12500.  
  12501.  The following sections provide a very small summary of rexx, for people 
  12502.  unfamiliar with programming this may not be enough and you may need to look 
  12503.  elsewhere. A good place to ask questions or just sit back and watch is the 
  12504.  news group "comp.lang.rexx". 
  12505.  
  12506.  Some Examples of Rexx Code Integration 
  12507.  
  12508.  Some simple one liners: 
  12509.  
  12510.       ;--- Capture some HTML information ---
  12511.       #evaluate ShortNameHtml            "_filespec('name', '<?OutputFile>')"
  12512.       #evaluate ShortNameHtmlLowerCase   "ToLowerCase('<$ShortNameHtml>')"
  12513.  
  12514.       ;--- Capture date/time information ---
  12515.       #evaluate DateTime @date('WeekDay') || ' ' || date('Month') || ' ' || substr(date('Sorted'), 7, 2) || ' ' || left(date('Sorted'), 4) || ' at ' || time('Civil')@
  12516.  
  12517.  More complex example where multi statement rexx is formatted in a very 
  12518.  readable manner (using #DefineRexx): 
  12519.  
  12520.       #DefineRexx IMPORT_RECORD_FILTER
  12521.                   if Column.1 = "Wendy" then
  12522.                      Remove='This is "Wendy" record'    ;;Don't want this record
  12523.                   else
  12524.                      Column.1 = translate(Column.1)     ;;Make column #1 upper case
  12525.       #DefineRexx
  12526.       #import ImportMe.CMA CMA "" "First<BR>Name" "Surname" "Job"
  12527.  
  12528.  
  12529. ΓòÉΓòÉΓòÉ 11.1. Rexx Variables ΓòÉΓòÉΓòÉ
  12530.  
  12531. Rexx Variables 
  12532.  
  12533. You can get a (slighty out of date) regina rexx manual from 
  12534. http://sites.netscape.net/ssatguru, this has HTML and compiled Windows Help 
  12535. formats for download. 
  12536.  
  12537. Rexx unlike many other programming languages does not require its variables to 
  12538. be predefined and there is only one type (string). A number is just a string of 
  12539. characters. 
  12540.  
  12541. Variable names can be any reasonable length and can contain the letters 'A' to 
  12542. 'Z', the digits '0' to '9' or any of "!?_" (digits can't start a variable 
  12543. name). 
  12544.  
  12545. In PPWIZARD you must not try to use the value of a variable which does not 
  12546. exist or it will trap with a "NOVALUE" abort and output diagnostic information 
  12547. which should spell out your problem. 
  12548.  
  12549. I very much recommend that you don't use simple rexx variable names such as 
  12550. "Count".  This is dangerous as it may clash with PPWIZARD variables. If this 
  12551. occurs it will probably be very difficult to diagnose and PPWIZARD (and your 
  12552. code) will probably malfunction in unpredictable ways. 
  12553.  
  12554. No PPWIZARD variables start with '_' and for this reason I recommend that you 
  12555. preceed all variable names with this character. For example instead of 'Count' 
  12556. use '_Count'. 
  12557.  
  12558. All rexx variables you define are global, as are those used by PPWIZARD.  This 
  12559. gives a lot of its power but it can also be dangerous. Always try to be aware 
  12560. of this fact. 
  12561.  
  12562. You also need to be aware that PPWIZARD may modify the rexx RC or RESULT 
  12563. variables that you believe has been set by an #evaluate command.  Do not rely 
  12564. on these variables, set your own (of course within a single #evaluate PPWIZARD 
  12565. will not touch these variables). 
  12566.  
  12567. Some examples of giving rexx variables a value: 
  12568.  
  12569.        #evaluate ^^   ^_Count   = 1^             ;;Both this and next line set value to the number 1
  12570.        #evaluate ^^   ^_Count   = '1'^
  12571.        #evaluate ^^   ^_Count   = _Count + 1^    ;;Increase value by 1
  12572.        #evaluate ^^   ^_Array.1 = 'a value'^
  12573.        #evaluate ^^   ^_Fred    = "a value"^
  12574.  
  12575.  
  12576. ΓòÉΓòÉΓòÉ 11.2. Rexx Expressions ΓòÉΓòÉΓòÉ
  12577.  
  12578. Rexx Expressions 
  12579.  
  12580. You can get a (slighty out of date) regina rexx manual from 
  12581. http://sites.netscape.net/ssatguru, this has HTML and compiled Windows Help 
  12582. formats for download. 
  12583.  
  12584. The following operators can be used: 
  12585.  
  12586.          + 
  12587.           Adds values. 
  12588.  
  12589.          - 
  12590.           Subtracts values. 
  12591.  
  12592.          * 
  12593.           Multiplies values. 
  12594.  
  12595.          / 
  12596.           Divides values (5/2 => 2.5). 
  12597.  
  12598.          % 
  12599.           Divides values, want whole number (5/2 => 2). 
  12600.  
  12601.          // 
  12602.           Divides values, want remainder (5//2 => 1). 
  12603.  
  12604.  Expressions can also make use of PPWIZARD or standard rexx functions. 
  12605.  
  12606.  Some examples of expressions being used: 
  12607.  
  12608.          #evaluate ^^   ^ResultOfExpression = (10 + 8) / 2^        ;;Value 9
  12609.          #evaluate ^^   ^ResultOfExpression = (_Count - 1) % $Div^
  12610.          #evaluate ^^   ^Path               = GetEnv('PATH')^
  12611.  
  12612.  
  12613. ΓòÉΓòÉΓòÉ 11.3. Rexx Conditional Logic ΓòÉΓòÉΓòÉ
  12614.  
  12615. Rexx Conditional Logic 
  12616.  
  12617. You can get a (slighty out of date) regina rexx manual from 
  12618. http://sites.netscape.net/ssatguru, this has HTML and compiled Windows Help 
  12619. formats for download. 
  12620.  
  12621. The #if command allows you to evaluate any rexx conditional expression to 
  12622. determine whether it's true or not. 
  12623.  
  12624. The following tests operators are concidered to be "non-strict" (leading and 
  12625. trailing blanks are ignored as are leading zeros on numbers): 
  12626.  
  12627.          = 
  12628.           Tests if values are equal. 
  12629.  
  12630.          <> 
  12631.           Tests if values are not equal. 
  12632.  
  12633.          < 
  12634.           Tests if left value is less than the right value (can be text or 
  12635.           number). 
  12636.  
  12637.          <= 
  12638.           Tests if left value is less than or equal to the right value (can be 
  12639.           text or number). 
  12640.  
  12641.          > 
  12642.           Tests if left value is greater than the right value (can be text or 
  12643.           number). 
  12644.  
  12645.          >= 
  12646.           Tests if left value is greater than or equal to the right value (can 
  12647.           be text or number). 
  12648.  
  12649.  The following tests operators are concidered to be "strict": 
  12650.  
  12651.          == 
  12652.           Tests if values are equal. 
  12653.  
  12654.          \== 
  12655.           Tests if values are not equal. 
  12656.  
  12657.          << 
  12658.           Tests if left value is less than the right value (can be text or 
  12659.           number). 
  12660.  
  12661.          <<= 
  12662.           Tests if left value is less than or equal to the right value (can be 
  12663.           text or number). 
  12664.  
  12665.          >> 
  12666.           Tests if left value is greater than the right value (can be text or 
  12667.           number). 
  12668.  
  12669.          >>= 
  12670.           Tests if left value is greater than or equal to the right value (can 
  12671.           be text or number). 
  12672.  
  12673.  The following logical operators are also useful: 
  12674.  
  12675.          & - AND (both must be true) 
  12676.  
  12677.          | - OR (either can be true) 
  12678.  
  12679.  Some examples follow: 
  12680.  
  12681.       #if  lines(<$LanguageFile>) = 0
  12682.       #if  Defined('Var1') = 'Y' | Defined('Var2') = 'Y'
  12683.       #if <$TmpHH> < 12
  12684.       #if translate(GetEnv("PRJSRCDIR")) = "E:\DB\PROJECTS\HOMEPAGE"
  12685.  
  12686.  
  12687. ΓòÉΓòÉΓòÉ 11.4. Rexx Looping ΓòÉΓòÉΓòÉ
  12688.  
  12689. Rexx Looping 
  12690.  
  12691. You can get a (slighty out of date) regina rexx manual from 
  12692. http://sites.netscape.net/ssatguru, this has HTML and compiled Windows Help 
  12693. formats for download. 
  12694.  
  12695. Loops are one of the complex areas of rexx and most things you will wish to do 
  12696. with PPWIZARD will either not require them or the simpler PPWIZARD loops will 
  12697. be enough. 
  12698.  
  12699. The syntax of rexx loops is as follows: 
  12700.  
  12701.     DO [ symbol=start   [TO  finish]  ]     [WHILE expression_w]
  12702.        [                [BY  step  ]  ]
  12703.        [                [FOR count ]  ]     [UNTIL expression_u]
  12704.  
  12705.        [ expression_c                 ]     [FOREVER           ]
  12706.  
  12707. Examples follow (these would need to be integrated with PPWIZARD using the 
  12708. #evaluate command : 
  12709.  
  12710.     do 10
  12711.        /* Do something 10 times */
  12712.     end
  12713.  
  12714.     do _Count = 1 to 100
  12715.        /* Do something 100 times (Count given values 1,2,3 to 100) */
  12716.     end
  12717.  
  12718.     do _Multiple = 0 to 20 by 2.3
  12719.        /* Loop with _Multiple = all multiples of 2.3 not more than 20 */
  12720.     end
  12721.  
  12722.     do _Multiple = 0 for 6 by 5.7
  12723.        /* Loop with _Multiple = the first six multiples of 5.7 */
  12724.     end
  12725.  
  12726.     _Finished = 'N'
  12727.     do while _Finished = 'N'
  12728.        /* Set _Finished variable to 'Y' to exit loop */
  12729.     end;
  12730.  
  12731.     do until _Finished = 'Y' & _Fred <> 0
  12732.        /* Set _Finished variable to 'Y' to exit loop (_Fred must also be non zero) */
  12733.     end;
  12734.  
  12735.     do 3 until _Answer = "YES"
  12736.        /* Exits loop after 3 times or if _Answer becomes 'YES' */
  12737.     end
  12738.  
  12739.     do _Count = 1 to 10 until Fred == ""
  12740.        /* Loop 1 to 10 unless condition met */
  12741.     end
  12742.  
  12743.     do _Count = 1 to 10
  12744.        /* Looping 1 to 10 */
  12745.  
  12746.        /* Want to restart loop (don't execute following loop code)? */
  12747.        if _Restart = 'Y' then
  12748.           iterate;         /* Go back to start of loop (_Count incremented) */
  12749.  
  12750.        /* Want to exit loop early? */
  12751.        if _Flag = 'Y' | _State = 'R' then
  12752.           break;           /* Exit loop */
  12753.     end
  12754.  
  12755.  
  12756. ΓòÉΓòÉΓòÉ 11.5. Rexx Parsing ΓòÉΓòÉΓòÉ
  12757.  
  12758. Rexx Parsing 
  12759.  
  12760. You can get a (slighty out of date) regina rexx manual from 
  12761. http://sites.netscape.net/ssatguru, this has HTML and compiled Windows Help 
  12762. formats for download. 
  12763.  
  12764. Parsing is another of rexx's complex areas, a subset of its syntax is 
  12765. summarised here: 
  12766.  
  12767.     PARSE [UPPER] LINEIN [template]
  12768.     PARSE [UPPER] NUMERIC template
  12769.     PARSE [UPPER] VAR symbol template
  12770.     PARSE [UPPER] VALUE expression WITH template
  12771.  
  12772.         template        -> [firstPosition] assignments [assignments]
  12773.         assignments     -> [nextPosition] varlist [stopPosition]
  12774.         varlist         -> varname ' ' [varlist]
  12775.         varname         ->   "non-constant symbol"
  12776.                            | '.'
  12777.         firstPosition   -> position
  12778.         nextPosition    -> position [nextPosition]
  12779.         stopPosition    -> position
  12780.         position        ->   searchPosition
  12781.                            | absPosition
  12782.                            | relPosition
  12783.                            | '(' "expression" ')'
  12784.         searchPosition  -> "string constant"
  12785.         absPosition     ->   "integer"
  12786.                            | '=' numexpr
  12787.         relPosition     ->   '+' numexpr
  12788.                            | '-' numexpr
  12789.         numexpr         ->   "integer"
  12790.                            | '(' "integer expression" ')'
  12791.  
  12792. This is an example of extracting each directory (one at a time) from the path 
  12793. (located in DOS or OS/2 environment): 
  12794.  
  12795.     ;--- Get "PATH" from environment
  12796.     #evaluate ^^  ^_Path = GetEnv('PATH')^
  12797.  
  12798.     ;--- Start list -----------------
  12799.     <P>The path is:
  12800.     <OL>
  12801.  
  12802.     ;--- List Components ------------
  12803.     #{
  12804.        ;--- Get next directory name -
  12805.        #evaluate ^^ ^parse var _Path _ThisBit ';' _Path^
  12806.  
  12807.        ;--- Exit if at end of path --
  12808.        #if  _ThisBit = '' & _Path=''
  12809.             #break
  12810.        #endif
  12811.  
  12812.        ;--- Output directory name ---
  12813.        <LI><??_ThisBit>
  12814.     #}
  12815.  
  12816.     ;--- End list -------------------
  12817.     </OL>
  12818.  
  12819.  
  12820. ΓòÉΓòÉΓòÉ 11.6. Standard Rexx Routines ΓòÉΓòÉΓòÉ
  12821.  
  12822. SUMMARY OF REXX "BUILT IN" ROUTINES 
  12823.  
  12824. You can get a (slighty out of date) regina rexx manual from 
  12825. http://sites.netscape.net/ssatguru, this has HTML and compiled Windows Help 
  12826. formats for download. 
  12827.  
  12828. Note that some of the routines listed below may not be available in the rexx 
  12829. version you are using (neither does it list all functions): 
  12830.  
  12831.     ABBREV(information,info[,length])  - check for valid abbreviations
  12832.     ABS(number)                        - return the absolute value
  12833.     B2D(binary)
  12834.     B2X(binary)
  12835.     D2B(decimal)
  12836.     C2X(string)
  12837.     C2D(string[,n])
  12838.     D2C(decimal[,n])                   - convert between data formats
  12839.     D2X(decimal[,n])
  12840.     X2B(hex)
  12841.     X2C(hex)
  12842.     X2D(hex)
  12843.     CENTER(s,n[,pad])                  - centre a string in a field
  12844.     CENTRE(s,n[,pad])
  12845.     COMPARE(s1,s2[,pad])               - compare two strings
  12846.  
  12847.     COPIES(s,n)                        - replicate a string
  12848.     DATATYPE(string[,type])            - test datatype. Type can be:
  12849.                                        A (alphanumeric) B (bits) L (lowercase)
  12850.                                        M (mixed case) N (number) S (symbol chars)
  12851.                                        U (upper case) W (whole number) X (hex)
  12852.  
  12853.     DATE([format])                     - get date. Format can be:
  12854.                                        B (base date - days since 1/1/1 AD)
  12855.                                        C (days in century) D (days in year)
  12856.                                        E (European) J (Julian) M (month name)
  12857.                                        N (normal: dd Mon yyyy) O (ordered)
  12858.                                        S (sorted) U (USA) W (day of week)
  12859.  
  12860.  
  12861.     FORMAT(number [,[before] [,[after] [,[expp] [,expt]]]] )
  12862.                                        - format a number as specified
  12863.     FUZZ()                             - NUMERIC FUZZ setting
  12864.     INSERT(new,target[,[n][,[length][,pad]]])  - insert new string into target
  12865.     JUSTIFY(s,n[,pad])                 - justify text to given width
  12866.     LASTPOS(needle,haystack[,start])   - find last occurrence of a string
  12867.     LEFT(string,num[,pad])             - return an initial substring
  12868.     LENGTH(string)                     - find the length of a string
  12869.     MAX(number[,number...])            - find the maximum of a set
  12870.     MIN(number[,number...])            - find the minimum of a set
  12871.     OVERLAY(new,target[,[n][,[length][,pad]]])  - overlay new string on to target
  12872.     POS(needle,haystack[,start])       - find the first occurance of a string
  12873.     RANDOM([min][,[max][,seed]])       - return a random number
  12874.     REVERSE(string)                    - find the reverse of a string
  12875.     RIGHT(string,num[,pad])            - return a final substring
  12876.     SPACE(s[,[n][,pad]])               - evenly space words in a sentence
  12877.     STRIP(string[,[opt][,char]])       - remove leading/trailing spaces
  12878.     SUBSTR(string,n[,length[,pad]])    - return a substring
  12879.     SUBWORD(string,n[,k])              - return a substring of words
  12880.     SYMBOL(name)                       - test to see if a symbol is defined
  12881.     TIME([format])                     - get the time. Format can be:
  12882.                                        C (civil time) N (normal) L (long)
  12883.                                        H (hours since midnight)
  12884.                                        M (minutes since midnight)
  12885.                                        S (seconds since midnight) E (elapsed time)
  12886.                                        R (elapsed time then reset)
  12887.  
  12888.     TRANSLATE(string[,[tableo][,[tablei][,pad]]])
  12889.                                        - translate characters using given tables
  12890.     TRUNC(number[,n])                  - truncate floating point number
  12891.     VALUE(s[,[newvalue][,selector]])   - get or set value of a symbol
  12892.  
  12893.     VERIFY(string,reference[,[option][,start]])
  12894.                                        - verify string for valid characters
  12895.     WORD(string,n)                     - return a word from a string
  12896.     WORDINDEX(string,n)                - return the position of a word in a string
  12897.     WORDLENGTH(string,n)               - return the length of a word in a string
  12898.     WORDPOS(phrase,string[,start])     - find a phrase in a string
  12899.     WORDS(string)                      - return the number of words in a string
  12900.     XRANGE([a[,b]])                    - return a range of characters
  12901.  
  12902. Some rexx interpreters support functions which are not ANSI standard, others 
  12903. won't support all standard ANSI routines.  If you care about operating system 
  12904. portability you will be careful about which routines you use. PPWIZARD has its 
  12905. own routines which may be be used, these should be used in preference to 
  12906. "standard" rexx ones as they will work in all operating systems that PPWIZARD 
  12907. supports. 
  12908.  
  12909.  
  12910. ΓòÉΓòÉΓòÉ 11.6.1. translate() ΓòÉΓòÉΓòÉ
  12911.  
  12912. translate() 
  12913.  
  12914. This is a standard Standard Rexx Routines, there are many more (only a small 
  12915. number are documented in this manual). Only a summary is described here, for 
  12916. more complete and accurate information about this and other rexx routines you 
  12917. will need to obtain some rexx documentation. 
  12918.  
  12919. This routine is passed a string and a translated result is returned. The string 
  12920. is translated a character at a time, and if only a single parameter was passed 
  12921. converts the string to upper case. The ToLowerCase() call can be used to 
  12922. convert a string to lower case. 
  12923.  
  12924. This function performs translations in english only, for other languages see 
  12925. the "ToLowerCase()" example. 
  12926.  
  12927. To perform other sorts of translations supply an "output" followed by and 
  12928. "input" character string. Any character in the "input" string is converted to 
  12929. the matching character in the output string. Note that the ppwizard 
  12930. BulkChar2String() routine can convert single characters to any length strings. 
  12931.  
  12932. EXAMPLES 
  12933.  
  12934.     ;--- Convert to upper case ---
  12935.     InUpper = translate("asdf")
  12936.  
  12937.     ;--- Convert "\" to "/" ------
  12938.     NewStr = translate(OldStr, "/", "\")
  12939.  
  12940.  
  12941. ΓòÉΓòÉΓòÉ 11.7. Rexx Fragments - Kick Start ΓòÉΓòÉΓòÉ
  12942.  
  12943. Rexx Fragments - Kick Start 
  12944.  
  12945. You can get a (slighty out of date) regina rexx manual from 
  12946. http://sites.netscape.net/ssatguru, this has HTML and compiled Windows Help 
  12947. formats for download. 
  12948.  
  12949. This section will show you some small portions of rexx code (not complete) 
  12950. which can be used to quickly get you up to speed in rexx. 
  12951.  
  12952. Note that the examples below are isolated fragments, you could not cut and 
  12953. paste them and run them though PPWIZARD as they are... 
  12954.  
  12955.            ;--- Assign a value to a variable ---
  12956.            SomeVariable = 'the cat sat on the mat';
  12957.  
  12958.            ;--- Convert string to upper case ---
  12959.            UpperCaseString = translate(SomeVariable);
  12960.  
  12961.            ;--- Get first 2 characters of string ---
  12962.            Left2 = left('abcd', 2);
  12963.  
  12964.            ;--- Get last 2 characters of string ---
  12965.            Right2 = right('abcd', 2);
  12966.  
  12967.            ;--- Get middle 2 characters of string (first char at posn 1) ---
  12968.            Middle2 = substr('abcd', 2, 2);      ;;Last '2' is length
  12969.  
  12970.            ;--- See if first char of string is 'A' (either case) ---
  12971.            if  translate(left(UpperCaseString, 1)) = 'A' then
  12972.            do;
  12973.                ;--- Any number of rexx statements ---
  12974.            end;
  12975.  
  12976.            ;--- Does "SomeVariable" contain the characters "Fred"? ---
  12977.            if  pos('Fred', SomeVariable) <> 0 then     ;Does var
  12978.                SingleStatement;
  12979.            else
  12980.            do
  12981.                ;--- Any number of rexx statements ---
  12982.            end;
  12983.  
  12984.            ;--- Is the second word of "SomeVariable" the word "the"? ---
  12985.            if  word(SomeVariable, 2) = 'the' then
  12986.                SingleStatement;
  12987.  
  12988.  
  12989. ΓòÉΓòÉΓòÉ 11.8. Inbuilt PPWIZARD Functions ΓòÉΓòÉΓòÉ
  12990.  
  12991. LIST OF INBUILT PPWIZARD FUNCTIONS 
  12992.  
  12993. Any of these PPWIZARD routines may be used by your rexx code: 
  12994.  
  12995.          Add2() 
  12996.          AddCommasToDecimalNumber() 
  12997.          AddInputFileToDependancyList() 
  12998.          AddOutputFileToDependancyList() 
  12999.          AddTempFileToDependancyList() 
  13000.          AddressCmd() 
  13001.          ArrayRemoveDup() 
  13002.          ArrayReverse() 
  13003.          ArraySort() 
  13004.          ArraySplit() 
  13005.          ArrayTranslate() 
  13006.          AsIs() 
  13007.          AsIsPrepare() 
  13008.          AutoTag() 
  13009.          Bd2Date() 
  13010.          BaseDate() 
  13011.          BreakAt() 
  13012.          BulkChar2String() 
  13013.          BulkChangePrepare() 
  13014.          Chars() 
  13015.          CompareReplaceFixed() 
  13016.          DataGet() 
  13017.          DataSave() 
  13018.          Debug() 
  13019.          DebugIndent() 
  13020.          Defined() 
  13021.          DieIfIoErrorOccurred() 
  13022.          EnsureFileHasCorrectCase() 
  13023.          Error() 
  13024.          ErrorSql() 
  13025.          ExpandXCodes() 
  13026.          FindFile() 
  13027.          FindFileInPath() 
  13028.          GenerateFileName() 
  13029.          GetAmPmTime() 
  13030.          GetAmPmTimeFromHhMmSs() 
  13031.          GetDependancyInfo() 
  13032.          GetEnv() 
  13033.          GetFileLineBeingProcessed() 
  13034.          GetFileTimeStamp() 
  13035.          GetId() 
  13036.          GetIdPrepare() 
  13037.          GetImageHeightWidth() 
  13038.          GetInputFileNameAndLine() 
  13039.          GetLineBeingProcessed() 
  13040.          GetQuotedRest() 
  13041.          GetQuotedText() 
  13042.          Info() 
  13043.          InputComponentLevel() 
  13044.          InputComponentLineLevel() 
  13045.          IsDebugOn() 
  13046.          LoadRexxSql() 
  13047.          MacroGet() 
  13048.          MacroSet() 
  13049.          MakeWebLinks() 
  13050.          MustDeleteFile() 
  13051.          OptionGet() 
  13052.          OptionSet() 
  13053.          PadString() 
  13054.          ProcessNext() 
  13055.          QueryExists() 
  13056.          QuoteIt() 
  13057.          RandomString() 
  13058.          ReplaceCurlyHexCodes() 
  13059.          ReplaceMacros() 
  13060.          ReplaceString() 
  13061.          ReplaceStringCI() 
  13062.          RexxVarDefined() 
  13063.          Say() 
  13064.          SetEnv() 
  13065.          SetId() 
  13066.          SetXCode() 
  13067.          SStrip() 
  13068.          StackPush() 
  13069.          StackPop() 
  13070.          Summary() 
  13071.          Tabs2Spaces() 
  13072.          TimeStamp() 
  13073.          ToLowerCase() 
  13074.          UpdateCrc32() 
  13075.          UrlDecode() 
  13076.          UrlEncode() 
  13077.          Warning() 
  13078.          WriteLineToTmpImportFile() 
  13079.          RexGetTmpFileName() 
  13080.          _filespec() 
  13081.          _SysFileDelete() 
  13082.          _SysFileTree() 
  13083.  
  13084.  SOME NOTES 
  13085.  
  13086.  On PPWIZARD's download page there are many external add-ons which are 
  13087.  frequently more powerful than anything I might wish inbuilt into PPWIZARD 
  13088.  (such as the sort download) so do not forget to check there if you are after 
  13089.  something specific. I do not like to add to the above list of internal 
  13090.  functions and will only do so when there is a good reason. 
  13091.  
  13092.  Note that I do not always document return codes in the functions listed above 
  13093.  if I do not believe that they will be useful to you. 
  13094.  
  13095.  Rexx has two different ways of calling a function depending on whether or not 
  13096.  you wish to process any return code. 
  13097.  
  13098.  The following demonstrates the syntax that should be used when you need the 
  13099.  return code: 
  13100.  
  13101.          ;--- Put return code into the rexx variable "FuncRc" ---
  13102.          FunctRc = RexxFunction(parm1, parm2)     ;;Pass 2 parameters
  13103.  
  13104.          ;--- Display value -------------------------------------
  13105.          call Say 'RC = ' || RexxFunction(parm1)  ;;Pass 1 parameter
  13106.  
  13107.  The following demonstrates the syntax that should be used when you don't need 
  13108.  the return code: 
  13109.  
  13110.          ;--- Place return code into an unused variable name ---
  13111.          Dummy = RexxFunction(parm1, parm2)       ;;Not valid if function does not return a return code
  13112.  
  13113.          ;--- Alternate call syntax ----------------------------
  13114.          call RexxFunction parm1, parm2           ;;Always valid
  13115.  
  13116.  The following code does not correctly call AddTempFileToDependancyList(): 
  13117.  
  13118.       #evaluate '' ^AddTempFileToDependancyList('NUL')^
  13119.  
  13120.  As a result of the incorrect call syntax, rexx passed the return code to the 
  13121.  operating system for execution. The operating system then displayed (in OS/2): 
  13122.  
  13123.       [F:\HTMLTEST]Y
  13124.       SYS1041: The name Y is not recognized as an
  13125.       internal or external command, operable program or batch file.
  13126.  
  13127.  Note that the results may not always be so obvious, for example in OS/2 it may 
  13128.  complain about running out of memory or things may simply run slower. 
  13129.  
  13130.  
  13131. ΓòÉΓòÉΓòÉ 11.8.1. Add2() ΓòÉΓòÉΓòÉ
  13132.  
  13133. Add2() 
  13134.  
  13135. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13136. extensions) can be used with any operating system supported by PPWIZARD. 
  13137.  
  13138. This routine simplifies the addition of data into arrays and makes the code 
  13139. easier to understand. 
  13140.  
  13141. Each time this routine is called the supplied data is added onto the end of the 
  13142. array (stem). 
  13143.  
  13144. If the array did not exist it is created then updated. 
  13145.  
  13146. The function takes 1 or 2 parameters as follows: 
  13147.  
  13148.        1. The string to be added. 
  13149.  
  13150.        2. This parameter indicates the array (stem) to be updated. You should 
  13151.           not pass a trailing dot. If you don't pass a value the last value 
  13152.           used is used for the call. 
  13153.  
  13154.  The routine returns the number of items in the array. As per normal rexx 
  13155.  convention, this value is also saved into the ".0" item. 
  13156.  
  13157.  
  13158. ΓòÉΓòÉΓòÉ 11.8.2. AddCommasToDecimalNumber() ΓòÉΓòÉΓòÉ
  13159.  
  13160. AddCommasToDecimalNumber() 
  13161.  
  13162. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13163. extensions) can be used with any operating system supported by PPWIZARD. 
  13164.  
  13165. This function takes a single parameter (a decimal integer) and adds commas as 
  13166. required. 
  13167.  
  13168.  
  13169. ΓòÉΓòÉΓòÉ 11.8.3. AddInputFileToDependancyList() ΓòÉΓòÉΓòÉ
  13170.  
  13171. AddInputFileToDependancyList() 
  13172.  
  13173. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13174. extensions) can be used with any operating system supported by PPWIZARD. 
  13175.  
  13176. This function allows you to specify an input dependancy. The function should be 
  13177. called before the file is read for the most accurate result in all 
  13178. circumstances. 
  13179.  
  13180. This routine is an alternative to the "#DependsOn" command. 
  13181.  
  13182.  
  13183. ΓòÉΓòÉΓòÉ 11.8.4. AddOutputFileToDependancyList() ΓòÉΓòÉΓòÉ
  13184.  
  13185. AddOutputFileToDependancyList() 
  13186.  
  13187. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13188. extensions) can be used with any operating system supported by PPWIZARD. 
  13189.  
  13190. This function allows you to specify an output dependancy. The function should 
  13191. be called after you have completed all updating of the file. 
  13192.  
  13193. This routine is an alternative to the "#DependsOn" command. 
  13194.  
  13195.  
  13196. ΓòÉΓòÉΓòÉ 11.8.5. AddTempFileToDependancyList() ΓòÉΓòÉΓòÉ
  13197.  
  13198. AddTempFileToDependancyList() 
  13199.  
  13200. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13201. extensions) can be used with any operating system supported by PPWIZARD. 
  13202.  
  13203. This function allows you to specify that a file is a temporary one that should 
  13204. be ignored as far as dependancy checking is concerned. 
  13205.  
  13206. The function must be used before the file is marked an an input or output 
  13207. dependancy. 
  13208.  
  13209. This routine is an alternative to the "#DependsOn" command. 
  13210.  
  13211.  
  13212. ΓòÉΓòÉΓòÉ 11.8.6. AddressCmd() ΓòÉΓòÉΓòÉ
  13213.  
  13214. AddressCmd() 
  13215.  
  13216. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13217. extensions) can be used with any operating system supported by PPWIZARD. 
  13218.  
  13219. This routine will pass the command that you specify (as the first argument) to 
  13220. the operating system's command processor. 
  13221.  
  13222. This routine allows you to execute any native operating system commands as well 
  13223. as perl, pascal, rexx or in fact code written using any language. If the 
  13224. commands output is required the output can be redirected and you can tell 
  13225. ppwizard to #include it or you can load it yourself to parse out selected 
  13226. information. 
  13227.  
  13228. The command will by default be logged when debug is on. This is a major reason 
  13229. why you should use this call (rather than using rexx's native methods). 
  13230.  
  13231. If your command produces some files as output or you create some by redirection 
  13232. you can specify the names of the files as parameter 2 onwards and these will be 
  13233. dumped when debug is on (the only reason for supplying more than the command 
  13234. line as the first parameter). 
  13235.  
  13236. Under OS/2 if the command to be executed is a rexx batch file you should 
  13237. preceed the command with "CMD.EXE /c" or the command will fail. If you don't 
  13238. know what the command is you should preceed all commands with that string to 
  13239. play safe. 
  13240.  
  13241. Stupid Example 
  13242.  
  13243. This example shows a directory commands output going into one file and any 
  13244. error messages into another. If debug is on the contents of both files as well 
  13245. as the return code will be dumped. 
  13246.  
  13247.     #evaluate "" ^call AddressCmd "dir /od >dirlist.out 2>error.out", "dirlist.out", "error.out"^
  13248.  
  13249.  
  13250. ΓòÉΓòÉΓòÉ 11.8.7. ArrayRemoveDup() ΓòÉΓòÉΓòÉ
  13251.  
  13252. ArrayRemoveDup() 
  13253.  
  13254. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13255. extensions) can be used with any operating system supported by PPWIZARD. 
  13256.  
  13257. This routine loops through an array and removes repeating entries. You can 
  13258. define how many entries in a row to allow. 
  13259.  
  13260. The array is never searched so if you wish to never have more that one item 
  13261. anywhere in the array having the same value then you should sort the array 
  13262. first. 
  13263.  
  13264. The compare is "strict", that is leading/trailing whitespace etc is 
  13265. significant. Depending on your needs you might wish to case translate or strip 
  13266. whitespace from entries (possibly using ArrayTranslate()). 
  13267.  
  13268. This function takes one or more parameters as follows: 
  13269.  
  13270.        1. The name of an array to be processed (without dot). 
  13271.  
  13272.        2. The optional number of repeating entries allowed (default is 1). 
  13273.  
  13274.  The number of items in the array after removing any duplicates is returned. 
  13275.  
  13276.  
  13277. ΓòÉΓòÉΓòÉ 11.8.8. ArrayReverse() ΓòÉΓòÉΓòÉ
  13278.  
  13279. ArrayReverse() 
  13280.  
  13281. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13282. extensions) can be used with any operating system supported by PPWIZARD. 
  13283.  
  13284. This function is used to reverse the order of elements in an array. The "array" 
  13285. has numeric indexes with the ".0" element holding the number of elements. 
  13286.  
  13287. The function takes a single parameter which is the name of the array (without 
  13288. dot). 
  13289.  
  13290. The routine returns the number of items in the array. 
  13291.  
  13292. Silly Example 
  13293.  
  13294.     ;--- Set up the array -----------------------
  13295.     #evaluate ''               \
  13296.               ^                \
  13297.                 A.1 = "5345";  \
  13298.                 A.2 = "4123";  \
  13299.                 A.3 = "61743"; \
  13300.                 A.4 = "1678";  \
  13301.                 A.0 = 4;       \
  13302.               ^
  13303.  
  13304.     ;--- Sort array & Reverse order & display ---
  13305.     #evaluate '' ^call ArraySort "A"^
  13306.     #evaluate '' ^call ArrayReverse  "A"^
  13307.     #evaluate '' ^do I = 1 to A.0; say a.i; end;^
  13308.  
  13309.  
  13310. ΓòÉΓòÉΓòÉ 11.8.9. ArraySort() ΓòÉΓòÉΓòÉ
  13311.  
  13312. ArraySort() 
  13313.  
  13314. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13315. extensions) can be used with any operating system supported by PPWIZARD. 
  13316.  
  13317. This function is used to sort a rexx array. The "array" has numeric indexes 
  13318. with the ".0" element holding the number of elements. The array can hold 
  13319. numbers or strings. 
  13320.  
  13321. The sort is always ascending. You can use the ArrayReverse() routine if 
  13322. required. 
  13323.  
  13324. The function takes 1 or more parameters as follows: 
  13325.  
  13326.        1. The name of the array (don't include the dot). 
  13327.  
  13328.        2. If you wish to sort only over specific columns then the starting 
  13329.           column number (first column is 1). 
  13330.  
  13331.        3. If the optional starting column was specified then this specifies the 
  13332.           ending column. If not specified then the rest of the string is used. 
  13333.  
  13334.        4. This is an optional parameter. Do you want a strict compare? If you 
  13335.           do then pass 'Y'. A strict compare does not ignore leading and 
  13336.           trailing whitespace, however it won't correctly sort numbers. 
  13337.  
  13338.  The routine returns the number of items in the array. 
  13339.  
  13340.  If you are sorting a very large array with a fixed known name then you might 
  13341.  wish to have a look at the faster and more powerful PPWSORT.H header file. 
  13342.  
  13343.  Silly Example 
  13344.  
  13345.       ;--- Set up the array ------------------------
  13346.       #evaluate ''               \
  13347.                 ^                \
  13348.                   A.1 = "ASDFG"; \
  13349.                   A.2 = "4123";  \
  13350.                   A.3 = "61743"; \
  13351.                   A.4 = "1678";  \
  13352.                   A.0 = 4;       \
  13353.                 ^
  13354.  
  13355.       ;--- Sort array & display --------------------
  13356.       #evaluate '' ^call ArraySort "A"^
  13357.       #evaluate '' ^do I = 1 to A.0; say '"'a.i'"'; end; say ''^
  13358.  
  13359.       ;--- Sort array (start column 3) & display ---
  13360.       #evaluate '' ^call ArraySort "A", 3^
  13361.       #evaluate '' ^do I = 1 to A.0; say '"'a.i'"'; end;
  13362.  
  13363.  
  13364. ΓòÉΓòÉΓòÉ 11.8.10. ArraySplit() ΓòÉΓòÉΓòÉ
  13365.  
  13366. ArraySplit() 
  13367.  
  13368. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13369. extensions) can be used with any operating system supported by PPWIZARD. 
  13370.  
  13371. This routine splits a string value based on a delimiter into multiple tokens 
  13372. (stored in an array). 
  13373.  
  13374. This function takes two or more parameters as follows: 
  13375.  
  13376.        1. The name of the array to create (don't include the dot). 
  13377.  
  13378.        2. The value to be processed (split). 
  13379.  
  13380.        3. An optional delimiter (a single space is the default). A delimiter 
  13381.           can be any number of characters long. 
  13382.  
  13383.        4. This optional parameter indicates what type of space translation 
  13384.           should occur (if not supplied "B" is used). This value should be "K" 
  13385.           to leave whitespace alone! It can be be "BM" to remove all leading 
  13386.           and trailing whitespace as well as removing any duplicated whitespace 
  13387.           within the string. You can also supply "L", "T", or "B" to remove 
  13388.           leading, trailing or both types of whitespace. 
  13389.  
  13390.        5. This optional parameter allows you to specify that you wish to keep 
  13391.           blank tokens (or those only containing whitespace). Normally blank 
  13392.           tokens are dropped, pass 'Y' to prevent this. 
  13393.  
  13394.  The number of items in the array is returned. 
  13395.  
  13396.  
  13397. ΓòÉΓòÉΓòÉ 11.8.11. ArrayTranslate() ΓòÉΓòÉΓòÉ
  13398.  
  13399. ArrayTranslate() 
  13400.  
  13401. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13402. extensions) can be used with any operating system supported by PPWIZARD. 
  13403.  
  13404. This routine loops through an array and performs translations you define. 
  13405.  
  13406. This function takes one or more parameters as follows: 
  13407.  
  13408.        1. The name of an array to be processed (without dot). 
  13409.  
  13410.        2. This optional parameter indicates what type of space translation 
  13411.           should occur (if not supplied "B" is used). This value should be "K" 
  13412.           to leave whitespace alone! It can be be "BM" to remove all leading 
  13413.           and trailing whitespace as well as removing any duplicated whitespace 
  13414.           within the string. You can also supply "L", "T", or "B" to remove 
  13415.           leading, trailing or both types of whitespace. 
  13416.  
  13417.        3. This optional parameter allows you to specify that you require case 
  13418.           translation so that all entries are either in lower or upper case. If 
  13419.           this parameter is blank no translation is performed, if 'L' then 
  13420.           lowercase translation and 'U' means upper case translation. 
  13421.  
  13422.  The number of items in the array is returned. 
  13423.  
  13424.  
  13425. ΓòÉΓòÉΓòÉ 11.8.12. AsIs() ΓòÉΓòÉΓòÉ
  13426.  
  13427. AsIs() 
  13428.  
  13429. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13430. extensions) can be used with any operating system supported by PPWIZARD. 
  13431.  
  13432. This function takes a single parameter and will return the string after all "as 
  13433. is" conversion has taken place (see the #AsIs command). 
  13434.  
  13435. Note that this replacement occurs whether or not "as is" mode is currently on, 
  13436. the AsIsPrepare() function can be called to set up exactly what you wish 
  13437. modified. 
  13438.  
  13439. Note that you may not wish to use this routine because of interference you 
  13440. might cause with the use of the #AsIs command, in this case you might find 
  13441. BulkChar2String() useful. 
  13442.  
  13443. This routine is useful where you are reading in data directly rather than using 
  13444. #include or #import commands.  You could be using the rexx linein() routine or 
  13445. accessing SQL data. 
  13446.  
  13447. Stupid Example 
  13448.  
  13449.     ;--- Setup INTERNATIONAL symbols (2 only for this demo) ---
  13450.     #AutoTagState +
  13451.     #AutoTag      '╨ö'    'ä'
  13452.     #AutoTag      '╨Ö'    'ë'    ;;Only 2 for this example
  13453.     #AsIs         SETUP  INTERNATIONAL_SYMBOLS
  13454.     #AutoTagState -
  13455.  
  13456.     ;--- Prepare ASIS Tagging ----------------------------
  13457.     #evaluate "" ^AsIsPrepare("INTERNATIONAL_SYMBOLS")^
  13458.  
  13459.     ;--- Assign to some variables ------------------------
  13460.     #evaluate "NoChanges"   ^"╨Ö ╨Ö ╨Ö"^
  13461.     #evaluate "Changesmade" ^AsIs("╨Ö ╨Ö ╨Ö")^
  13462.  
  13463.     ;--- Generate couple of lines ------------------------
  13464.     BEFORE: <$NoChanges>
  13465.     AFTER : <$Changesmade>
  13466.  
  13467.  
  13468. ΓòÉΓòÉΓòÉ 11.8.13. AsIsPrepare() ΓòÉΓòÉΓòÉ
  13469.  
  13470. AsIsPrepare() 
  13471.  
  13472. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13473. extensions) can be used with any operating system supported by PPWIZARD. 
  13474.  
  13475. This function takes a single parameter made up zero or more "names" previous 
  13476. setup with the "SETUP" command of #AsIs. 
  13477.  
  13478. It basically identifies the tagging you wish to have take place when the AsIs() 
  13479. routine is called. 
  13480.  
  13481.  
  13482. ΓòÉΓòÉΓòÉ 11.8.14. AutoTag() ΓòÉΓòÉΓòÉ
  13483.  
  13484. AutoTag() 
  13485.  
  13486. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13487. extensions) can be used with any operating system supported by PPWIZARD. 
  13488.  
  13489. This function takes a single parameter and will return the string after all 
  13490. currently defined #AutoTag replacements have been make. 
  13491.  
  13492. Note that this replacement occurs whether or not "auto tag" mode is currently 
  13493. on. 
  13494.  
  13495. This routine is useful where you are reading in data directly rather than using 
  13496. #include or #import commands.  You could be using the rexx linein() routine or 
  13497. accessing SQL data. 
  13498.  
  13499. Stupid Example 
  13500.  
  13501.     #AutoTagState +
  13502.     #AutoTag      'FROM'    'TO'
  13503.     #evaluate     'Result'  AutoTag('from / FROM');
  13504.     <$Result>                              ;;Output saved result.
  13505.     #AutoTagState -
  13506.  
  13507.  
  13508. ΓòÉΓòÉΓòÉ 11.8.15. Bd2Date() ΓòÉΓòÉΓòÉ
  13509.  
  13510. Bd2Date() 
  13511.  
  13512. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13513. extensions) can be used with any operating system supported by PPWIZARD. 
  13514.  
  13515. This function takes the passed BASEDATE and returns a formatted date. 
  13516.  
  13517. The parameters are: 
  13518.  
  13519.        1. A basedate. 
  13520.  
  13521.  The value is returned in the format "YYYYMMDD". This may need further 
  13522.  manipulation to get the format you require. 
  13523.  
  13524.  
  13525. ΓòÉΓòÉΓòÉ 11.8.16. BaseDate() ΓòÉΓòÉΓòÉ
  13526.  
  13527. BaseDate() 
  13528.  
  13529. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13530. extensions) can be used with any operating system supported by PPWIZARD. 
  13531.  
  13532. This function can be called to work out a basedate (julian day) given a date. 
  13533. The integer will be negative if an error occurred. You can tell how many days 
  13534. apart 2 dates are by subtraction of one from the other. The basedate is the 
  13535. number of days since 1 January 0001. 
  13536.  
  13537. If the returned basedate integer is divided by 7, the remainder will tell you 
  13538. what day of the week it is (where 0=Monday, 6=Sunday). 
  13539.  
  13540. The number returned for a date is compatible with rexx's "date('BaseDate')" 
  13541. call. 
  13542.  
  13543. You can convert a basedate back into a displayable date with BD2DATE(). 
  13544.  
  13545. You can use GetFileTimeStamp() to obtain the date/time a file was modified and 
  13546. calculate a basedate from this if you wish to calculate the age of a file. 
  13547.  
  13548. INPUT DATE 
  13549.  
  13550. The routine takes a single parameter (the date) with the year, month and day of 
  13551. month being supplied in that order.  The year should either be supplied as 4 
  13552. digits or will pivot at 1980. 
  13553.  
  13554. It will take the input in these formats: 
  13555.  
  13556.        1. YYYYMMDD - any following characters ignored. 
  13557.        2. YY/MM/DD or YYYY/MM/DD 
  13558.        3. YY-MM-DD or YYYY-MM-DD 
  13559.        4. YY MM DD or YYYY MM DD 
  13560.        5. If nothing passed (or blank) then todays date is used. 
  13561.  
  13562.  Note that for most formats it actually does not matter how many digits are 
  13563.  supplied for day of month and month, however a resonable amount of validation 
  13564.  occurs. 
  13565.  
  13566.  EXAMPLE INPUT DATES 
  13567.  
  13568.        1. date('Sorted'); 
  13569.        2. date('Ordered'); 
  13570.        3. "98-2-12" 
  13571.        4. "1998/02/01" 
  13572.        5. "20001230" 
  13573.        6. "20001230235959" 
  13574.  
  13575.  EXAMPLE CODE 
  13576.  
  13577.  The following code could be used in a web page which has an expiry (use by) 
  13578.  date for some reason (maybe it counts down the days to an event): 
  13579.  
  13580.       #if basedate() > basedate('20011225')
  13581.           #error ^This page expired 25 Dec 2001^
  13582.       #endif
  13583.  
  13584.  This code works out the date a week for now and generates it in 2 formats: 
  13585.  
  13586.       #DefineRexx ''
  13587.              ;--- Get date in default format for 7 days from now ---
  13588.              BaseDateToday   = basedate();
  13589.              BaseDateIn7Days = BaseDateToday + 7;
  13590.              DateYYYYMMDD    = Bd2Date(BaseDateIn7Days);
  13591.  
  13592.              ;--- Convert to nicer format ---------
  13593.              parse var DateYYYYMMDD YYYY 5 MM 7 DD
  13594.              MmText = word('Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec', MM);
  13595.              DatePretty = DD+0 || ' ' || MmText || ' ' || YYYY;
  13596.       #DefineRexx
  13597.       Date in 7 Days
  13598.       ~~~~~~~~~~~~~~
  13599.       DEFAULT: <??DateYYYYMMDD>    ;;Maybe "20010403"
  13600.       PRETTY : <??DatePretty>      ;;Maybe "3 Apr 2001"
  13601.  
  13602.  
  13603. ΓòÉΓòÉΓòÉ 11.8.17. BreakAt() ΓòÉΓòÉΓòÉ
  13604.  
  13605. BreakAt() 
  13606.  
  13607. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13608. extensions) can be used with any operating system supported by PPWIZARD. 
  13609.  
  13610. This function gets passed a string and ensures that no component is larger than 
  13611. a value you specify.  It is useful for automatically breaking up long URLs in 
  13612. tables etc so a column does not get too wide. The function takes the following 
  13613. parameters: 
  13614.  
  13615.        1. Break Length 
  13616.           There are 2 formats for this value: 
  13617.  
  13618.               A single integer specifies the maximum width of each component. 
  13619.                The minimum is a third of this value. 
  13620.  
  13621.               You can supply both the minimum & maximum values by separating 
  13622.                them with "-" (as in "5-40"). 
  13623.  
  13624.        2. String 
  13625.           This is the string we are adjusting. 
  13626.  
  13627.        3. Break At Char List 
  13628.           This is a list of chars.  We will try and find the longest string 
  13629.           less than or equal to "Break Length" that breaks after one of these 
  13630.           specified characters, if we can't find one the string is just 
  13631.           truncated at the maximum length.  If this optional value is not 
  13632.           specified then the 4 characters ":./#" are used. 
  13633.  
  13634.        4. Break With Character 
  13635.           This specifies the string used to break the string. If this optional 
  13636.           value is not specified then "<BR>" is used. 
  13637.  
  13638.  The resultant string is returned. 
  13639.  
  13640.  EXAMPLE 
  13641.  
  13642.  This example shows a table where the first column contains a URL as a 
  13643.  hypertext link to the URL shown.  We don't wish the column to be wider than 18 
  13644.  characters (longer URLs will span multiple lines). 
  13645.  
  13646.       ;--- Define a macro to (1) Create link (2) split up long URLS ---
  13647.       #define LinkToDisplayedURL                             \
  13648.               #evaluate "TmpResult" @BreakAt(18, '{$URL}')@  \
  13649.               <A TARGET=_top HREF="http://{$URL}">           \
  13650.               <$TmpResult></A>                               \
  13651.               #undef     TmpResult
  13652.  
  13653.       ;--- Example of use in a table ----------------------------------
  13654.       <BR><CENTER><TABLE COLS=2 BORDER=5 CELLSPACING=5>
  13655.           ;------------------------------------------------------------
  13656.           <TR>
  13657.           <TH ALIGN=CENTER>http://
  13658.           <TH ALIGN=CENTER>Information</B>
  13659.           </TR>
  13660.  
  13661.           ;------------------------------------------------------------
  13662.           <TR>
  13663.           <TD ALIGN=CENTER><$LinkToDisplayedURL URL="www.geocities.com/SiliconValley/Heights/6121/">
  13664.           <TD ALIGN=CENTER>
  13665.           Programmer's Info Page.
  13666.           </TR>
  13667.       </TABLE></CENTER>
  13668.  
  13669.  
  13670. ΓòÉΓòÉΓòÉ 11.8.18. BulkChar2String() ΓòÉΓòÉΓòÉ
  13671.  
  13672. BulkChar2String() 
  13673.  
  13674. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13675. extensions) can be used with any operating system supported by PPWIZARD. 
  13676.  
  13677. This function is used to convert a whole series of single characters into 
  13678. strings. To convert single characters to other single characters you would of 
  13679. course use the rexx translate() routine. 
  13680.  
  13681. This function takes 2 parameters as follows: 
  13682.  
  13683.        1. The name of the source string. 
  13684.  
  13685.        2. The name of a rexx variable which lists each of the characters (in 
  13686.           order) which you wish to convert. For each character in this string 
  13687.           an element in the array of the same name contains what it should be 
  13688.           converted to. The BulkChangePrepare() routine can be used to simplify 
  13689.           the creation of the change information. 
  13690.  
  13691.  The routine returns the possibly modified source string. 
  13692.  
  13693.  When this routine returns the rexx variable ReplaceCount will have been 
  13694.  incremented by the number of replacements made. 
  13695.  
  13696.  Silly Example 
  13697.  
  13698.       ;--- Set up the conversion information ------
  13699.       #DefineRexx ""
  13700.          call BulkChangePrepare "Conv";                 ;;Initialize to empty
  13701.          call BulkChangePrepare "Conv", '&', '&';
  13702.          call BulkChangePrepare "Conv", '<', '<';
  13703.          call BulkChangePrepare "Conv", '>', '>';
  13704.       #DefineRexx
  13705.  
  13706.       ;--- Modify the input string -----------------
  13707.       #evaluate '' ^say 'MODIFIED = ' || BulkChar2String('AAAA <&> BBBB', 'Conv')^
  13708.  
  13709.  
  13710. ΓòÉΓòÉΓòÉ 11.8.19. BulkChangePrepare() ΓòÉΓòÉΓòÉ
  13711.  
  13712. BulkChangePrepare() 
  13713.  
  13714. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13715. extensions) can be used with any operating system supported by PPWIZARD. 
  13716.  
  13717. This function is used to prepare the information required by the 
  13718. BulkChar2String() routine. 
  13719.  
  13720. This function takes 1 or 3 parameters as follows: 
  13721.  
  13722.        1. The name of a rexx variable which you will use in the change call. 
  13723.  
  13724.        2. The character to be replaced. 
  13725.  
  13726.        3. The string that will replace the character. 
  13727.  
  13728.  To initialize the change information this routine should be called with out 
  13729.  the second and third parameters. This routine does not return anything. 
  13730.  
  13731.  
  13732. ΓòÉΓòÉΓòÉ 11.8.20. Chars() ΓòÉΓòÉΓòÉ
  13733.  
  13734. Chars() 
  13735.  
  13736. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13737. extensions) can be used with any operating system supported by PPWIZARD. 
  13738.  
  13739. This function should be used to write characters to standard out. 
  13740.  
  13741. If the /ConsoleFile switch is used any output you send directly to standard 
  13742. output will not be visible! 
  13743.  
  13744. This call takes a single parameter and that is the characters to output. 
  13745.  
  13746.  
  13747. ΓòÉΓòÉΓòÉ 11.8.21. CompareReplaceFixed() ΓòÉΓòÉΓòÉ
  13748.  
  13749. CompareReplaceFixed() 
  13750.  
  13751. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13752. extensions) can be used with any operating system supported by PPWIZARD. 
  13753.  
  13754. This function has 2 main operations as follows: 
  13755.  
  13756.        1. Compare a string against a compare specification. The return 
  13757.           specification parameter is not passed by the caller. Returns 0 if not 
  13758.           matched and 1 if match. 
  13759.  
  13760.        2. Compare a string against a compare specification. Either return the 
  13761.           original string on no match or a new string as specified by the 
  13762.           return specification. 
  13763.  
  13764.  This is quite a complicated routine and hopefully the examples will clarify 
  13765.  things. 
  13766.  
  13767.  This routine can be very useful in #AsIs and #AutoTag processing. 
  13768.  
  13769.  The function takes 3 parameters as follows: 
  13770.  
  13771.        1. The string to be compared with. 
  13772.  
  13773.        2. The COMPARE specification. This is made up of one or more of the 
  13774.           following command sequences (in any order): 
  13775.  
  13776.               @Operator,Posn=^CmpText^ 
  13777.                The "operator" is a rexx compare operator such as "=" or "<>". 
  13778.  
  13779.                The "posn" is the integer position of the substring within the 
  13780.                "COMPARE" parameter to compare with "CmpText". If the value is 
  13781.                positive then the value refers to a position from the left else 
  13782.                it refers to a position from the right. For example "2" 
  13783.                indicates the second character from the left while "-2" 
  13784.                indicates the second last character. The length of the substring 
  13785.                is the same as the length of "CmpText". 
  13786.  
  13787.                Any character can be used for a quote character around the 
  13788.                "CmpText". 
  13789.  
  13790.               ?Operator/CmpText/ 
  13791.                The operator should be either "=" or "!".  If "=" then we expect 
  13792.                to find "CmpText" in the first parameter, otherwise we don't. 
  13793.  
  13794.                Any character can be used for a quote character around the 
  13795.                "CmpText". 
  13796.  
  13797.               !SubCommand 
  13798.                The subcommand is one of: 
  13799.  
  13800.                  -  S 
  13801.                     The following compares are to be case sensitive (each time 
  13802.                     this routine is called it begins in case sensitive mode). 
  13803.  
  13804.                  -  i 
  13805.                     The following compares are to be case insensitive (you 
  13806.                     should supply upper case "CmpText" text). 
  13807.  
  13808.                  -  I 
  13809.                     Ignore leading and trailing whitespace. Convert multiple 
  13810.                     spaces into a single space. 
  13811.  
  13812.                  -  B 
  13813.                     Ignore leading and trailing whitespace. 
  13814.  
  13815.                  -  L 
  13816.                     Ignore leading whitespace. 
  13817.  
  13818.                  -  T 
  13819.                     Ignore trailing whitespace. 
  13820.  
  13821.        3. The RETURN specification. If not supplied then we are doing a simple 
  13822.           compare operation and returning 1 on match and 0 if not. 
  13823.  
  13824.           This parameter determines what string this routine will return. You 
  13825.           can extract parts of the first parameter and intermix text of your 
  13826.           own. A return command is imbedded in text and begins with the '@' 
  13827.           character, the following byte determines the type of command, valid 
  13828.           commands are: 
  13829.  
  13830.               @ 
  13831.                A '@@' indicates that the user wishes a single '@'. This is an 
  13832.                escape sequence which allows the '@' character to be specified. 
  13833.  
  13834.               $Posn,Len; 
  13835.                You wish to extract a string out of the first parameter. You 
  13836.                need to specify its position and length. You may supply '*' for 
  13837.                the length to indicate that the rest of the string is desired. 
  13838.  
  13839.                If the value is positive then the value refers to a position 
  13840.                from the left else it refers to a position from the right. For 
  13841.                example "2" indicates the second character from the left while 
  13842.                "-2" indicates the second last character. 
  13843.  
  13844.               =/RexxExpression/ 
  13845.                A rexx expression is executed to determine the text to be used, 
  13846.                you have access to the first parameter of this routine in the 
  13847.                variable "CompareString". This method should be avoided where 
  13848.                ever possible as it is significantly slower. 
  13849.  
  13850.                Any character can be used for a quote character around the 
  13851.                "RexxExpression" parameter. 
  13852.  
  13853.  While some validation of the parameters is performed you should be careful 
  13854.  with the parameters passed. If invalid parameters are passed you probably will 
  13855.  not get the "change" you desire and I'm not ruling out a PPWIZARD trap. 
  13856.  Validations are only performed when they will not (greatly) affect 
  13857.  performance. 
  13858.  
  13859.  Example - Compare Specifications 
  13860.  
  13861.        1. @=,1=^HTML^ 
  13862.           To see if a string starts with the characters "HTML" (in that case). 
  13863.  
  13864.        2. @=,1=^HTML^!i@=,-2=^YZ^ 
  13865.           To see if a string starts with the characters "HTML" (in that case) 
  13866.           and ends with the characters "YZ" (in any case). 
  13867.  
  13868.        3. !B@=,1=^HTML^!i@=,-2=^YZ^ 
  13869.           Same as above but leading and trailing whitespace is ignored. 
  13870.  
  13871.        4. @=,1=/HTML/!i@<>,-2=\YZ\ 
  13872.           To see if a string starts with the characters "HTML" (in that case) 
  13873.           and does not end with the characters "YZ" (in any case). 
  13874.  
  13875.        5. !i?=/HTML/ 
  13876.           We expect the compare string to contain "HTML" (in any case). 
  13877.  
  13878.  Example - Return Specifications 
  13879.  
  13880.        1. ABCD 
  13881.           Return the string "ABCD". 
  13882.  
  13883.        2. AB@@C@@D 
  13884.           Return the string "AB@C@D". 
  13885.  
  13886.        3. REM @$1,*; 
  13887.           Return the compare string (first parameter) preceeded by "REM ". 
  13888.  
  13889.        4. REM @$1,1;@$3,1;@$-1,1; 
  13890.           Return the 1st and 3rd and last characters of the compare string 
  13891.           preceeded by "REM ". 
  13892.  
  13893.        5. REM (@=/strip(CompareString)/) 
  13894.           Return the line stripped of leading and trailing whitespace 
  13895.           surrounded by round brackets and preceeded by "REM ". 
  13896.  
  13897.  Stupid Examples 
  13898.  
  13899.       ;--- The following compare operation will return "1" as the compare "matches" ---
  13900.       #evaluate ^^ ^say 'Expect to see 1    ==> ' || CompareReplaceFixed('HTML', '@=,1=~HTML~')^
  13901.  
  13902.       ;--- The following compare matches and the return specification is processed ---
  13903.       #evaluate ^^ ^say 'Expect to see ASDF ==> ' || CompareReplaceFixed('HTML', '@=,1=~HTML~', 'ASDF')^
  13904.  
  13905.  
  13906. ΓòÉΓòÉΓòÉ 11.8.22. DataGet() ΓòÉΓòÉΓòÉ
  13907.  
  13908. DataGet() 
  13909.  
  13910. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13911. extensions) can be used with any operating system supported by PPWIZARD. 
  13912.  
  13913. This function is used to retrieve a value previously stored away with the 
  13914. DataSave() function. 
  13915.  
  13916. It is OK for the value not to exist, if this is the case the "default" value 
  13917. you specified will be returned.  If you wish you can make the "default" value 
  13918. some sort of "invalid value" to detect what you consider to be an error. 
  13919.  
  13920. The function takes 3 parameters as follows: 
  13921.  
  13922.        1. The Application Key. 
  13923.  
  13924.        2. The Key. 
  13925.  
  13926.        3. The default value (optional, default is ''). 
  13927.  
  13928.  
  13929. ΓòÉΓòÉΓòÉ 11.8.23. DataSave() ΓòÉΓòÉΓòÉ
  13930.  
  13931. DataSave() 
  13932.  
  13933. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13934. extensions) can be used with any operating system supported by PPWIZARD. 
  13935.  
  13936. This function is used to save a value away using a 2 part key.  If you wish you 
  13937. can make the first part constant.  The value can be retrieved using the 
  13938. DataGet() function. 
  13939.  
  13940. The function takes 3 parameters as follows: 
  13941.  
  13942.        1. The Application Key. 
  13943.  
  13944.        2. The Key. 
  13945.  
  13946.        3. The data to store. 
  13947.  
  13948.  Note that there is no information returned by this function. 
  13949.  
  13950.  WARNING 
  13951.  
  13952.  Currently the value you save is kept between compiles, this is not the aim and 
  13953.  will be corrected in a future release.  Do not code anything that relies on 
  13954.  this fact.  If you use this routine you will need to consider if you can 
  13955.  compile more than one source at a time. 
  13956.  
  13957.  
  13958. ΓòÉΓòÉΓòÉ 11.8.24. Debug() ΓòÉΓòÉΓòÉ
  13959.  
  13960. Debug() 
  13961.  
  13962. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13963. extensions) can be used with any operating system supported by PPWIZARD. 
  13964.  
  13965. This function is used to output a debug line. The line is only output if debug 
  13966. mode is currently on. 
  13967.  
  13968. The DebugIndent() call can be used to make your output easier to understand. 
  13969.  
  13970. The function takes a single parameter and that is the line to be output. 
  13971.  
  13972.  
  13973. ΓòÉΓòÉΓòÉ 11.8.25. DebugIndent() ΓòÉΓòÉΓòÉ
  13974.  
  13975. DebugIndent() 
  13976.  
  13977. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13978. extensions) can be used with any operating system supported by PPWIZARD. 
  13979.  
  13980. This function is passed a single numeric parameter which is positive or 
  13981. negative (normally -1 or 1). A positive value causes a bigger indent on the 
  13982. left of Debug() output. 
  13983.  
  13984. If you increase the indent you must remember to decrease it when finished. 
  13985.  
  13986.  
  13987. ΓòÉΓòÉΓòÉ 11.8.26. Defined() ΓòÉΓòÉΓòÉ
  13988.  
  13989. Defined() 
  13990.  
  13991. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  13992. extensions) can be used with any operating system supported by PPWIZARD. 
  13993.  
  13994. This function can be called (probably in a #if command) to determine if a 
  13995. variable has been defined with either #define or #evaluate.  The return code is 
  13996. either 'N' or 'Y'. 
  13997.  
  13998. You would use this routine in a #if command rather than a #ifdef or #ifndef if 
  13999. you want to do something which involves testing the existance of more than one 
  14000. variable. 
  14001.  
  14002. The parameters are as follows: 
  14003.  
  14004.        1. Define Name 
  14005.           This is the name of the variable. 
  14006.  
  14007.  EXAMPLE 
  14008.  
  14009.       #ifdef Var1
  14010.            ...
  14011.       #endif
  14012.  
  14013.       #if  Defined('Var1') = 'Y' | Defined('Var2') = 'Y'
  14014.            ...
  14015.       #endif
  14016.  
  14017.  
  14018. ΓòÉΓòÉΓòÉ 11.8.27. DieIfIoErrorOccurred() ΓòÉΓòÉΓòÉ
  14019.  
  14020. DieIfIoErrorOccurred() 
  14021.  
  14022. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14023. extensions) can be used with any operating system supported by PPWIZARD. 
  14024.  
  14025. This function can be called to at any time prior to the closing of a file 
  14026. (stream) to determine if any input/output errors have occurred. 
  14027.  
  14028. The routine will display a message and abort PPWIZARD processing if an error 
  14029. has occurred. 
  14030.  
  14031. The parameters are as follows: 
  14032.  
  14033.        1. File Name 
  14034.           This is the name of an unclosed file. 
  14035.  
  14036.  
  14037. ΓòÉΓòÉΓòÉ 11.8.28. EnsureFileHasCorrectCase() ΓòÉΓòÉΓòÉ
  14038.  
  14039. EnsureFileHasCorrectCase() 
  14040.  
  14041. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14042. extensions) can be used with any operating system supported by PPWIZARD. 
  14043.  
  14044. This routine takes a filename as its only parameter and adjusts its filename as 
  14045. specified with the "/FileNames" command line switch. 
  14046.  
  14047. Note that while the intention of this routine is to adjust the case of 
  14048. filenames there is no reason why any rexx string can't be passed if you have 
  14049. the need. 
  14050.  
  14051.  
  14052. ΓòÉΓòÉΓòÉ 11.8.29. Error() ΓòÉΓòÉΓòÉ
  14053.  
  14054. Error() 
  14055.  
  14056. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14057. extensions) can be used with any operating system supported by PPWIZARD. 
  14058.  
  14059. This routine is probably most useful in #import filter code and takes from 1 to 
  14060. 10 parameters. Each parameter contains the contents of a line to be displayed. 
  14061.  
  14062. The passed message line(s) will be displayed and PPWIZARD processing 
  14063. terminated. 
  14064.  
  14065.  
  14066. ΓòÉΓòÉΓòÉ 11.8.30. ErrorSql() ΓòÉΓòÉΓòÉ
  14067.  
  14068. ErrorSql() 
  14069.  
  14070. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14071. extensions) can be used with any operating system supported by PPWIZARD. 
  14072.  
  14073. This routine is probably most useful in when accessing SQL databases directly 
  14074. in rexx. 
  14075.  
  14076. When an SQL specific error is detected simply call this routine with up to 6 
  14077. lines (parameters) and it will dump these along with the reason the SQL call 
  14078. failed. PPWIZARD will then terminate. 
  14079.  
  14080. Note that if parameter 1 is not passed then this call will create a description 
  14081. of the problem based on the last RexxSQL call used. 
  14082.  
  14083.  
  14084. ΓòÉΓòÉΓòÉ 11.8.31. ExpandXCodes() ΓòÉΓòÉΓòÉ
  14085.  
  14086. ExpandXCodes() 
  14087.  
  14088. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14089. extensions) can be used with any operating system supported by PPWIZARD. 
  14090.  
  14091. This routine can be called to expand <?xXX> codes. 
  14092.  
  14093. This routine is passed a single parameter. The codes are expanded and the 
  14094. result returned. 
  14095.  
  14096.  
  14097. ΓòÉΓòÉΓòÉ 11.8.32. FindFile() ΓòÉΓòÉΓòÉ
  14098.  
  14099. FindFile() 
  14100.  
  14101. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14102. extensions) can be used with any operating system supported by PPWIZARD. 
  14103.  
  14104. The purpose of this routine is to search for a file. The return code is the 
  14105. full name of the file or the empty string ("") if it could not be located. This 
  14106. routine use used internally by PPWIZARD to search for files included with the 
  14107. #include command as well as other situations. 
  14108.  
  14109. This routine takes a single parameter such as "fred.inc" and looks in the 
  14110. following standard locations for it: 
  14111.  
  14112. The following locations are searched in order, using FindFileInPath(): 
  14113.  
  14114.        1. The Current Directory 
  14115.        2. /INCLUDEPATH.BR Any locations specified with the/IncludePath switch.
  14116.        3. PPWIZARD_INCLUDE environment variable.
  14117.        4. INCLUDE environment variable.
  14118.        5. PPWIZARD Install Directory 
  14119.  
  14120.  If you need more control over where PPWIZARD looks for the file then you 
  14121.  should also check out the FindFileInPath() routine (which is also used 
  14122.  internally by this call). 
  14123.  
  14124.  Example 
  14125.  
  14126.       #DefineRexx '' "$TRACE"
  14127.          File1 = FindFile("htmlpre.ih");
  14128.       #DefineRexx
  14129.  
  14130.  
  14131. ΓòÉΓòÉΓòÉ 11.8.33. FindFileInPath() ΓòÉΓòÉΓòÉ
  14132.  
  14133. FindFileInPath() 
  14134.  
  14135. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14136. extensions) can be used with any operating system supported by PPWIZARD. 
  14137.  
  14138. The purpose of this routine is to search for a file. It gives you full control 
  14139. over where it searches, unlike the FindFile() routine. If you want the current 
  14140. directory searched then you need to specify this! 
  14141.  
  14142. The return code is the full name of the file or the empty string ("") if it 
  14143. could not be located. 
  14144.  
  14145. This routine takes 2 parameters as follows: 
  14146.  
  14147.        1. LookingFor 
  14148.           This is the partial name of a file which we are trying to locate 
  14149.           (such as "HTMLPRE.IH" or "include\HTMLPRE.IH"). 
  14150.  
  14151.        2. DirList 
  14152.           This is a list of items separated by ";" (or colon for unix). 
  14153.  
  14154.           If the item begins with a "*" character then what follows is the name 
  14155.           of an environment variable whose contents should be searched. 
  14156.  
  14157.           If the item begins with a "+" character then what follows is the name 
  14158.           of a directory. You wish the whole directory tree to be searched. 
  14159.           Note that depending on the size of the tree you could significantly 
  14160.           slow down searching (be careful). 
  14161.  
  14162.           If the items does not begin with any special character then it is 
  14163.           simply the name of a directory to be searched. 
  14164.  
  14165.  Example 
  14166.  
  14167.       #DefineRexx '' "$TRACE"
  14168.          File1 = FindFile("ppwizard.rex", "+c:\webimage;*PATH;c:\any\dir1;*REGINA_MACROS;+c:\any\dir2tree");
  14169.       #DefineRexx
  14170.  
  14171.  
  14172. ΓòÉΓòÉΓòÉ 11.8.34. GenerateFileName() ΓòÉΓòÉΓòÉ
  14173.  
  14174. GenerateFileName() 
  14175.  
  14176. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14177. extensions) can be used with any operating system supported by PPWIZARD. 
  14178.  
  14179. This function returns a filename which is translated in the same way as the 
  14180. "/Output" switch. It also ensures that any directory component of the generated 
  14181. filename exists. 
  14182.  
  14183. The parameters are as follows: 
  14184.  
  14185.        1. Name of a file 
  14186.           This is the name of a file that is used as a basic for conversion 
  14187.           using the second parameter. 
  14188.  
  14189.        2. An "Edit Mask" 
  14190.           This tells PPWIZARD how to convert the first parameter. 
  14191.  
  14192.           An edit mask is basically much like a file (with path if required) 
  14193.           and will contain zero or one special characters as follows: 
  14194.  
  14195.             a. *.* or {$SHORT} 
  14196.                This gets replaced with the short filename (no path) of the 
  14197.                current input file.
  14198.  
  14199.             b. * or {$BASE} 
  14200.                This gets replaced with the short filename (less path and 
  14201.                extension) of the current input file.
  14202.  
  14203.             c. {$FULL} 
  14204.                This gets replaced with the full filename (with path) of the 
  14205.                current input file.
  14206.  
  14207.             d. ? or {$PATH} 
  14208.                This gets replaced with the path (including terminating slash) 
  14209.                of the current input file. This is most likely to be of use if 
  14210.                you want to position generated files relative to the input file 
  14211.                and your mask scans subdirectories. For example "?OUT\*.HTM".
  14212.  
  14213.             e. {$path} 
  14214.                This allows you to set up a separate tree for generated 
  14215.                filenames, the input mask and file are examined and the relative 
  14216.                path extracted, the result is either blank ('') or a relative 
  14217.                path that ends with a path separator. Note for this to work the 
  14218.                input mask must either use an absolute path, begin with '.' or 
  14219.                '..' followed by slash or not have a path attached at all 
  14220.                otherwise ppwizard will abort. It would be pointless to use this 
  14221.                sort of path unless subdirectories are being scanned. You may 
  14222.                wish to investigate the /BaseDir switch. 
  14223.  
  14224.  Note that unix type operating systems will probably have problems with "$path" 
  14225.  etc (to unix this means replace with the "path" environment variable's 
  14226.  contents). You need to hide or escape the dollar sign, so use either 
  14227.  "{x24}path" or "\$path" instead.
  14228.  
  14229.  The "EditMask" can be absolute or relative (your exact circumstances will 
  14230.  determine your choice). 
  14231.  
  14232.  Note that resultant relative filenames are always relative to the current 
  14233.  directory. 
  14234.  
  14235.  While you control the case of the mask you can't control the case of the part 
  14236.  that replaces the '*'.  What you can do is ensure the whole name is either in 
  14237.  upper or lower case with the /FileNames switch. 
  14238.  
  14239.  Note that the /UNC switch affects how this routine operates. 
  14240.  
  14241.  Example 
  14242.  
  14243.       ;--- For the current input file work out a good name for a debug file ---
  14244.       #evaluate '' ^DebugFile = GenerateFileName('<?InputFile>', 'out\*.DBG')^
  14245.  
  14246.  
  14247. ΓòÉΓòÉΓòÉ 11.8.35. GetAmPmTime() ΓòÉΓòÉΓòÉ
  14248.  
  14249. GetAmPmTime() 
  14250.  
  14251. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14252. extensions) can be used with any operating system supported by PPWIZARD. 
  14253.  
  14254. This function returns the current time in a 12 hour format. Note that the hour 
  14255. is not padded to 2 characters so the length of the returned value can vary. 
  14256.  
  14257. This routine takes these parameters: 
  14258.  
  14259.        1. Want Seconds Returned? .BR  Optional parameter, the value should be 
  14260.           'Y' or 'N'. The default is "Y". 
  14261.  
  14262.        2. AM/PM Text .BR  This optional parameter defaults to "am;pm" which is 
  14263.           the text you want to use to represent am and pm times. 
  14264.  
  14265.  
  14266. ΓòÉΓòÉΓòÉ 11.8.36. GetAmPmTimeFromHhMmSs() ΓòÉΓòÉΓòÉ
  14267.  
  14268. GetAmPmTimeFromHhMmSs() 
  14269.  
  14270. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14271. extensions) can be used with any operating system supported by PPWIZARD. 
  14272.  
  14273. This function reformats a passed 24 hour time and returns a 12 hour time of the 
  14274. form "HH:MM:SS??" or "HH:MM??". Note that "HH" never has a leading zero. 
  14275.  
  14276. The parameters are as follows: 
  14277.  
  14278.        1. The Time 
  14279.           This is the 24 hour time in the format "HHMMSS" (exactly 6 
  14280.           characters) or "HH:MM:SS" (with or without the seconds). No 
  14281.           validation is performed on the passed values, some valid ones are 
  14282.           "15:59:52", 1:1:1", "155952" and "15:59". 
  14283.  
  14284.        2. Want Seconds Returned? .BR  Optional parameter, the value should be 
  14285.           'Y' or 'N'. If the value is not supplied then the seconds value will 
  14286.           only be returned if one was passed. 
  14287.  
  14288.        3. AM/PM Text .BR  This optional parameter defaults to "am;pm" which is 
  14289.           the text you want to use to represent am and pm times. 
  14290.  
  14291.  Example 
  14292.  
  14293.          FileDateTime = GetFileTimeStamp(TheFile);
  14294.          FileTime     = GetAmPmTimeFromHhMmSs(substr(FileDateTime, 9))
  14295.  
  14296.  
  14297. ΓòÉΓòÉΓòÉ 11.8.37. GetDependancyInfo() ΓòÉΓòÉΓòÉ
  14298.  
  14299. GetDependancyInfo() 
  14300.  
  14301. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14302. extensions) can be used with any operating system supported by PPWIZARD. 
  14303.  
  14304. This function allows you to access information about input and output 
  14305. dependancy information currently stored. 
  14306.  
  14307. The parameters are as follows: 
  14308.  
  14309.        1. Dependancy Type 
  14310.           You should pass either "INPUT" or "OUTPUT". 
  14311.  
  14312.        2. Which One 
  14313.           If this parameter is not supplied a count of the number of available 
  14314.           items of the type specified is returned. You may pass any number from 
  14315.           1 to the number of items available to retrieve it. 
  14316.  
  14317.  
  14318. ΓòÉΓòÉΓòÉ 11.8.38. GetEnv() ΓòÉΓòÉΓòÉ
  14319.  
  14320. GetEnv() 
  14321.  
  14322. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14323. extensions) can be used with any operating system supported by PPWIZARD. 
  14324.  
  14325. This function returns the value of an operating system environment variable. An 
  14326. empty string is returned if the variable is unknown. 
  14327.  
  14328. The parameters are as follows: 
  14329.  
  14330.        1. Variable Name 
  14331.           This is the name of the environment variable. 
  14332.  
  14333.        2. Die if Missing? 
  14334.           This optional variable is used to tell ppwizard to abort if the 
  14335.           variable could not be found. To tell PPWIZARD to abort pass upper 
  14336.           case 'Y'. 
  14337.  
  14338.  Example 
  14339.  
  14340.       ;--- Lets keep all WORK/HOME conditional logic here -------------------------
  14341.       #define AtHome  translate(GetEnv("PRJSRCDIR", 'Y')) =  "E:\DB\PROJECTS\HOMEPAGE\HTML"
  14342.       #define AtWork  translate(GetEnv("PRJSRCDIR", 'Y')) <> "E:\DB\PROJECTS\HOMEPAGE\HTML"
  14343.  
  14344.       ...
  14345.       ...
  14346.  
  14347.       ;--- External Links ---------------------------------------------------------
  14348.       #if    <$AtHome>
  14349.               #define ExtLink   <A TARGET=_top HREF="{$URL}">{$VISIBLE=`{$URL}`}</A>
  14350.       #elseif
  14351.               #define ExtLink   {$VISIBLE=`{$URL}`}{$URL-}
  14352.       #endif
  14353.  
  14354.  
  14355. ΓòÉΓòÉΓòÉ 11.8.39. GetFileLineBeingProcessed() ΓòÉΓòÉΓòÉ
  14356.  
  14357. GetFileLineBeingProcessed() 
  14358.  
  14359. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14360. extensions) can be used with any operating system supported by PPWIZARD. 
  14361.  
  14362. This function takes no parameters and returns the text of the current line 
  14363. being processed. The line is as read from a file and may or may not be the 
  14364. current line being processed (after macro expansion etc). The line being 
  14365. processed is available using the GetLineBeingProcessed() call. 
  14366.  
  14367. The returned line has been stripped of leading and trailing whitespace. This 
  14368. call would usually be called to remember details about a current situation 
  14369. which you may wish to report at some future stage. 
  14370.  
  14371. If using this call you may also wish to use GetInputFileNameAndLine(), see this 
  14372. section for an example of these calls in use. 
  14373.  
  14374.  
  14375. ΓòÉΓòÉΓòÉ 11.8.40. GetFileTimeStamp() ΓòÉΓòÉΓòÉ
  14376.  
  14377. GetFileTimeStamp() 
  14378.  
  14379. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14380. extensions) can be used with any operating system supported by PPWIZARD. 
  14381.  
  14382. This function takes a single parameter (the name of the file we wish the 
  14383. date/time imformation of). 
  14384.  
  14385. If successful this routine returns a decimal number of the form 
  14386. "YYYYMMDDHHMMSS". The returned number can be compared with others to determine 
  14387. the newest file etc. You can substr() etc to transform the result into whatever 
  14388. format you desire. 
  14389.  
  14390. If the call fails (for example if the specified file does not exist) then a 
  14391. WARNING is generated and a return code of "-1" is returned. 
  14392.  
  14393. You can determine the day of the week or age of a file by passing the return 
  14394. value to BaseDate(). 
  14395.  
  14396. Example 
  14397.  
  14398. The following example shows how the date/time of a file can be retrieved and 
  14399. converted into whatever format you wish. Note that in the following macro I was 
  14400. careful not to redefine any variables and that a file not found is treated as a 
  14401. fatal error. I generally prefer to use #DefineRexx to code a macro such as that 
  14402. shown below however this one demonstates how it can be done with very little 
  14403. knowledge of rexx at all. 
  14404.  
  14405.     #define   GetFileDateTime                                                    \
  14406.               #DependsOn INPUT  "{$File}"                                       -\
  14407.               #evaluate  TmpDateTime  ^GetFileTimeStamp("{$File}");^            -\
  14408.               #if   <$TmpDateTime> = -1                                         -\
  14409.                     #error ^The file "{$File}" was not found.^                  -\
  14410.               #elseif                                                           -\
  14411.                     ;--- Reformat the retrieved information ------------------- -\
  14412.                     #evaluate TmpDate ^substr('<$TmpDateTime>', 7, 2) || '/' || substr('<$TmpDateTime>', 5, 2) || '/' || left('<$TmpDateTime>', 4)^ -\
  14413.                     #evaluate TmpTime ^GetAmPmTimeFromHhMmSs(substr('<$TmpDateTime>', 9))^-\
  14414.                                                                                 -\
  14415.                     ;--- Output the information ("DD/MM/YYYY at HH:MM:SSam") -- -\
  14416.                     <$TmpDate> at <$TmpTime>                                    -\
  14417.                     #undef TmpDate                                              -\
  14418.                     #undef TmpTime                                              -\
  14419.               #endif                                                            -\
  14420.               #undef TmpDateTime
  14421.  
  14422.     ;--- Use my macro to get a timestamp -------------------------------------
  14423.     <P>The date/time stamp of "C:\AUTOEXEC.BAT" is "<$GetFileDateTime File="C:\AUTOEXEC.BAT">".
  14424.  
  14425.  
  14426. ΓòÉΓòÉΓòÉ 11.8.41. GetId() ΓòÉΓòÉΓòÉ
  14427.  
  14428. GetId() 
  14429.  
  14430. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14431. extensions) can be used with any operating system supported by PPWIZARD. 
  14432.  
  14433. This function is produces a unique string from your text and can ensure that 
  14434. the new string only contains "valid" characters and can be limited in length. 
  14435.  
  14436. This can be useful when you wish to use a value as a key of some sort. For the 
  14437. value that you pass, this routine will determine a unique key (or ID) of the 
  14438. format you requested. 
  14439.  
  14440. The routine has a memory and will always return the same ID for the same value. 
  14441.  
  14442. Note that if you currently search array elements then you know that this is 
  14443. slow. Generating unique rexx variable names for a string allows you to save the 
  14444. information for "keyed" access, that is absolutely no searching required to 
  14445. locate the information! 
  14446.  
  14447. The fastest and typically easiest way of generating a "key" is with the 
  14448. standard rexx "c2x()" built in routine. All characters generated by "c2x()" 
  14449. will be valid in a rexx variable name and as long as you prefix it with 
  14450. something alphabetic you will generate a valid rexx variable name. Its major 
  14451. deficiency is that it doubles the string length (not counting a constant 
  14452. prefix) and this can cause problems on some interpreters (not regina) which 
  14453. usually have variable name restrictions of 250 characters or so). Another major 
  14454. disadvantage is that if the key is visible (say if used to generate a filename) 
  14455. then it is absolutely cryptic (can also make debugging harder)! 
  14456.  
  14457. My recommendation is that if you don't have length restrictions and the key is 
  14458. not visible (or you don't care what a filename looks like etc) then you would 
  14459. be crazy not to use "c2x()" as it is extremely fast, otherwise this "GetId()" 
  14460. routine should be used. 
  14461.  
  14462. The function takes at least 3 parameters as follows: 
  14463.  
  14464.        1. A handle that was previously prepared with GetIdPrepare(). 
  14465.  
  14466.        2. The type of ID you'd like, valid types being: 
  14467.  
  14468.               2_ 
  14469.                Non valid characters are converted to underscores. Leading and 
  14470.                trailing underscores are removed. Duplicated underscores are 
  14471.                also removed. 
  14472.  
  14473.                The upper and lower case characters as well as zero to nine are 
  14474.                always valid characters. You may specify additional valid 
  14475.                characters in the optional 4th parameter to this function. 
  14476.  
  14477.               MAXCHARS 
  14478.                The value is first converted in a similar manner to that used 
  14479.                for "2_" mode. The leftmost 'x' chars are kept. 
  14480.  
  14481.                The upper and lower case characters as well as zero to nine are 
  14482.                always valid characters. You may specify additional valid 
  14483.                characters in the optional 4th parameter to this function. 
  14484.  
  14485.                The optional 5th parameter specifies the maximum number of 
  14486.                characters in an ID with the default being 8. 
  14487.  
  14488.                This type can be used to generate file names for a 8.3 based 
  14489.                file system. 
  14490.  
  14491.               C2X 
  14492.                Non valid characters are converted to 'x??', where '??' is the 
  14493.                characters ASCII code in hexadecimal. 
  14494.  
  14495.                The upper and lower case characters as well as zero to nine are 
  14496.                always valid characters. You may specify additional valid 
  14497.                characters in the optional 4th parameter to this function. 
  14498.  
  14499.        3. The value for which you want an ID generated. This is case sensitive, 
  14500.           to make case insensitive simply convert your value to either upper or 
  14501.           lower case before calling this routine. 
  14502.  
  14503.        4. Depending on the type of ID being generated there may be a 4th or 
  14504.           other parameters. 
  14505.  
  14506.  Example 
  14507.  
  14508.       ;--- Example #1 ---
  14509.       #evaluate ''   ^call GetIdPrepare 'PPW'^
  14510.       #evaluate ''   ^call SetId 'PPW', '#define', "HashDef"^       ;;Set preferred ID
  14511.       #evaluate ''   ^say GetId('PPW', 'MAXCHARS', 'define')^
  14512.       #evaluate ''   ^say GetId('PPW', 'MAXCHARS', '#define')^
  14513.       #evaluate ''   ^say GetId('PPW', 'MAXCHARS', 'define it')^
  14514.       #evaluate ''   ^say GetId('PPW', 'MAXCHARS', 'define')^
  14515.       #evaluate ''   ^say GetId('PPW', 'MAXCHARS', 'aaaaaaaaaaaaaaaa',, 10)^  ;;Max 10 chars
  14516.       #evaluate ''   ^say GetId('PPW', 'MAXCHARS', 'aaaaaaaaaaaaaaab',, 10)^
  14517.       #evaluate ''   ^say GetId('PPW', 'MAXCHARS', 'aaaaaaaaaaaaaaac',, 10)^
  14518.       #evaluate ''   ^say GetId('PPW', 'MAXCHARS', 'aaaaaaaaaaaaaaaa',, 10)^
  14519.  
  14520.       ;--- Example #2 ---
  14521.       #evaluate ''   ^call GetIdPrepare 'PPW'^
  14522.       #evaluate ''   ^say GetId('PPW', '2_', '#define')^
  14523.       #evaluate ''   ^say GetId('PPW', '2_', '#include', '#')^  ;;Allow Hash to be valid as well
  14524.  
  14525.  
  14526. ΓòÉΓòÉΓòÉ 11.8.42. GetIdPrepare() ΓòÉΓòÉΓòÉ
  14527.  
  14528. GetIdPrepare() 
  14529.  
  14530. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14531. extensions) can be used with any operating system supported by PPWIZARD. 
  14532.  
  14533. This function is used to prepare a handle for use in the GetId() routine. 
  14534.  
  14535. The function takes 2 parameters: 
  14536.  
  14537.        1. The handle to be used in GetId() and SetId(). 
  14538.  
  14539.        2. An optional parameter which if 'Y' means that you wish unique IDs 
  14540.           generated by GetId() for what are probably non-unique values (or 
  14541.           keys). When you specify unique IDs you are only allowed to use 
  14542.           SetId() with a key of '' otherwise you are contradicting yourself! 
  14543.  
  14544.           Normally when GetId() is called you pass it a unique key for which 
  14545.           you wish a unique ID generated. If you ask for an ID for the same key 
  14546.           at some later stage the original ID is returned. 
  14547.  
  14548.           When 'Y' is used you intend to pass non-unique keys but YOU ensure or 
  14549.           know that each time GetId() is called it is for a different entity 
  14550.           even if the key looks identical!  GetId() will generate a unique ID 
  14551.           each time it is called and will not remember it. This mode can 
  14552.           generate "prettier" IDs (at least until the key is duplicated) and 
  14553.           without tricky code. The "FTPLIKE.IH" add-on uses the "unique" mode. 
  14554.  
  14555.  
  14556. ΓòÉΓòÉΓòÉ 11.8.43. GetImageHeightWidth() ΓòÉΓòÉΓòÉ
  14557.  
  14558. GetImageHeightWidth() 
  14559.  
  14560. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14561. extensions) can be used with any operating system supported by PPWIZARD. 
  14562.  
  14563. This function can be used to automatically generate the HEIGHT and WIDTH 
  14564. parameters on a html "IMG" tag. 
  14565.  
  14566. The function takes 3 parameters (the 2nd and 3rd are optional), the parameters 
  14567. are: 
  14568.  
  14569.        1. The name of a file (.GIF, .JPG or .PNG) 
  14570.  
  14571.        2. The width  scaling factor (default = "100%"). 
  14572.  
  14573.        3. The height scaling factor (default = "?"). 
  14574.  
  14575.        4. By default this function now returns the height and width values 
  14576.           surrounded by double quotes, if you want the old style (no quotes) 
  14577.           then pass 'Y' for this parameter. 
  14578.  
  14579.        5. By default this function caches results so that it does not have to 
  14580.           re-read a file if it is used multiple times. The cache is maintained 
  14581.           across individual builds for the life of a ppwizard invokation. Pass 
  14582.           'Y' for this parameter if you want to bypass all cache logic. 
  14583.  
  14584.  The scaling factor can be in these formats: 
  14585.  
  14586.          A number followed by a percentage sign scales the size by the amount 
  14587.           specified. "50%" would halve the size while 200% would double it. 
  14588.  
  14589.          A number on its own (such as "100") fixes the size to the value 
  14590.           supplied. It would be a common thing for the other sides size to be 
  14591.           specified with "?" to have it scaled down in a proportional manner. 
  14592.  
  14593.          A "?" causes the side to be sized in the same proportion as the other 
  14594.           side. 
  14595.  
  14596.  Note that scaling both sizes of an image by "50%" gives you an image a 1/4 of 
  14597.  the size. 
  14598.  
  14599.  If an error occurs the routine aborts, otherwise a string similar to "WIDTH=10 
  14600.  HEIGHT=20" gets returned. If you have one of the supported image types and 
  14601.  ppwizard fails to handle it please send it to me zipped so I can update 
  14602.  ppwizard as required. 
  14603.  
  14604.  Note that as the image file needs to be read to determine its size this 
  14605.  routine will slow down the preprocessing of your files. You could get smart 
  14606.  and generate an image header file of sizes (each one #defined) so that a 
  14607.  separate slow step generates a header file that html source includes. 
  14608.  
  14609.  Example #1 - IMG Macro 
  14610.  
  14611.  This demonstrates how you can create an "IMG" macro which can take any number 
  14612.  of html IMG tag parameters.  It generates a HTML image tag with the height and 
  14613.  width parameters added: 
  14614.  
  14615.   ;--- We will make use of existing functionality -----------------------------
  14616.   #define   FILEINFO_DEFAULT_PATH ..\     ;;This plus "SRC" value indicates where "LOCAL" file is (build time), in my case it's in "..\graphics"
  14617.   #include  "FILEINFO.H"
  14618.  
  14619.   ;--- Image Macros -----------------------------------------------------------
  14620.   #define IMG                                                      \
  14621.           ;--- Get image & video information using rexx code --   -\
  14622.           #DefineRexx  ''                                         -\
  14623.              ;--- Make sure IMG file exists etc ---------------   -\
  14624.              <$RexxVerifyLocalInputFile FILE="{$SRC}">;           -\
  14625.                                                                   -\
  14626.              ;--- Get Image Height & Width --------------------   -\
  14627.              RxImgHw = GetImageHeightWidth(<$FILEINFO_RXVAR_FULL_LOCAL_FILE>); -\
  14628.           #DefineRexx                                             -\
  14629.                                                                   -\
  14630.           ;--- Generate the "IMG" tag -------------------------   -\
  14631.           <IMG SRC="{$SRC}" <??RxImgHw>{$? $$PASSDSQ $$SPCPLUS}>
  14632.  
  14633.   ;--- Test macro -------------------------------------------------------------
  14634.   <$IMG SRC="16x12.gif">
  14635.   <$IMG ALT="a graphic" SRC="16x12.gif">
  14636.   <$IMG ALT="a graphic" SRC="16x12.gif" X='Y'>
  14637.  
  14638.  Example #2 
  14639.  
  14640.  This demonstrates the creation of image tables (using "styles"): 
  14641.  
  14642.      ;--- Photo macro will either use passed size or work out correct size for you ---
  14643.      #define Photo                                                               \
  14644.              #evaluate+  LocalFileName    ^"..\graphics\{$Image}"^               \
  14645.              #DependsOn  INPUT            "<$LocalFileName>"                     \
  14646.              <TR>                                                                \
  14647.              #if "{$Size=''}" <> ""                                              \
  14648.                  #define+   TmpSize {$Size=''}     ;;User supplied size          \
  14649.              #elseif                                                             \
  14650.                  #evaluate+ TmpSize ^GetImageHeightWidth("<$LocalFileName>")^    \
  14651.              #endif                                                              \
  14652.              <TD ALIGN=CENTER>                                                   \
  14653.              <IMG SRC="graphics/clear1x1.gif" WIDTH=1 HEIGHT=1 VSPACE=20>        \
  14654.              {$Title}<BR><BR>                                                    \
  14655.              <IMG SRC="graphics/{$Image}" BORDER=0 <$TmpSize> ALT="{$Title}">    \
  14656.              <IMG SRC="graphics/clear1x1.gif" WIDTH=1 HEIGHT=1 VSPACE=20>        \
  14657.              </TR>
  14658.  
  14659.       ;--- Create table of photos --------------------------------------------
  14660.       <BR><CENTER><TABLE COLS=1 BORDER=10 CELLSPACING=10>
  14661.          <TR>
  14662.          <TH ALIGN=CENTER>Pictures
  14663.          </TR>
  14664.  
  14665.          ;--- Include all my photos ------------------------------------------
  14666.          <$Photo Image="lazy.jpg"     Title="Watching TV">
  14667.          <$Photo Image="carback.jpg"  Title="New Car (Back Left)">
  14668.       </TABLE></CENTER>
  14669.  
  14670.  Example #3 
  14671.  
  14672.  This example shows how you can manipulate the format of the height and width 
  14673.  text, this example produces "width,height": 
  14674.  
  14675.   ;--- Define macro which creates 'new Image(W,H);' text ----------------------
  14676.   #defineRexx '_ImageWidthCommaHeight_'
  14677.      ;--- Get heigth and width for image (seperated them from fixed text) -----
  14678.      parse value GetImageHeightWidth("{$IMAGE}") with 'WIDTH="' iWidth '" HEIGHT="' iHeight '"'
  14679.  
  14680.      ;--- Format the information the way we need it ---------------------------
  14681.      iWidthHeight = iWidth || ',' || iHeight;
  14682.   #defineRexx
  14683.   #define ImageWidthCommaHeight                             \
  14684.           #evaluate ^^ ^<$_ImageWidthCommaHeight_ {$?}>^   -\
  14685.           <??iWidthHeight>
  14686.  
  14687.   ;--- Test macro -------------------------------------------------------------
  14688.   JsVar = new Image(<$ImageWidthCommaHeight IMAGE="graphics\ppw_bg.jpg">);
  14689.  
  14690.  
  14691. ΓòÉΓòÉΓòÉ 11.8.44. GetInputFileNameAndLine() ΓòÉΓòÉΓòÉ
  14692.  
  14693. GetInputFileNameAndLine() 
  14694.  
  14695. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14696. extensions) can be used with any operating system supported by PPWIZARD. 
  14697.  
  14698. This function takes no parameters and returns information about the current 
  14699. "location". It reports the current line number and file being processed. This 
  14700. information is already available in other forms (<?InputComponent> & 
  14701. <?InputComponentLine>) however this routine simplifies getting it into a nicely 
  14702. formatted output. 
  14703.  
  14704. If you are interested in this call you should probably also check out the 
  14705. GetFileLineBeingProcessed() and GetLineBeingProcessed() calls. 
  14706.  
  14707. Example 
  14708.  
  14709. This example has been extracted out of the standard PPWIZARD header file 
  14710. NESTCHK.H which can detect and report details of nesting errors such as 
  14711. forgetting a "</TABLE>" tag. 
  14712.  
  14713.     #DefineRexx NestingInc_REXX
  14714.                 ;--- Ensure ID is valid -------
  14715.                 if symbol('{$ID $$SQx2}_Level') <> 'VAR' then
  14716.                    Error('The ID of "{$ID $$SQx2}" is unknown (you must use "NestingInit")!');
  14717.  
  14718.                 ;--- Increase nesting level ---
  14719.                 call _valueS "{$ID}_Level", {$ID}_Level + 1;
  14720.  
  14721.                 ;--- Record details about current location ---
  14722.                 call _valueS "{$ID}_FilePosn.{$ID}_Level", GetInputFileNameAndLine();
  14723.                 call _valueS "{$ID}_CurrLine.{$ID}_Level", GetFileLineBeingProcessed();
  14724.     #DefineRexx
  14725.     #define NestingInc                                            \
  14726.             #evaluate  '' ^<$NestingInc_REXX ID='{$ID}'>^
  14727.  
  14728. The reported output (on nesting errors) looks something like: 
  14729.  
  14730.     NESTING ERRORS
  14731.     ~~~~~~~~~~~~~~
  14732.     Missing 2 end nesting tags on "HTML TABLE tag"
  14733.       * line 8 of "E:\DB\PROJECTS\OS2\ppwizard\1.in"
  14734.         <<$TABLE> COLS=1 blah blah>
  14735.       * line 9 of "E:\DB\PROJECTS\OS2\ppwizard\1.in"
  14736.         <<$TABLE> COLS=2 blah blah>
  14737.  
  14738.  
  14739. ΓòÉΓòÉΓòÉ 11.8.45. GetLineBeingProcessed() ΓòÉΓòÉΓòÉ
  14740.  
  14741. GetLineBeingProcessed() 
  14742.  
  14743. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14744. extensions) can be used with any operating system supported by PPWIZARD. 
  14745.  
  14746. This function takes no parameters and returns the text of the current line 
  14747. being processed. The line returned is after macro expansion and may or may not 
  14748. be as read from the file. The line as read from the file is available using the 
  14749. GetFileLineBeingProcessed() call. 
  14750.  
  14751. The returned line has been stripped of leading and trailing whitespace. This 
  14752. call would usually be called to remember details about a current situation 
  14753. which you may wish to report at some future stage. 
  14754.  
  14755. If using this call you may also wish to use GetInputFileNameAndLine(), see this 
  14756. section for an example of these calls in use. 
  14757.  
  14758.  
  14759. ΓòÉΓòÉΓòÉ 11.8.46. GetQuotedRest() ΓòÉΓòÉΓòÉ
  14760.  
  14761. GetQuotedRest() 
  14762.  
  14763. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14764. extensions) can be used with any operating system supported by PPWIZARD. 
  14765.  
  14766. Quite a few ppwizard commands take a "last parameter" which is a quoted string 
  14767. which is allowed to hold the quote character. This rexx function allows you to 
  14768. make use of this code. 
  14769.  
  14770. The function takes a single parameter: 
  14771.  
  14772.        1. The string which is expected to contain the quoted value. 
  14773.  
  14774.  The function returns the quoted string (without quotes) or dies. 
  14775.  
  14776.  
  14777. ΓòÉΓòÉΓòÉ 11.8.47. GetQuotedText() ΓòÉΓòÉΓòÉ
  14778.  
  14779. GetQuotedText() 
  14780.  
  14781. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14782. extensions) can be used with any operating system supported by PPWIZARD. 
  14783.  
  14784. Most ppwizard commands take "quoted parameters". This rexx function allows you 
  14785. to make use of this code. 
  14786.  
  14787. The function takes one or two parameters: 
  14788.  
  14789.        1. The string which is expected to contain the quoted value. 
  14790.  
  14791.        2. A string containing the name of a variable which is to contain the 
  14792.           "rest" of the string from the first parameter. If this parameter is 
  14793.           not passed then the whole of the first parameter must have contained 
  14794.           the quoted value or the function aborts. 
  14795.  
  14796.  The function returns the quoted string (without quotes) or dies. 
  14797.  
  14798.  Example 
  14799.  
  14800.       ;--- We expect EXACTLY 3 parameters ---
  14801.       @@P1 = GetQuotedText(substr(@@Line,2), "Rest");
  14802.       @@P2 = GetQuotedText(Rest, "Rest");
  14803.       @@P3 = GetQuotedText(Rest);
  14804.  
  14805.  
  14806. ΓòÉΓòÉΓòÉ 11.8.48. Info() ΓòÉΓòÉΓòÉ
  14807.  
  14808. Info() 
  14809.  
  14810. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14811. extensions) can be used with any operating system supported by PPWIZARD. 
  14812.  
  14813. This routine takes a single parameter which is displayed as if the #Info 
  14814. command was used. 
  14815.  
  14816.  
  14817. ΓòÉΓòÉΓòÉ 11.8.49. InputComponentLevel() ΓòÉΓòÉΓòÉ
  14818.  
  14819. InputComponentLevel() 
  14820.  
  14821. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14822. extensions) can be used with any operating system supported by PPWIZARD. 
  14823.  
  14824. This routine takes a single parameter which is the include level that you are 
  14825. interested in. The full name of the input file at that level is returned. 
  14826.  
  14827. If you don't pass any value then the current level is assumed. If you pass an 
  14828. invalid value the empty string ("") is returned. 
  14829.  
  14830. This rexx routine does a similar job to the "<?InputComponent>" special 
  14831. variable (but for any level - not just the current one). 
  14832.  
  14833. Stupid Example 
  14834.  
  14835. Simple example in which one file works out who included it and at what line: 
  14836.  
  14837.     ;--- Work out who included this file (and what line) ---
  14838.     #evaluate ParentFile  ^InputComponentLevel(<?IncludeLevel>-1)^
  14839.     #if  '<$ParentFile>' = ''
  14840.          <P>There is no parent file!
  14841.     #elseif
  14842.          #evaluate ParentLine  ^InputComponentLineLevel(<?IncludeLevel>-1)^
  14843.          <P>The parent file is: "<$ParentFile>" (line <$ParentLine>)
  14844.     #endif
  14845.  
  14846.  
  14847. ΓòÉΓòÉΓòÉ 11.8.50. InputComponentLineLevel() ΓòÉΓòÉΓòÉ
  14848.  
  14849. InputComponentLineLevel() 
  14850.  
  14851. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14852. extensions) can be used with any operating system supported by PPWIZARD. 
  14853.  
  14854. This routine takes a single parameter which is the include level that you are 
  14855. interested in. The line number being processed of the input file at that level 
  14856. is returned. 
  14857.  
  14858. If you don't pass any value then the current level is assumed. If you pass an 
  14859. invalid value the empty string ("") is returned. 
  14860.  
  14861. This rexx routine does a similar job to the "<?InputComponentLine>" special 
  14862. variable (but for any level - not just the current one). 
  14863.  
  14864. For an example of how it could be used have a look at the InputComponentLevel() 
  14865. routine. 
  14866.  
  14867.  
  14868. ΓòÉΓòÉΓòÉ 11.8.51. LoadRexxSql() ΓòÉΓòÉΓòÉ
  14869.  
  14870. LoadRexxSql() 
  14871.  
  14872. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14873. extensions) can be used with any operating system supported by PPWIZARD. 
  14874.  
  14875. This routine is only useful when accessing SQL databases directly in rexx. 
  14876.  
  14877. This routine takes no parameters and simply tries to load Mark Hessling's 
  14878. RexxSQL runtime. I recommend that this call be used as it may be enhanced in 
  14879. future (maybe more intelligence in finding the DLL etc) and dies with an error 
  14880. message when the DLL can't be loaded. 
  14881.  
  14882.  
  14883. ΓòÉΓòÉΓòÉ 11.8.52. IsDebugOn() ΓòÉΓòÉΓòÉ
  14884.  
  14885. IsDebugOn() 
  14886.  
  14887. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14888. extensions) can be used with any operating system supported by PPWIZARD. 
  14889.  
  14890. This function can be called to simply determine whether debug is on or off or 
  14891. to determine the level of user debug currently active (see DebugLevel). 
  14892.  
  14893. This function would be useful if you wished to conditionally call Debug() or 
  14894. conditionally generate html comments in your output etc. 
  14895.  
  14896. The function takes either zero or one parameters as follows: 
  14897.  
  14898.          No parameters indicates that you simply want a Y/N response to 
  14899.           whether or not debug is on (similar to "<?DebugOn>" variable). 
  14900.  
  14901.          If a parameter is supplied it should be a digit (one of 1, 2 or 3). 
  14902.           If debug is off this routine will return 0 otherwise it will return 
  14903.           the result of the supplied number anded to the value of the user bits 
  14904.           (which of course could also result in 0). 
  14905.  
  14906.           That is you can check on each bit seperately if you wish. If you 
  14907.           simply wish to tell if any user debug state is on then pass 3, if you 
  14908.           wish to check the state of one of your flags then pass it's value, a 
  14909.           return code of 0 indicates that that level of debug is not on. 
  14910.  
  14911.  
  14912. ΓòÉΓòÉΓòÉ 11.8.53. MacroGet() ΓòÉΓòÉΓòÉ
  14913.  
  14914. MacroGet() 
  14915.  
  14916. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14917. extensions) can be used with any operating system supported by PPWIZARD. 
  14918.  
  14919. This function takes a single parameter (the name of a macro) and returns its 
  14920. contents. 
  14921.  
  14922. The macro must already exist (created by #define or #evaluate). The value of 
  14923. the macro is returned, if this contains any macros to be replaced, macro 
  14924. parameters or commands to be executed they are not replaced or executed. 
  14925.  
  14926. If you need parameter substitution you could create unique strings and use 
  14927. ReplaceString() to perform the "substitution" yourself. 
  14928.  
  14929. Note that there is also a MacroSet() routine. 
  14930.  
  14931.  
  14932. ΓòÉΓòÉΓòÉ 11.8.54. MacroSet() ΓòÉΓòÉΓòÉ
  14933.  
  14934. MacroSet() 
  14935.  
  14936. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14937. extensions) can be used with any operating system supported by PPWIZARD. 
  14938.  
  14939. This function is used to create a macro. Note that there is also a MacroGet() 
  14940. routine. 
  14941.  
  14942. The function takes 2 or 3 parameters as follows: 
  14943.  
  14944.        1. Name of variable. 
  14945.  
  14946.        2. The macros value. 
  14947.  
  14948.        3. Optional parameter, pass 'Y' if it's OK to redefine the macro, '' for 
  14949.           warning or '?' to only define if it does not already exist. 
  14950.  
  14951.  
  14952. ΓòÉΓòÉΓòÉ 11.8.55. MakeWebLinks() ΓòÉΓòÉΓòÉ
  14953.  
  14954. MakeWebLinks() 
  14955.  
  14956. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14957. extensions) can be used with any operating system supported by PPWIZARD. 
  14958.  
  14959. This function is used to process any http or ftp web addresses in a string. By 
  14960. default a hypertext link is created but you have full control over what occurs. 
  14961.  
  14962. This call does not try and "guess" that something is a web address (for example 
  14963. "www.fred.com") but simply looks for the specified protocol and works out where 
  14964. the URL ends (it knows which characters are valid in a URL). 
  14965.  
  14966. The function takes 3 parameters as follows: 
  14967.  
  14968.        1. The string, the possibly modified string is returned by this call. 
  14969.  
  14970.        2. The protocol, should be exactly "http", "https" or "ftp". 
  14971.  
  14972.        3. Optional parameter, this is a template of how the url should be 
  14973.           handled. By default a simple link is created. <P> The string can 
  14974.           contain the following "variables": 
  14975.  
  14976.               {URL} 
  14977.                This is replaced with the full url (with protocol), for example 
  14978.                "http://www.google.com". 
  14979.  
  14980.               {URL-} 
  14981.                This is replaced with the url without protocol attached, for 
  14982.                example "www.google.com". 
  14983.  
  14984.  
  14985. ΓòÉΓòÉΓòÉ 11.8.56. MustDeleteFile() ΓòÉΓòÉΓòÉ
  14986.  
  14987. MustDeleteFile() 
  14988.  
  14989. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  14990. extensions) can be used with any operating system supported by PPWIZARD. 
  14991.  
  14992. This routine takes a single parameter which is the name of the file you wish 
  14993. deleted. 
  14994.  
  14995. This function is used to ensure that a file does not exist. If first looks to 
  14996. see if the file exists and if so attempts to delete it, if this fails ppwizard 
  14997. terminates with an error. 
  14998.  
  14999.  
  15000. ΓòÉΓòÉΓòÉ 11.8.57. OptionGet() ΓòÉΓòÉΓòÉ
  15001.  
  15002. OptionGet() 
  15003.  
  15004. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15005. extensions) can be used with any operating system supported by PPWIZARD. 
  15006.  
  15007. This routine will return the value currently set for the identified #option. 
  15008.  
  15009. The function takes 1 parameter: 
  15010.  
  15011.        1. The name of the option you are querying. 
  15012.  
  15013.  
  15014. ΓòÉΓòÉΓòÉ 11.8.58. OptionSet() ΓòÉΓòÉΓòÉ
  15015.  
  15016. OptionSet() 
  15017.  
  15018. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15019. extensions) can be used with any operating system supported by PPWIZARD. 
  15020.  
  15021. This routine will set a new value for the identified #option. 
  15022.  
  15023. The function takes 2 parameters: 
  15024.  
  15025.        1. The name of the option you are updating. 
  15026.  
  15027.        2. The new value. 
  15028.  
  15029.  
  15030. ΓòÉΓòÉΓòÉ 11.8.59. PadString() ΓòÉΓòÉΓòÉ
  15031.  
  15032. PadString() 
  15033.  
  15034. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15035. extensions) can be used with any operating system supported by PPWIZARD. 
  15036.  
  15037. This function will generate a padded string, it can pad Left, Right or Center 
  15038. the string you supply. 
  15039.  
  15040. The function takes 3 parameters: 
  15041.  
  15042.        1. The string to be padded (never truncated if wanted length too short). 
  15043.  
  15044.        2. The length of the new string. 
  15045.  
  15046.        3. A single character (for Left, Right or Center). 
  15047.  
  15048.  
  15049. ΓòÉΓòÉΓòÉ 11.8.60. ProcessNext() ΓòÉΓòÉΓòÉ
  15050.  
  15051. ProcessNext() 
  15052.  
  15053. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15054. extensions) can be used with any operating system supported by PPWIZARD. 
  15055.  
  15056. PPWIZARD  macros utilize a buffer to hold lines that they generate, these are 
  15057. read before the file is accessed. This function allows you to add data to be 
  15058. processed next. 
  15059.  
  15060. The function takes a single parameter which is the line or lines (for multiple 
  15061. lines they should separated with a newline character). 
  15062.  
  15063. This routine is handy where you may have captured some text, including 
  15064. references to macros etc and you wish to process the data where the data might 
  15065. otherwise be written directly to the output file. 
  15066.  
  15067.  
  15068. ΓòÉΓòÉΓòÉ 11.8.61. QueryExists() ΓòÉΓòÉΓòÉ
  15069.  
  15070. QueryExists() 
  15071.  
  15072. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15073. extensions) can be used with any operating system supported by PPWIZARD. 
  15074.  
  15075. This function will determine whether a file exists. If it does not exist then 
  15076. "" is returned (else it's full filename (path etc) is returned). 
  15077.  
  15078. The function takes 2 parameters: 
  15079.  
  15080.        1. The name of a file (absolute or relative). 
  15081.  
  15082.        2. This optional parameter if set to 'Y' causes PPWIZARD to abort if the 
  15083.           file does not exist. 
  15084.  
  15085.  
  15086. ΓòÉΓòÉΓòÉ 11.8.62. QuoteIt() ΓòÉΓòÉΓòÉ
  15087.  
  15088. QuoteIt() 
  15089.  
  15090. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15091. extensions) can be used with any operating system supported by PPWIZARD. 
  15092.  
  15093. This function will determine a quote character that is not contained within the 
  15094. string you pass. Processing will abort if it can not do so. 
  15095.  
  15096. The function takes 2 parameters: 
  15097.  
  15098.        1. The string that you wish to quote. 
  15099.  
  15100.        2. An option list of all possible quote characters. If not supplied it 
  15101.           defaults to trying double then single quotes. 
  15102.  
  15103.  This routine is handy when a macro is passed some information and needs to 
  15104.  generate the data in a quoted format. Some languages such as HTML allow 
  15105.  information to be quoted with either a single or a double quote. 
  15106.  
  15107.  Stupid Example 
  15108.  
  15109.       #evaluate     ''  ~RxQuote=QuoteIt('AS"DF')~
  15110.       Should be double = <??RxQuote>
  15111.       #evaluate     ''  ~RxQuote=QuoteIt("AS'DF")~
  15112.       Should be single = <??RxQuote>
  15113.       #evaluate     ''  ~RxContainsBothQuotes = 'AS"' || "'DF"~
  15114.       #evaluate     ''  ~RxQuote=QuoteIt(RxContainsBothQuotes, '"' || "'^")~
  15115.       Should be '^'    = <??RxQuote>
  15116.       #evaluate     ''  ~RxQuote=QuoteIt(RxContainsBothQuotes)~   ;;Will die
  15117.  
  15118.  
  15119. ΓòÉΓòÉΓòÉ 11.8.63. RandomString() ΓòÉΓòÉΓòÉ
  15120.  
  15121. RandomString() 
  15122.  
  15123. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15124. extensions) can be used with any operating system supported by PPWIZARD. 
  15125.  
  15126. This function will use the template string you provide and returned it filled 
  15127. in with randomly chosen characters. This can be handly for generating random 
  15128. variable names or similar strings. 
  15129.  
  15130. The function takes 2 parameters: 
  15131.  
  15132.        1. The template string. This is a string which should contain one or 
  15133.           more '?' characters each of which will be replaced with a randomly 
  15134.           chosen character. 
  15135.  
  15136.        2. An optional string of characters. The random characters will be 
  15137.           chosen out of this string. If this parameter is not passed then the 
  15138.           default string is the digits 0-9 and the uppercase characters A-Z. 
  15139.  
  15140.  Stupid Example 
  15141.  
  15142.       #evaluate     'Var1'  ~RandomString('VAR1_????')~
  15143.       #evaluate     'Var2'  ~RandomString('????????')~
  15144.  
  15145.       ...
  15146.  
  15147.       <$Var1> = <$Var1> + 1;
  15148.       <$Var2> = <$Var1>;
  15149.  
  15150.  
  15151. ΓòÉΓòÉΓòÉ 11.8.64. ReplaceCurlyHexCodes() ΓòÉΓòÉΓòÉ
  15152.  
  15153. ReplaceCurlyHexCodes() 
  15154.  
  15155. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15156. extensions) can be used with any operating system supported by PPWIZARD. 
  15157.  
  15158. This function takes a single parameter (the string) and will return a new 
  15159. string where any strings of the form "{xXX}" have been replaced (where '??' is 
  15160. a valid 2 character hexadecimal code, x00 to xFF). 
  15161.  
  15162. Some Example Codes 
  15163.  
  15164. Here are some example codes: 
  15165.  
  15166. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  15167. ΓöéAscii  ΓöéCode   ΓöéDescription     Γöé
  15168. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15169. Γöé32     Γöé{x20}  ΓöéSpace           Γöé
  15170. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15171. Γöé33     Γöé{x21}  Γöé!               Γöé
  15172. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15173. Γöé34     Γöé{x22}  Γöé" (double quote)Γöé
  15174. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15175. Γöé35     Γöé{x23}  Γöé#               Γöé
  15176. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15177. Γöé36     Γöé{x24}  Γöé$               Γöé
  15178. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15179. Γöé37     Γöé{x25}  Γöé%               Γöé
  15180. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15181. Γöé38     Γöé{x26}  Γöé&               Γöé
  15182. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15183. Γöé39     Γöé{x27}  Γöé' (single quote)Γöé
  15184. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15185. Γöé40     Γöé{x28}  Γöé(               Γöé
  15186. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15187. Γöé41     Γöé{x29}  Γöé)               Γöé
  15188. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15189. Γöé42     Γöé{x2A}  Γöé*               Γöé
  15190. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15191. Γöé43     Γöé{x2B}  Γöé+               Γöé
  15192. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15193. Γöé44     Γöé{x2C}  Γöé,               Γöé
  15194. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15195. Γöé45     Γöé{x2D}  Γöé-               Γöé
  15196. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15197. Γöé46     Γöé{x2E}  Γöé. (dot)         Γöé
  15198. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15199. Γöé47     Γöé{x2F}  Γöé/               Γöé
  15200. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15201. Γöé58     Γöé{x3A}  Γöé                Γöé
  15202. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15203. Γöé59     Γöé{x3B}  Γöé;               Γöé
  15204. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15205. Γöé60     Γöé{x3C}  Γöé<               Γöé
  15206. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15207. Γöé61     Γöé{x3D}  Γöé=               Γöé
  15208. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15209. Γöé62     Γöé{x3E}  Γöé>               Γöé
  15210. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15211. Γöé63     Γöé{x3F}  Γöé?               Γöé
  15212. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15213. Γöé64     Γöé{x40}  Γöé@               Γöé
  15214. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15215. Γöé91     Γöé{x5B}  Γöé[               Γöé
  15216. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15217. Γöé92     Γöé{x5C}  Γöé\               Γöé
  15218. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15219. Γöé93     Γöé{x5D}  Γöé]               Γöé
  15220. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15221. Γöé94     Γöé{x5E}  Γöé^               Γöé
  15222. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15223. Γöé95     Γöé{x5F}  Γöé_ (underscore)  Γöé
  15224. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15225. Γöé96     Γöé{x60}  Γöé`               Γöé
  15226. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15227. Γöé123    Γöé{x7B}  Γöé{               Γöé
  15228. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15229. Γöé124    Γöé{x7C}  Γöé|               Γöé
  15230. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15231. Γöé125    Γöé{x7D}  Γöé}               Γöé
  15232. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  15233. Γöé126    Γöé{x7E}  Γöé~               Γöé
  15234. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  15235.  
  15236.  
  15237. ΓòÉΓòÉΓòÉ 11.8.65. ReplaceMacros() ΓòÉΓòÉΓòÉ
  15238.  
  15239. ReplaceMacros() 
  15240.  
  15241. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15242. extensions) can be used with any operating system supported by PPWIZARD. 
  15243.  
  15244. This function takes a single parameter (the string) and will return a new 
  15245. string where Macros and standard symbols have been replaced. 
  15246.  
  15247. Note that you may not have fully expanded the string, ppwizard stops when it 
  15248. has generated a "newline" character, this is just to make life interesting! 
  15249.  
  15250.  
  15251. ΓòÉΓòÉΓòÉ 11.8.66. ReplaceString() ΓòÉΓòÉΓòÉ
  15252.  
  15253. ReplaceString() 
  15254.  
  15255. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15256. extensions) can be used with any operating system supported by PPWIZARD. 
  15257.  
  15258. This function will convert all occurances of a substring as you specify. 
  15259.  
  15260. The function takes 3 parameters as follows: 
  15261.  
  15262.        1. The string which is to be translated. 
  15263.  
  15264.        2. The FROM string. 
  15265.  
  15266.        3. The TO string. 
  15267.  
  15268.  When this routine returns the rexx variable ReplaceCount will have been 
  15269.  incremented by the number of replacements made. 
  15270.  
  15271.  Note that it's faster to use BulkChar2String() to modify a whole lot of 
  15272.  characters to strings.  Of course converting single characters to other single 
  15273.  characters is better done with the rexx translate() routine. 
  15274.  
  15275.  If you need to do case insensitive changes then use the ReplaceStringCI() 
  15276.  routine. 
  15277.  
  15278.  
  15279. ΓòÉΓòÉΓòÉ 11.8.67. ReplaceStringCI() ΓòÉΓòÉΓòÉ
  15280.  
  15281. ReplaceStringCI() 
  15282.  
  15283. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15284. extensions) can be used with any operating system supported by PPWIZARD. 
  15285.  
  15286. This function will convert all occurances of a substring as you specify. 
  15287.  
  15288. The function takes 3 parameters as follows: 
  15289.  
  15290.        1. The string which is to be translated. 
  15291.  
  15292.        2. The FROM string. 
  15293.  
  15294.        3. The TO string. 
  15295.  
  15296.  When this routine returns the rexx variable ReplaceCount will have been 
  15297.  incremented by the number of replacements made. 
  15298.  
  15299.  This routine is very similar to the ReplaceString() except that it is case 
  15300.  insensitive and that the "TO" string may contain one or more "{*}" strings 
  15301.  which will get replaced with the "FROM" string. 
  15302.  
  15303.  
  15304. ΓòÉΓòÉΓòÉ 11.8.68. RexxVarDefined() ΓòÉΓòÉΓòÉ
  15305.  
  15306. RexxVarDefined() 
  15307.  
  15308. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15309. extensions) can be used with any operating system supported by PPWIZARD. 
  15310.  
  15311. This function is basically a front end for the standard rexx "symbol()" routine 
  15312. which also ensures that the name you passed is valid as a rexx symbol. 
  15313.  
  15314. The routine causes processing to abort if the passed rexx variable is invalid 
  15315. (this validation is the main purpose of this routine!), if this is not desired 
  15316. then you need to use "symbol()'. 
  15317.  
  15318. If you know need to know whether or not the value of a rexx variable is valid 
  15319. then this routine could save you hours of debugging only to find that for some 
  15320. stupid reason the value you were using contains one or more invalid characters. 
  15321.  
  15322. PPWIZARD symbols can be deleted using the #undef command, in a similar manner 
  15323. rexx variables can be removed using the standard rexx 'drop' command. 
  15324.  
  15325. The function takes a single parameter which is the name of the rexx variable. 
  15326.  
  15327. The routine returns either '0' (not defined) or '1' for defined. 
  15328.  
  15329.  
  15330. ΓòÉΓòÉΓòÉ 11.8.69. RexGetTmpFileName() ΓòÉΓòÉΓòÉ
  15331.  
  15332. RexGetTmpFileName() 
  15333.  
  15334. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15335. extensions) can be used with any operating system supported by PPWIZARD. 
  15336.  
  15337. This function returns the name of of currently non-existing file which can be 
  15338. used as a temporary file. 
  15339.  
  15340. If you want some control over the name of the file then you may pass a single 
  15341. parameter which is a filename with '?' in any positions where a "random" digit 
  15342. can be placed (example "IMP_????.TMP"). 
  15343.  
  15344.  
  15345. ΓòÉΓòÉΓòÉ 11.8.70. Say() ΓòÉΓòÉΓòÉ
  15346.  
  15347. Say() 
  15348.  
  15349. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15350. extensions) can be used with any operating system supported by PPWIZARD. 
  15351.  
  15352. This function should be used to write lines to standard out. 
  15353.  
  15354. If the /ConsoleFile switch is used any output you send directly to standard 
  15355. output will not be visible! 
  15356.  
  15357. This call takes a single parameter and that is the characters to output. 
  15358.  
  15359.  
  15360. ΓòÉΓòÉΓòÉ 11.8.71. SetEnv() ΓòÉΓòÉΓòÉ
  15361.  
  15362. SetEnv() 
  15363.  
  15364. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15365. extensions) can be used with any operating system supported by PPWIZARD. 
  15366.  
  15367. This function takes two parameters as follows: 
  15368.  
  15369.        1. The name of the environment variable. 
  15370.        2. The new value ("" to delete it). 
  15371.  
  15372.  The return value is the original value of the environment variable or "" if it 
  15373.  did not exist. 
  15374.  
  15375.  This command may be useful to pass information to any filters you may have set 
  15376.  up (with /FilterInput or /FilterOutput). 
  15377.  
  15378.  
  15379. ΓòÉΓòÉΓòÉ 11.8.72. SetId() ΓòÉΓòÉΓòÉ
  15380.  
  15381. SetId() 
  15382.  
  15383. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15384. extensions) can be used with any operating system supported by PPWIZARD. 
  15385.  
  15386. This function is useful if you wish to ensure that when GetId() is called a 
  15387. specific value for an ID is used. An example of where this might be useful is 
  15388. if you have external entry points into a set of generated html pages. You 
  15389. normally would not care what they are called as long as all the links work, 
  15390. however as soon as you wish externally generated html to link to specific pages 
  15391. you must do something to ensure that the links name does not change. 
  15392.  
  15393. The function takes 3 parameters as follows: 
  15394.  
  15395.        1. A handle that was previously prepared with GetIdPrepare(). 
  15396.  
  15397.        2. The value (KEY) for which you are specifying an ID This is case 
  15398.           sensitive, to make case insensitive simply convert your value to 
  15399.           either upper or lower case before calling this routine. 
  15400.  
  15401.           There is one situation where you may wish to pass a empty key ('') 
  15402.           and that is when you specified unique ID mode on GetIdPrepare(). You 
  15403.           would do this to pass an ID that you never want returned by GetId(). 
  15404.  
  15405.        3. The ID you wish to give to the value (KEY). Note that this is not 
  15406.           validated in any way. It is up to you to ensure it's correct. 
  15407.  
  15408.  Example 
  15409.  
  15410.       #evaluate ''   ^call GetIdPrepare 'PPW'^
  15411.       #evaluate ''   ^call SetId 'PPW', '#define', "HashDef"^       ;;Set preferred ID
  15412.       #evaluate ''   ^say GetId('PPW', 'MAXCHARS', 'define')^
  15413.       #evaluate ''   ^say GetId('PPW', 'MAXCHARS', '#define')^
  15414.  
  15415.  
  15416. ΓòÉΓòÉΓòÉ 11.8.73. SetXCode() ΓòÉΓòÉΓòÉ
  15417.  
  15418. SetXCode() 
  15419.  
  15420. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15421. extensions) can be used with any operating system supported by PPWIZARD. 
  15422.  
  15423. This function takes two parameters as follows: 
  15424.  
  15425.        1. The name of the x code 
  15426.        2. It's value. 
  15427.  
  15428.  The 'x' code will be set to the value, this routine is a useful alternative to 
  15429.  the #RexxVar command and is more useful for bulk changes or setup. 
  15430.  
  15431.  
  15432. ΓòÉΓòÉΓòÉ 11.8.74. SStrip() ΓòÉΓòÉΓòÉ
  15433.  
  15434. SStrip() 
  15435.  
  15436. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15437. extensions) can be used with any operating system supported by PPWIZARD. 
  15438.  
  15439. This is a variation on the standard rexx "strip()" routine, the main difference 
  15440. being is that you can list all characters you wish to treat as spaces. 
  15441.  
  15442. This routine converts all the characters you indicate in the supplied string to 
  15443. spaces and then performs a normal "strip()" operation. By default it strips 
  15444. null bytes ('00'x) and this is typically the main reason it would be called. 
  15445.  
  15446. The function takes 1 or more parameters as follows: 
  15447.  
  15448.        1. The string to be stripped. 
  15449.  
  15450.        2. If supplied should be either 'L', 'T' or 'B' as per the rexx 
  15451.           "strip()" call. The default value is 'B' (strip leading and trailing 
  15452.           spaces). 
  15453.  
  15454.        3. If supplied should be a string of one or more bytes that lists all 
  15455.           characters you would like treated as spaces. The default value is 
  15456.           '00'x (null byte). 
  15457.  
  15458.  The routine returns the modified string. 
  15459.  
  15460.  
  15461. ΓòÉΓòÉΓòÉ 11.8.75. StackPush() ΓòÉΓòÉΓòÉ
  15462.  
  15463. StackPush() 
  15464.  
  15465. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15466. extensions) can be used with any operating system supported by PPWIZARD. 
  15467.  
  15468. The StackPush() and StackPop() routines can be used to store and restore 
  15469. information. Another major use is to validate steps that must be performed in 
  15470. pairs. When a build is completed all pushed items on all stacks must have been 
  15471. popped or the items on the stack are listed and the build fails. 
  15472.  
  15473. For every StackPush() operation there must be a corresponding StackPop(). 
  15474.  
  15475. Note that the "#PUSH and #POP commands use this mechanism for storage. 
  15476.  
  15477. When PPWIZARD has successfully completed a build it will validate all the 
  15478. stacks you have created and report any errors. 
  15479.  
  15480. The function these parameters: 
  15481.  
  15482.        1. A description of item being pushed. This also doubles as an ID which 
  15483.           identifies the stack you wish to push. If the stack does not exist 
  15484.           then an empty one is created. This value is displayed if a stack 
  15485.           error is detected. 
  15486.  
  15487.        2. This is the value to be stored. You don't need to pass this if you 
  15488.           are using the stack as a mechanism for the validation of correct 
  15489.           pairing (it will store ""). 
  15490.  
  15491.        3. This is an optional value which is only used when reporting stack 
  15492.           errors. By default PPWIZARD will display the current source line 
  15493.           being processed, this parameter allows you to specify alternative 
  15494.           text which may help someone locate the cause of the error. 
  15495.  
  15496.  
  15497. ΓòÉΓòÉΓòÉ 11.8.76. StackPop() ΓòÉΓòÉΓòÉ
  15498.  
  15499. StackPop() 
  15500.  
  15501. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15502. extensions) can be used with any operating system supported by PPWIZARD. 
  15503.  
  15504. The StackPush() and StackPop() routines can be used to store and restore 
  15505. information. Another major use is to validate steps that must be performed in 
  15506. pairs. When a build is completed all pushed items on all stacks must have been 
  15507. popped or the items on the stack are listed and the build fails. 
  15508.  
  15509. For every StackPush() operation there must be a corresponding StackPop(). 
  15510.  
  15511. Note that the "#PUSH and #POP commands use this mechanism for storage. 
  15512.  
  15513. The function takes one parameter as follows: 
  15514.  
  15515.        1. A description (stack "ID") of item being popped. 
  15516.  
  15517.  An error is generated if there is nothing on the stack otherwise the value is 
  15518.  returned. 
  15519.  
  15520.  
  15521. ΓòÉΓòÉΓòÉ 11.8.77. Summary() ΓòÉΓòÉΓòÉ
  15522.  
  15523. Summary() 
  15524.  
  15525. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15526. extensions) can be used with any operating system supported by PPWIZARD. 
  15527.  
  15528. This function can be called to add (or remove) details on the displayed 
  15529. summaries. 
  15530.  
  15531. The function takes parameters as follows: 
  15532.  
  15533.        1. The text for the left hand side (before ':'). 
  15534.  
  15535.        2. The text for the right hand side (after ':'). 
  15536.  
  15537.        3. Type of summary line as follows: 
  15538.  
  15539.               To see the details on this build's summary only then pass "" (or 
  15540.                anything other than valid values shown below). 
  15541.  
  15542.               To see the details on this build and all future build's (other 
  15543.                files) summaries then pass "A" or "ALL". 
  15544.  
  15545.               To see the details on the overall summary for all builds then 
  15546.                pass "O" or "OVERALL". 
  15547.  
  15548.               To drop summary details whether user or system generated pass 
  15549.                "D" or "DROP", in which case parameter 2 is ignored. The text in 
  15550.                parameter 1 must EXACTLY match that in a summary line. 
  15551.  
  15552.  Example 
  15553.  
  15554.       ;--- Don't want to see operating system version ---
  15555.       #evaluate "" "call Summary 'Operating Syst',, 'D'"
  15556.  
  15557.       ;--- Add a summary line to this build -------------
  15558.       #evaluate "" "call Summary 'Left', 'Right'"
  15559.  
  15560.  
  15561. ΓòÉΓòÉΓòÉ 11.8.78. Tabs2Spaces() ΓòÉΓòÉΓòÉ
  15562.  
  15563. Tabs2Spaces() 
  15564.  
  15565. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15566. extensions) can be used with any operating system supported by PPWIZARD. 
  15567.  
  15568. The function takes a string and expands any tabs that it contains. 
  15569.  
  15570. The routine takes parameters as follows: 
  15571.  
  15572.        1. The text string. 
  15573.  
  15574.        2. The tab width. If none was specified a width of 8 is used. 
  15575.  
  15576.  
  15577. ΓòÉΓòÉΓòÉ 11.8.79. TimeStamp() ΓòÉΓòÉΓòÉ
  15578.  
  15579. TimeStamp() 
  15580.  
  15581. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15582. extensions) can be used with any operating system supported by PPWIZARD. 
  15583.  
  15584. This routine returns a string of the form "YYYYMMDDHHMMSS" which represents a 
  15585. time. 
  15586.  
  15587. If no parameters are passed then the current time is returned. Parameters are: 
  15588.  
  15589.        1. A time offset. This parameter is optional. This is made up of space 
  15590.           seperated words such as "2w 3d 7h 1" which represents a time offset 
  15591.           (in this case 2 weeks, 3 days, 7 hours and 1 second). This is added 
  15592.           to the current or supplied time. 
  15593.  
  15594.        2. If it is not blank then this is a valid timestamp to be used as the 
  15595.           base time rather than the current time. 
  15596.  
  15597.  Example 
  15598.  
  15599.       #DefineRexx ''
  15600.          call say 'CURRENT TIME'
  15601.          call say '~~~~~~~~~~~~'
  15602.          call say '####### NOW     = ' || TimeStamp();
  15603.          call say '####### + 1     = ' || TimeStamp(1);
  15604.          call say '####### + 1day  = ' || TimeStamp('1d');
  15605.          call say '####### + 1d1s  = ' || TimeStamp('1s 1d');
  15606.  
  15607.          call say '19991112100000'
  15608.          call say '~~~~~~~~~~~~~~'
  15609.          call say '####### SUPPLIED= ' || TimeStamp(, "19991112100000");
  15610.          call say '####### + 1     = ' || TimeStamp(1, "19991112100000");
  15611.       #DefineRexx
  15612.  
  15613.  
  15614. ΓòÉΓòÉΓòÉ 11.8.80. ToLowerCase() ΓòÉΓòÉΓòÉ
  15615.  
  15616. ToLowerCase() 
  15617.  
  15618. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15619. extensions) can be used with any operating system supported by PPWIZARD. 
  15620.  
  15621. This function takes a single parameter and returns it in lower case. The 
  15622. translations are performed for english characters only (a-z), for other 
  15623. languages see the examples below. 
  15624.  
  15625. Note that there is no PPWIZARD "upper case" case routine as the standard rexx 
  15626. translate() does this nicely. 
  15627.  
  15628. Example - Polish Case Translation <P>You could have the following in a header 
  15629. file (possibly called "polish.ih"): 
  15630.  
  15631.     ;--- Define all non-english upper/lower case pairs --------------------------
  15632.     #DefineRexx ''
  15633.        ;--- Polish characters in cp-1250 or iso-8859-2 encoding -----------------
  15634.        PL_Lower = 'abcdefghijklmnopqrstuvwxyz' || 'B1B9E6EAB3F1F3B69CBFBC9F'x
  15635.        PL_Upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' || 'A1A5C6CAA3D1D3A68CAFAC8F'x
  15636.     #DefineRexx
  15637.  
  15638.  
  15639.     ;--- "$$" commands for Polish (cp-1250 or iso-8859-2 encoding) case conversion ---
  15640.     #DefineRexx REXX_$$PL_UPPER
  15641.        TheValue = translate(TheValue, PL_UPPER, PL_LOWER);
  15642.     #DefineRexx
  15643.     #DefineRexx REXX_$$PL_LOWER
  15644.        TheValue = translate(TheValue, PL_LOWER, PL_UPPER);
  15645.     #DefineRexx
  15646.  
  15647. Now for some examples of the above being used: 
  15648.  
  15649.     ;--- Define something ----------------------------------------
  15650.     #define SomethingInUpper   ASDF
  15651.  
  15652.     ;--- Use previously defined value (required in lower case) ---
  15653.     This is in lower case: "<$SomethingInUpper $$PL_LOWER>"
  15654.  
  15655.     ;--- Use previously defined value (required in lower case) ---
  15656.     #DefineRexx ''
  15657.         LowerCaseValue = translate('FRED', PL_LOWER, PL_UPPER)
  15658.     #DefineRexx
  15659.     So is this: "<??LowerCaseValue>"
  15660.  
  15661.  
  15662. ΓòÉΓòÉΓòÉ 11.8.81. UpdateCrc32() ΓòÉΓòÉΓòÉ
  15663.  
  15664. UpdateCrc32() 
  15665.  
  15666. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15667. extensions) can be used with any operating system supported by PPWIZARD. 
  15668.  
  15669. This function along with 2 other "helper" functions can be used to create a 
  15670. CRC-32 checksum for one or more blocks of memory. The routine being pure rexx 
  15671. is not real fast (about 40,000 bytes/sec on an Athlon 700) but would be fine 
  15672. for smallish blocks of memory. 
  15673.  
  15674. In case you don't know what a CRC is it can be used for two main reasons, 
  15675. firstly to create a random hash of a string and secondly it can be stored for 
  15676. comparison with another string's CRC at some future time. Two different strings 
  15677. are extremely unlikely to have the same CRC value. A CRC allows you to store 
  15678. the CRC and not the (possibly hugh) original string. 
  15679.  
  15680. The parameters are as follows: 
  15681.  
  15682.        1. CRC Value on Input 
  15683.           This allows you to progressively build up the CRC from a number of 
  15684.           memory blocks. The format is exactly 4 bytes binary, for example 
  15685.           '00112233'x. Typically (and if you wish to generated the same CRC as 
  15686.           ZIP uses) the value for the first block is the return code from 
  15687.           "Crc32PrePostConditioning()" called without parameters. 
  15688.  
  15689.        2. Block Of Memory 
  15690.           This is the block of memory for which the CRC is being updated. After 
  15691.           the last block of memory you would typically pass the CRC to 
  15692.           "Crc32PrePostConditioning()" as the one and only parameter. 
  15693.  
  15694.  The return code from each call to this routine is the updated return code. 
  15695.  
  15696.  The "Crc32InDisplayableForm()" routine when passed the binary form of the CRC 
  15697.  will return a displayable (hexadecimal) form. 
  15698.  
  15699.  Example 
  15700.  
  15701.  Assuming you have two variables "part1" and "part2" which contain the string 
  15702.  for which you wish to calculate a CRC then the following code will calculate 
  15703.  and then display one that would match that calculated by the zip utilities for 
  15704.  the same content: 
  15705.  
  15706.       ;--- Calculate the CRC ------------------------
  15707.       Crc32 = Crc32PrePostConditioning();        ;;Initialize CRC value
  15708.       Crc32 = UpdateCrc32(Crc32, Part1);         ;;Update CRC for this block
  15709.       Crc32 = UpdateCrc32(Crc32, Part2);         ;;As above
  15710.       Crc32 = Crc32PrePostConditioning(Crc32);   ;;Adjust CRC
  15711.  
  15712.       ;--- Display the CRC --------------------------
  15713.       say 'CRC32 = ' || Crc32InDisplayableForm(Crc32);   ;;Convert CRC to 8 byte displayable form
  15714.  
  15715.  
  15716. ΓòÉΓòÉΓòÉ 11.8.82. UrlDecode() ΓòÉΓòÉΓòÉ
  15717.  
  15718. UrlDecode() 
  15719.  
  15720. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15721. extensions) can be used with any operating system supported by PPWIZARD. 
  15722.  
  15723. This function can be called to convert a string (encoded URL) back into its 
  15724. plain text format.  The decoded string is returned. 
  15725.  
  15726. The parameters are as follows: 
  15727.  
  15728.        1. Input String 
  15729.           This is the string which is to be decoded. 
  15730.  
  15731.        2. Mode 
  15732.           Normally occurances of '+' are replaced with spaces. Pass "LEAVE+" to 
  15733.           not handle the plus characters. 
  15734.  
  15735.  
  15736. ΓòÉΓòÉΓòÉ 11.8.83. UrlEncode() ΓòÉΓòÉΓòÉ
  15737.  
  15738. UrlEncode() 
  15739.  
  15740. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15741. extensions) can be used with any operating system supported by PPWIZARD. 
  15742.  
  15743. This function can be called to convert a string into a valid format for use in 
  15744. a URL. Characters such as '#' are converted to codes as they have special 
  15745. meanings when found within a URL. The new encoded string is returned. This 
  15746. routine should eliminate the need for having to see encoded URLs in your source 
  15747. code. 
  15748.  
  15749. The parameters are as follows: 
  15750.  
  15751.        1. Input String 
  15752.           This is the string which is to be encoded. 
  15753.  
  15754.        2. Mode 
  15755.  
  15756.               EncodeAll 
  15757.                All characters in the input string are encoded, so that it can 
  15758.                be called as a poor man's encryption scheme. It can hide stuff 
  15759.                (at least from casual browsing) in plain html code etc. A space 
  15760.                in not encoded as a plus. 
  15761.  
  15762.               To% 
  15763.                You need to supply a 3rd parameter which is a list of all 
  15764.                characters that you would like to encode. A space is not encoded 
  15765.                as a plus. 
  15766.  
  15767.               To%Except 
  15768.                You need to supply a 3rd parameter which is a list of all 
  15769.                characters that you would not like to encode all others are 
  15770.                encoded. By default all alphanumerics, dot, minus and underscore 
  15771.                characters are left alone. A space is not encoded as a plus. 
  15772.  
  15773.               ? 
  15774.                If you can tell me a scheme that is required then let me know 
  15775.                and I can add it... 
  15776.  
  15777.        3. Mode Dependent Parameters 
  15778.           There may be one or more extra parameters depending on the mode. 
  15779.  
  15780.  Example 
  15781.  
  15782.       #evaluate 'HiddenText'   ^UrlEncode("Password", "EncodeAll")^
  15783.  
  15784.  
  15785. ΓòÉΓòÉΓòÉ 11.8.84. Warning() ΓòÉΓòÉΓòÉ
  15786.  
  15787. Warning() 
  15788.  
  15789. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15790. extensions) can be used with any operating system supported by PPWIZARD. 
  15791.  
  15792. This routine is probably most useful in #import filter code and takes a two 
  15793. parameters. The first parameter is the message ID and the second is the message 
  15794. text, see the #warning command for more details. 
  15795.  
  15796. The passed warning message will be displayed. 
  15797.  
  15798.  
  15799. ΓòÉΓòÉΓòÉ 11.8.85. WriteLineToTmpImportFile() ΓòÉΓòÉΓòÉ
  15800.  
  15801. WriteLineToTmpImportFile() 
  15802.  
  15803. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  15804. extensions) can be used with any operating system supported by PPWIZARD. 
  15805.  
  15806. This function takes a single parameter and has no return code (on failure 
  15807. PPWIZARD will terminate). It must only be called while #Import is being 
  15808. processed. 
  15809.  
  15810. You may pass one or more lines of data which will be written to the temporary 
  15811. file that pass one of an import generates. 
  15812.  
  15813. To indicate the end of a line the Linefeed character (decimal 10) should be 
  15814. used the actual characters written to the file are determined by the /CrLf 
  15815. state. 
  15816.  
  15817. For an example have a look at a complex import example. 
  15818.  
  15819.  
  15820. ΓòÉΓòÉΓòÉ 11.8.86. _filespec() ΓòÉΓòÉΓòÉ
  15821.  
  15822. _filespec() 
  15823.  
  15824. This is a rexx function provided by PPWIZARD. This routine is named similar to 
  15825. an OS/2 specific call with a similar purpose, this PPWIZARD version works in 
  15826. all operating systems supported by PPWIZARD. 
  15827.  
  15828. This function takes two parameters as follows: 
  15829.  
  15830.        1. The part of the filename to extract. Valid are (note you are also 
  15831.           allowed to passed only the 1st character of each command): 
  15832.  
  15833.               basename   - Base  (example 'XCOPY') 
  15834.               drive    - Drive (example 'C:') 
  15835.               extn     - Extension (example 'EXE') 
  15836.               location   - Location (example 'C:\OS2\') 
  15837.               name     - Shortname (example 'XCOPY.EXE') 
  15838.               path     - Path  (example '\OS2\') 
  15839.               withoutextn - No extension (example 'C:\OS2\XCOPY') 
  15840.  
  15841.        2. The name of the file. 
  15842.  
  15843.  The return value is the extracted component you requested. It is important to 
  15844.  note that a partial filename is not converted to its full name before 
  15845.  extraction, the part is extracted from what you supply. It is also assumed 
  15846.  that the filename is of a valid format. 
  15847.  
  15848.  Example 
  15849.  
  15850.       ;--- Capture some HTML information ---
  15851.       #evaluate  ShortNameHtml  ^_filespec('name', '<?OutputFile>')^
  15852.  
  15853.  
  15854. ΓòÉΓòÉΓòÉ 11.8.87. _SysFileDelete() ΓòÉΓòÉΓòÉ
  15855.  
  15856. _SysFileDelete() 
  15857.  
  15858. This is a rexx function provided by PPWIZARD. This routine is named similar to 
  15859. an OS/2 specific call with a similar purpose, this PPWIZARD version works in 
  15860. all operating systems supported by PPWIZARD. 
  15861.  
  15862. This function takes a single parameter which is the filename to delete. This 
  15863. routine returns a non-zero return code on error. 
  15864.  
  15865. The MustDeleteFile() routine is similar to this call except that ppwizard will 
  15866. terminate on error if the file can't be deleted. 
  15867.  
  15868.  
  15869. ΓòÉΓòÉΓòÉ 11.8.88. _SysFileTree() ΓòÉΓòÉΓòÉ
  15870.  
  15871. _SysFileTree() 
  15872.  
  15873. This is a rexx function provided by PPWIZARD. This routine is named similar to 
  15874. an OS/2 specific call with a similar purpose, this PPWIZARD version works in 
  15875. all operating systems supported by PPWIZARD. 
  15876.  
  15877. This function takes two parameters as follows: 
  15878.  
  15879.        1. The name of a file or directory to look for (normally containing 
  15880.           wildcard characters appropriate to the operating system being used). 
  15881.  
  15882.           In linux specify a directory name with a terminating slash to capture 
  15883.           all files or subdirectories in that directory. 
  15884.  
  15885.        2. The name of a rexx stem (array) to place the list of matching files 
  15886.           (example "Files"). On return "Files.0" contains the number of files, 
  15887.           "Files.1" contains the first filename etc. 
  15888.  
  15889.        3. List of options, supported are: 
  15890.  
  15891.               F  - Files only (default). 
  15892.               D  - Directories only. 
  15893.               FS - Files and follow subdirectories. 
  15894.               DS - Directories and follow subdirectories. 
  15895.  
  15896.  If successful a return code of 0 is returned. The contents of the "array" may 
  15897.  not be valid if an error occurred so always either check the return code or 
  15898.  preset the ".0" element to 0 before making the call. 
  15899.  
  15900.  The full (absolute) name of files is always returned, however the names of 
  15901.  directories may be absolute or relative depending on what you passed as the 
  15902.  first parameter to this routine. 
  15903.  
  15904.  
  15905. ΓòÉΓòÉΓòÉ 12. Related Tools & Links ΓòÉΓòÉΓòÉ
  15906.  
  15907. Graphics Manipulation 
  15908.  
  15909.          Image Magick 
  15910.           This is an excellent free Image Conversion and Manipulation package. 
  15911.           It can be used to automate the creation of thumbnails (my "thumb.ih" 
  15912.           download requires it). It can be used for all sorts of purposes for 
  15913.           example to resize, rotate, sharpen, color reduce, or add special 
  15914.           effects to an image. It could be used to create graphic buttons from 
  15915.           an image and some text. 
  15916.  
  15917.           It supports over 68 image formats and make no mistake this product 
  15918.           differs in 2 main ways from others you might find, it is completely 
  15919.           free and everything can be automated! The PPWIZARD thumb nail header 
  15920.           runs it in command line mode but there is a GUI ('X' windows). 
  15921.  
  15922.           The source is available and it runs on Windows 2000 or Windows 95/98 
  15923.           as well as on virtually any Unix system and Linux, Macintosh, VMS, 
  15924.           and OS/2. It is available from http://www.imagemagick.org/ 
  15925.  
  15926.           One glitch (at least under windows), it must be installed in the 
  15927.           "C:\ImageMagick" directory for it to work. 
  15928.  
  15929.  REXX Extensions 
  15930.  
  15931.          RexxSQL - SQL ACCESS 
  15932.           Another free product for a large range of operating systems. Support 
  15933.           covers a very large number of different databases. It is available 
  15934.           from http://www.lightlink.com/hessling/REXXSQL/. This is required by 
  15935.           the #import SQL command. 
  15936.  
  15937.          REXXIO 
  15938.           A free rexx extension for Windows and OS/2. Contains File Functions, 
  15939.           Directory Functions, Search Functions, Window Functions, 
  15940.           Keyboard/Mouse Event Functions, Rexx Functions, Registry Functions, 
  15941.           Global Stem Variable Functions, General Functions, Comms Functions 
  15942.           Event Functions. Get it from 
  15943.           http://www.lestec.com.au/freelibrary.htm. 
  15944.  
  15945.          REGUTIL 
  15946.           A free rexx extension for unix and windows. It provides access to 
  15947.           windows registry as well as some other powerful file and directory 
  15948.           features. It was created by Patrick McPhee and is available from 
  15949.           http://www.interlog.com/~ptjm/. 
  15950.  
  15951.          RxSock For Windows 
  15952.           Get a windows version of the RxSock.DLL from 
  15953.           http://home.hiwaay.net/~abbott/regina/. It allows you to talk to web 
  15954.           servers (grab web pages etc). My "CHECKURL" URL checker (validates a 
  15955.           pages exists and hasn't moved (see 
  15956.           http://www.labyrinth.net.au/~dbareis/checkurl.htm). 
  15957.  
  15958.           There is a "linux" patch for this product so that it will run on 
  15959.           Linux. 
  15960.  
  15961.          RexxGD - IMAGE MANIPULATION 
  15962.           A rexx interface to a graphics manipulation program allowing you to 
  15963.           automatically create buttons and graphics. It is available from 
  15964.           http://www.lightlink.com/hessling/RexxGd/index.html. 
  15965.  
  15966.          RexxTK - GUI INTERFACE 
  15967.           Allows you to create graphical interfaces using input boxes, radio 
  15968.           buttons etc. It is available from 
  15969.           http://www.lightlink.com/hessling/RexxTk/index.html. 
  15970.  
  15971.  Other Links 
  15972.  
  15973.          The Regina REXX Interpreter 
  15974.           Download the free rexx interpreter required by ppwizard on all 
  15975.           operating systems other than OS/2 from 
  15976.           http://www.lightlink.com/hessling/. Note that you could use the OS/2 
  15977.           version under OS/2 and there are reasons why you may wish to. 
  15978.  
  15979.          Regina Documentation 
  15980.           You can get a (slighty out of date) regina rexx manual from 
  15981.           http://sites.netscape.net/ssatguru, this has HTML and compiled 
  15982.           Windows Help formats for download. 
  15983.  
  15984.          Rexx Tips and Tricks 
  15985.           Absolutely a must read for anyone using rexx under OS/2, only 
  15986.           available as an OS/2 INF file. Note that a lot of the information is 
  15987.           also applicable to other operating systems. You can get it from 
  15988.           http://hobbes.nmsu.edu/cgi-bin/h-search?sh=1&button=Search&key=rexx+tips+%26+tricks&stype=all&sort=type&dir=%2F. 
  15989.  
  15990.          Rexx Language Organisation 
  15991.           Links to rexx sites and other interested info, available at 
  15992.           http://www.rexxla.org/ 
  15993.  
  15994.          TCP-IP (RxSock) Tutorial 
  15995.           A good short tutorial on using sockets (URL checking etc) is 
  15996.           available at http://www2.hursley.ibm.com/rexxtut/socktut1.htm 
  15997.  
  15998.  
  15999. ΓòÉΓòÉΓòÉ 13. PPWIZARD Extensions ΓòÉΓòÉΓòÉ
  16000.  
  16001. PPWIZARD Extensions 
  16002.  
  16003. You may not wish to use some of these headers but it would pay you to look at 
  16004. them purely from the point of view of examples. 
  16005.  
  16006.  
  16007. ΓòÉΓòÉΓòÉ 13.1. VALRURL.H - Remote Resource Validation ΓòÉΓòÉΓòÉ
  16008.  
  16009. VALRURL.H - Remote Resource Validation 
  16010.  
  16011. This section describes how PPWIZARD can be used to validate remote resources, 
  16012. by remote I mean any resource that you could not determine if it existed or not 
  16013. purely by examining the local machines environment. 
  16014.  
  16015. The header file "VALRURL.H" can be used to validate ftp and http URLs on remote 
  16016. servers. This will for example warn you if a particular link would generate a 
  16017. 404 in a browser. 
  16018.  
  16019. Currently the header works under OS/2, http (web page) validation may work as 
  16020. is under Windows (95/98/NT) or may require small changes. If you have another 
  16021. operating system you may still wish to examine the header file as only minor 
  16022. work would probably be required to get it to work if you already have a method 
  16023. to validate a URL. 
  16024.  
  16025. EXAMPLE - Immediate Validation 
  16026.  
  16027. This example is not real life in that the URLs would normally not be used on 
  16028. their own but would be part of a hypertext link. You are expected to be online 
  16029. (to the internet) at the time you try the example as the URL checking is done 
  16030. immediately after a otherwise successful build. The example also demonstates 
  16031. setting up debugging: 
  16032.  
  16033.     ;--- Load external URL validation support ---
  16034.     ;;#define  VALRURL_NO_CHECK_HTTP
  16035.     ;;#define  VALRURL_NO_CHECK_FTP
  16036.     #define  VALRURL_FTP_EMAIL       db0@anz.com
  16037.     #define  VALRURL_DEBUG           +out\DEBUG.URL\*.DBG    ;;Append to end of any existing debug file
  16038.     #include "VALRURL.H"
  16039.  
  16040.     ;--- Check some HTTP URLS ---
  16041.     <$RemHttp url="http://anz.com">                                     ;;Does not exist
  16042.     <$RemHttp url="http://www.labyrinth.net.au/~dbareis/ppwizard.htm">  ;;Exists
  16043.     <$RemHttp url="http://www.labyrinth.net.au/~dbareis/zips_fw">       ;;Needs a '/'
  16044.     <$RemHttp url="http://www.labyrinth.net.au/~dbareis/no_such.htm">   ;;Does not exist
  16045.  
  16046.     ;--- Check some FTP URLS ---
  16047.     <$RemFtp  url="ftp://ftp.anz.com">                                  ;;Does not exist
  16048.     <$RemFtp  url="ftp://ftp.pc.ibm.com/pub/pccbbs/os2_ews">            ;;Directory
  16049.     <$RemFtp  url="ftp://ftp.pc.ibm.com/pub/pccbbs/os2_ews/aping.txt">  ;;File
  16050.  
  16051. EXAMPLE - Delayed Validation 
  16052.  
  16053. This example is more real life. It also creates a URL list so that you don't 
  16054. need to be online when the html is built. You can run the generated URL files 
  16055. through the validator (supplied with ppwizard for OS/2 - http may work under 
  16056. windows) whenever you wish. 
  16057.  
  16058. It shows one possible way of defining a common header file containing a useful 
  16059. front end macro as well as the definition of a remote URL. As the URL is only 
  16060. mentioned in one place no matter where or how many times it appears on your web 
  16061. pages it is simple to fix if it becomes out of date. 
  16062.  
  16063. The common header file "MyCommon.IH" follows: 
  16064.  
  16065.     ;--- Load external URL validation support -----------
  16066.     #define  VALRURL_FTP_EMAIL         db0@anz.com
  16067.     #define  VALRURL_CHECK_LATER_MASK  out\REMOTE.URL\*.URL
  16068.     #include "VALRURL.H"
  16069.  
  16070.     ;--- Useful macro: Validate URL and generate link ---
  16071.     #define InternetLink                         \
  16072.             <A HREF="<$RemHttp URL=^{$URL}^>">  -\
  16073.                {$VISIBLE=^{$URL}^}              -\
  16074.             </A>
  16075.  
  16076.     ;--- Define URLs (usually in common header file -----
  16077.     #define HttpPpwizardHomePage   \
  16078.             http://www.labyrinth.net.au/~dbareis/ppwizard.htm
  16079.  
  16080. What might appear in one of your pages follows: 
  16081.  
  16082.     ;--- Load common header file ---
  16083.     #include "MyCommon.IH"
  16084.  
  16085.     ;--- Check some HTTP URLS ------
  16086.     <P>Please see my <$InternetLink URL="<$HttpPpwizardHomePage>">
  16087.     for a great
  16088.     <$InternetLink URL="<$HttpPpwizardHomePage>" VISIBLE=^preprocessor^>.
  16089.  
  16090. At some future stage when you are online to the internet you might start the 
  16091. validation process with a command similar to: 
  16092.  
  16093.     checkurl.cmd CheckListedUrls remote.url\*.URL
  16094.  
  16095. VALRURL.H 
  16096.  
  16097. ;----------------------------------------------------------------------------
  16098. ;     MODULE NAME:   VALRURL.IH
  16099. ;
  16100. ;         $Author:   USER "Dennis"  $
  16101. ;       $Revision:   1.2  $
  16102. ;           $Date:   26 Sep 2001 18:51:34  $
  16103. ;        $Logfile:   C:/DBAREIS/Projects.PVCS/MultiOs/PPWIZARD/valrurl.h.pvcs  $
  16104. ;
  16105. ;     DESCRIPTION:   This is a header file for checking HTTP/FTP urls on
  16106. ;                    remote servers. All URLs are passed with a leading
  16107. ;                    "http://' or "ftp://".
  16108. ;
  16109. ;                    This routine does not validate that any "#Section"
  16110. ;                    on http URLs are correct. It will validate that the
  16111. ;                    html page exists on the server.
  16112. ;
  16113. ;                    It will only check a URL once. This is the case even
  16114. ;                    across builds of multiple ".IT" files if they are being
  16115. ;                    built using the one call to PPWIZARD.
  16116. ;
  16117. ;                    Note that I don't search a table to work out if a URL
  16118. ;                    has already been used, my method is much faster however
  16119. ;                    on very long URLs which appear in multiple files in the
  16120. ;                    same PPWIZARD invokation it may repeat the test.
  16121. ;
  16122. ;
  16123. ;                    OPERATING SYSTEMS
  16124. ;                    ~~~~~~~~~~~~~~~~~
  16125. ;                    This header has only been tested under OS/2. The
  16126. ;                    required DLLs appear to have been installed by OS/2
  16127. ;                    version 4 (Merlin). If these are unavailable on your
  16128. ;                    machine you may need a TCP-IP fixpack, otherwise you
  16129. ;                    will need to locate a web page containing the files.
  16130. ;
  16131. ;                    Since there is a "RxSock.DLL" available for windows
  16132. ;                    http checking will also work there (if any changes
  16133. ;                    required please let me know the details).
  16134. ;                    There is no "RxFtp.DLL" for windows (that I know of).
  16135. ;
  16136. ;                    You can get RxSock for windows from:
  16137. ;
  16138. ;                                http://home.hiwaay.net/~abbott/regina/
  16139. ;
  16140. ;
  16141. ;                    COMMENTS
  16142. ;                    ~~~~~~~~
  16143. ;                    Error messages could be improved a bit!
  16144. ;
  16145. ;                    Not sure about all error handling, please let me know
  16146. ;                    of any issues you have. If you can see that I'm doing
  16147. ;                    something wrong, please tell me!
  16148. ;
  16149. ;
  16150. ;                    EXAMPLE
  16151. ;                    ~~~~~~~
  16152. ;                    ;;#define  VALRURL_NO_CHECK_HTTP
  16153. ;                    ;;#define  VALRURL_NO_CHECK_FTP
  16154. ;                    ;;#define  VALRURL_DEBUG            out\DEBUG.URL\*.DBG
  16155. ;                    #define    VALRURL_CHECK_LATER_MASK out\REMOTE.URL\*.URL
  16156. ;                    #define    VALRURL_FTP_EMAIL        db0@anz.com
  16157. ;                    #include "VALRURL.H"
  16158. ;
  16159. ;                    <P>Please see
  16160. ;                    <A HREF="<$RemHttp url="http://www.labyrinth.net.au/~dbareis/ppwizard.htm">">
  16161. ;                       PPWIZARD's homepage
  16162. ;                    </A>.
  16163. ;
  16164. ;                    You may wish to come up with your own set of "front end"
  16165. ;                    macros to simplify the above. Also in general I recommend
  16166. ;                    defining the external URL's in a header if they are to
  16167. ;                    be used in more than one place.
  16168. ;----------------------------------------------------------------------------
  16169.  
  16170.  
  16171. ;--- Initialization (for this compile) --------------------------------------
  16172. #ifdef  VALRURL_CHECK_LATER_MASK
  16173.         #DefineRexx ''
  16174.            ;--- Create URL file name based on input name ---
  16175.            UrlListFile = GenerateFileName('<?InputFile>', '<$VALRURL_CHECK_LATER_MASK>');
  16176.  
  16177.            ;--- Delete the file for starters, will get created if any URLs ---
  16178.            call stream UrlListFile, 'c', 'close';
  16179.            call _SysFileDelete UrlListFile;
  16180.         #DefineRexx
  16181. #endif
  16182.  
  16183.  
  16184. ;--- Only do rest of header once! -------------------------------------------
  16185. #ifndef VERSION_VALRURL_IH
  16186.    ;--- Define the version number of this header file -----------------------
  16187.    #define   VERSION_VALRURL_IH    01.266
  16188.    #require  99.315
  16189.  
  16190.    ;--- Need access to sort stuff ------------------------------------------
  16191.    #include "PPWSORT.H"
  16192.  
  16193.    ;--- Allow user to prevent generation if they only wish validation ------
  16194.    #ifndef RemHttpGenerate
  16195.        #define RemHttpGenerate      {$URL}
  16196.    #endif
  16197.    #ifndef RemFtpGenerate
  16198.        #define RemFtpGenerate       {$URL}
  16199.    #endif
  16200.  
  16201.    ;--- Allow user to modify what happens on failing validation ------------
  16202.    #ifndef VALRURL_FAILED_VALIDATION_REXX
  16203.            #DefineRexx VALRURL_FAILED_VALIDATION_REXX
  16204.                    call warning "CRURL", ThisUrl || ' ==> ' || UrlChkRc;
  16205.            #DefineRexx
  16206.    #endif
  16207.  
  16208.    ;--- Allow user to modify what happens on successful validation ---------
  16209.    #ifndef VALRURL_VALIDATED_OK_REXX
  16210.            ;--- Default is display success only when debug is on -----------
  16211.            #ifdef  VALRURL_DEBUG
  16212.                    ;--- Display successful URL as debug is on --------------
  16213.                    #DefineRexx VALRURL_VALIDATED_OK_REXX
  16214.                                call info 'DEBUG: ' || ThisUrl || ' successfully validated';
  16215.                    #DefineRexx
  16216.            #elseif
  16217.                    ;--- Define empty handler if debug is off ---------------
  16218.                    #define VALRURL_VALIDATED_OK_REXX
  16219.            #endif
  16220.    #endif
  16221.  
  16222.  
  16223.    ;--- Allow user to specify email address for FTP site logon -------------
  16224.    #ifndef VALRURL_FTP_EMAIL
  16225.            #define VALRURL_FTP_EMAIL VALRURL_<$VERSION_VALRURL_IH>@real.email.address.unknown
  16226.    #endif
  16227.  
  16228.    ;--- User calls these macros to perform validation ----------------------
  16229.    #define RemHttp                                                  \
  16230.            <$ValidateHttpR    URL="{$URL}">     ;;Check Remote URL -\
  16231.            <$RemHttpGenerate  URL="{$URL}">     ;;Generate URL
  16232.    #define RemFtp                                                   \
  16233.            <$ValidateFtpR     URL="{$URL}">     ;;Check Remote URL -\
  16234.            <$RemHttpGenerate  URL="{$URL}">     ;;Generate URL
  16235.  
  16236.    ;--- Checking HTTP:// ? -------------------------------------------------
  16237.    #ifdef  VALRURL_NO_CHECK_HTTP
  16238.            #define ValidateHttpR   ;;No checking
  16239.    #elseif
  16240.            #define ValidateHttpR   <$ValidateUrlR Type="http://" URL="{$URL}">
  16241.    #endif
  16242.  
  16243.  
  16244.    ;--- Checking FTP:// ? --------------------------------------------------
  16245.    #ifdef  VALRURL_NO_CHECK_FTP
  16246.            #define ValidateFtpR    ;;No checking
  16247.    #elseif
  16248.            #define ValidateFtpR    <$ValidateUrlR Type="ftp://" URL="{$URL}">
  16249.    #endif
  16250.  
  16251.    ;--- Initialization - Once per PPWIZARD Invokation (NOT build!) ---------
  16252.    #if symbol('UrlCheckerPgm') <> 'VAR'
  16253.        ;--- No need to do anything if delaying the checking! ---------------
  16254.        #ifndef VALRURL_CHECK_LATER_MASK
  16255.            #if Defined('VALRURL_NO_CHECK_HTTP') = 'N' | Defined('VALRURL_NO_CHECK_FTP') = 'N'
  16256.                ;--- Find External program ----------------------------------
  16257.                #define VALRURL_EXT_CMD   CHECKURL.CMD
  16258.                #evaluate ''                                                                                           \
  16259.                ^                                                                                                      \
  16260.                    UrlCheckerPgm = _SysSearchPath('PATH', '<$VALRURL_EXT_CMD>');                                      \
  16261.                    if  UrlCheckerPgm = '' then;                                                                       \
  16262.                    do;                                                                                                \
  16263.                        parse source . . PpwRexxFile;                                                                  \
  16264.                        UrlCheckerPgm = _filespec('location', PpwRexxFile) || '<$VALRURL_EXT_CMD>';                    \
  16265.                            if  stream(UrlCheckerPgm, 'c', 'query exists') = '' then;                                  \
  16266.                                Error('Could not locate "<$VALRURL_EXT_CMD>" (searched PATH and PPWIZARD directory)'); \
  16267.                    end;                                                                                               \
  16268.                ^
  16269.  
  16270.                ;--- Display version numbers of DLLs we are using -----------
  16271.                #evaluate '' ^interpret 'ExtCmdVersion = "<??UrlCheckerPgm>"("VERSION?")'^
  16272.                #info        'Header file version <$VERSION_VALRURL_IH>'
  16273.                #info        'Using Check URL external command <??ExtCmdVersion>'
  16274.                #ifndef  VALRURL_NO_CHECK_HTTP
  16275.                    #evaluate '' ^interpret 'SocketVersion = "<??UrlCheckerPgm>"("SOCKETVERSION?")'^
  16276.                    #info     'Validating remote http URLs with <??SocketVersion>'
  16277.                #endif
  16278.                #ifndef  VALRURL_NO_CHECK_FTP
  16279.                    #evaluate '' ^interpret 'FtpVersion    = "<??UrlCheckerPgm>"("FTPVERSION?")'^
  16280.                    #info     'Validating remote ftp  URLs with <??FtpVersion>'
  16281.                #endif
  16282.  
  16283.                ;--- Set email address for FTP downloads --------------------
  16284.                #ifndef  VALRURL_NO_CHECK_FTP
  16285.                    #evaluate '' ^call SetEnv "CHECKURL_EMAIL", "<$VALRURL_FTP_EMAIL>"^
  16286.                #endif
  16287.            #endif
  16288.        #endif
  16289.    #endif
  16290.  
  16291.    ;--- Set up debug? ----------------------------------------------
  16292.    #ifndef  VALRURL_DEBUG
  16293.        #evaluate '' ^call SetEnv "CHECKURL_DEBUG", ''^            ;;Prevent Debug
  16294.    #elseif
  16295.        #evaluate '' ^TDbgFile = GenerateFileName('<?InputFile>', '<$VALRURL_DEBUG>')^
  16296.        #evaluate '' ^call _SysFileDelete TDbgFile^
  16297.        #evaluate '' ^call SetEnv "CHECKURL_DEBUG", TDbgFile^      ;;Turn it on
  16298.        #info        'Any debugger output goes to "<??TDbgFile>"'
  16299.    #endif
  16300.  
  16301.    ;--- Make sure we have required support for this compile -----------------
  16302.    #ifndef VALRURL_CHECK_LATER_MASK
  16303.        #ifndef  VALRURL_NO_CHECK_HTTP
  16304.            #evaluate '' ^interpret 'SupportHttp = "<??UrlCheckerPgm>"("SOCKETREADY?")'^
  16305.            #if SupportHttp <> 'OK'
  16306.                ;--- Can't validate HTTP URLs -----------------------------------
  16307.                #Warning "CRURL"  "Can't validate HTTP URLs"
  16308.                #define+ RemHttp <$RemHttpGenerate  URL="{$URL}"> ;;Can't validate URL
  16309.            #endif
  16310.        #endif
  16311.        #ifndef  VALRURL_NO_CHECK_FTP
  16312.            #evaluate '' ^interpret 'SupportFtp  = "<??UrlCheckerPgm>"("FTPREADY?")'^
  16313.            #if SupportFtp <> 'OK'
  16314.                ;--- Can't validate FTP URLs -----------------------------------
  16315.                #Warning "CRURL"  "Can't validate FTP URLs"
  16316.                #define+ RemFtp <$RemFtpGenerate  URL="{$URL}">   ;;Can't validate URL
  16317.            #endif
  16318.        #endif
  16319.    #endif
  16320.  
  16321.    ;--- Initialization for this build ---------------------------------------
  16322.    #RexxVar ValUrlCount = 0            ;;Counts elements in URL array
  16323.    #OnExit  <$ProcessRemoteUrlList>    ;;Handle the list (user could override macro)
  16324.  
  16325.    ;--- Handle URL (just add to array, don't worry about duplicates here) ---
  16326.    #define ValidateUrlR                                                      \
  16327.            ;--- Make sure we validate a full URL -------------              -\
  16328.            #evaluate '' ^<$ValidateUrlR_REXX_FullUrl Type="{$Type}" URL="{$URL}">^  -\
  16329.                                                                             -\
  16330.            ;--- Add URL (in "FullUrl" var) to end of array ---              -\
  16331.            #RexxVar ValUrlCount + 1                                         -\
  16332.            #RexxVar ValUtlList.ValUrlCount = FullUrl                        -\
  16333.                                                                             -\
  16334.            ;--- Add location ---------------------------------              -\
  16335.            #evaluate '' ^<$ValidateUrlR_REXX_Location>^                     -\
  16336.            #RexxVar ValUtlLocn.ValUrlCount = UrlSourceLocation
  16337.    #DefineRexx ValidateUrlR_REXX_FullUrl
  16338.                ;--- Make sure URL starts with "http:" etc ---
  16339.                UrlType = "{$Type}";
  16340.                FullUrl = "{$URL}";
  16341.                if  abbrev(FullUrl, UrlType) = 0 then;
  16342.                    FullUrl = UrlType || FullUrl;
  16343.  
  16344.                ;--- Remove any "#section" bit ---
  16345.                #Option PUSH AllowPack=NO
  16346.                parse var FullUrl (UrlType) httpServer '/' HttpPageAddr;
  16347.                #Option POP
  16348.                parse var HttpPageAddr HttpPageAddr '#';
  16349.                FullUrl = UrlType || httpServer || '/' || HttpPageAddr;
  16350.    #DefineRexx
  16351.    #ifndef ValidateUrlR_REXX_Location              ;;Allow caller to create their own "location"
  16352.        #DefineRexx ValidateUrlR_REXX_Location
  16353.                    #Option PUSH AllowPack=NO
  16354.                    do  IncIndex = 1 to <?IncludeLevel>
  16355.                    #Option POP
  16356.                        ;--- Format the input file at this level ---
  16357.                        ThisBit = _filespec('name', InputComponentLevel(IncIndex));
  16358.                        ThisBit = ThisBit || '(' || AddCommasToDecimalNumber(InputComponentLineLevel(IncIndex)) || ')';
  16359.  
  16360.                        ;--- Update location string ----------------
  16361.                        if  IncIndex = 1 then
  16362.                            UrlSourceLocation = ThisBit;
  16363.                        else
  16364.                            UrlSourceLocation = UrlSourceLocation || '->' || ThisBit;
  16365.                    end
  16366.        #DefineRexx
  16367.    #endif
  16368.  
  16369.    ;--- Work though URL list and end of successful build --------------------
  16370.    #define ProcessRemoteUrlList                                \
  16371.            #if [ValUrlCount = 0]                              -\
  16372.                #info 'No remote URLs to validate'             -\
  16373.            #elseif                                            -\
  16374.                #info 'Validating <??ValUrlCount> remote URLs' -\
  16375.                ;--- Sort the array ---                        -\
  16376.                #RexxVar ValUtlList.0 = ValUrlCount            -\
  16377.                #evaluate '' ^<$GenRexx2Sort2Arrays ARRAY1='ValUtlList' ARRAY2='ValUtlLocn'>^ -\
  16378.                                                               -\
  16379.                ;--- Process the array ---                     -\
  16380.                #evaluate '' ^<$ProcessRemoteUrlList_REXX>^    -\
  16381.            #endif
  16382.    #DefineRexx ProcessRemoteUrlList_REXX_COMMON_START
  16383.            ;--- Work through URL list (drop duplicates) ---
  16384.            LastUrl = '';
  16385.            LastLoc = '';
  16386.            do  UrlIndex = 1 to ValUtlList.0
  16387.                ThisUrl = ValUtlList.UrlIndex;
  16388.                ThisLoc = ValUtlLocn.UrlIndex;
  16389.                if  ThisUrl <> LastUrl | ThisLoc <> LastLoc then;
  16390.                do
  16391.    #DefineRexx
  16392.    #DefineRexx ProcessRemoteUrlList_REXX_COMMON_END
  16393.                    LastUrl = ThisUrl;
  16394.                    LastLoc = ThisLoc;
  16395.                end;
  16396.            end;
  16397.    #DefineRexx
  16398.  
  16399.    ;--- What are we doing with the list of URLs? ----------------------------
  16400.    #ifndef ProcessRemoteUrlList_REXX
  16401.        #ifdef  VALRURL_CHECK_LATER_MASK
  16402.            ;--- Generate file (user will check URLs later / when online) ----
  16403.            #DefineRexx ProcessRemoteUrlList_REXX
  16404.                    ;--- We already know URL filename & its been deleted ---
  16405.                    #ifndef VALRURL_DONT_DEPEND_ON_GENERATED_URL_LIST
  16406.                            call AddOutputFileToDependancyList UrlListFile;
  16407.                    #endif
  16408.                    call Info 'Generating: ' || UrlListFile;
  16409.                    call lineout UrlListFile, ';---';
  16410.                    call lineout UrlListFile, ';--- Remote URLs from "<?InputFile>"';
  16411.                    call lineout UrlListFile, ';--- Use CHECKURL.CMD under OS/2 or other similar';
  16412.                    call lineout UrlListFile, ';--- tool to process the list.';
  16413.                    call lineout UrlListFile, ';---';
  16414.                    call lineout UrlListFile, '';
  16415.                    call lineout UrlListFile, '';
  16416.  
  16417.                    ;--- Now work through the list of URLs ---
  16418.                    <$ProcessRemoteUrlList_REXX_COMMON_START>;
  16419.                        ;--- Need to output new location pragma? ---
  16420.                        if  ThisLoc <> LastLoc then
  16421.                            call lineout UrlListFile, ';PRAGMA(URL_SOURCE)=' || ThisLoc;
  16422.  
  16423.                        call lineout UrlListFile, ThisUrl;
  16424.                    <$ProcessRemoteUrlList_REXX_COMMON_END>;
  16425.  
  16426.                    ;--- Close the listing file ---
  16427.                    call DieIfIoErrorOccurred UrlListFile;
  16428.                    CloseRc = stream(UrlListFile, 'c', 'close');
  16429.            #DefineRexx
  16430.        #elseif
  16431.            ;--- We are online, do immediate check of URLs -------------------
  16432.            #DefineRexx ProcessRemoteUrlList_REXX
  16433.                    <$ProcessRemoteUrlList_REXX_COMMON_START>;
  16434.                        ;--- Calculate ID for this URL ---
  16435.                        FullPageId     = '!R_' || c2x(ThisUrl);
  16436.                        FullPageIdStat = symbol(FullPageId);    ;;Exists/Name too long?
  16437.  
  16438.                        ;--- Already done this URL (previous build)? ---
  16439.                        if  FullPageIdStat = 'VAR' then;
  16440.                            UrlChkRc = _valueG(FullPageId);   ;;Already know if valid!
  16441.                        else;
  16442.                        do;
  16443.                            ;--- Haven't checked yet ---
  16444.                            interpret 'UrlChkRc = "<??UrlCheckerPgm>"("CHECK1URL " || ThisUrl)';
  16445.  
  16446.                            ;--- Set ID so we won't repeat this exercise! ---
  16447.                            if  FullPageIdStat <> 'BAD' then;
  16448.                                call _valueS FullPageId, UrlChkRc;
  16449.                        end;
  16450.  
  16451.                        ;--- Handle return code ---
  16452.                        if  UrlChkRc = 'OK' then;
  16453.                        do;
  16454.                            <$VALRURL_VALIDATED_OK_REXX>;
  16455.                        end;
  16456.                        else;
  16457.                        do;
  16458.                            <$VALRURL_FAILED_VALIDATION_REXX>;
  16459.                        end;
  16460.                    <$ProcessRemoteUrlList_REXX_COMMON_END>;
  16461.            #DefineRexx
  16462.        #endif
  16463.    #endif
  16464.  
  16465. #endif
  16466.  
  16467.  
  16468.  
  16469. ΓòÉΓòÉΓòÉ 13.2. PPWSORT.H - Sorting ΓòÉΓòÉΓòÉ
  16470.  
  16471. PPWSORT.H - Sorting 
  16472.  
  16473. PPWIZARD has an internal sort routine called ArraySort(), where possible it is 
  16474. recommended that it be used however the header file has the following 
  16475. advantages: 
  16476.  
  16477.        1. You can generate sort code inline when generating Rexx code 
  16478.           (PPWIZARD's internal code will not be available when the generated 
  16479.           code executes!). 
  16480.  
  16481.        2. You can sort more than one array at a time, this allows you to keep 
  16482.           associated information together. 
  16483.  
  16484.        3. The compare operation can be as complex as you wish. 
  16485.  
  16486.        4. If you wish to sort an array with a known name (probably usual thing 
  16487.           in PPWIZARD code) and there are many entries in the array then the 
  16488.           sort can be much faster. 
  16489.  
  16490.  There are two generic macros you can choose from, "ArraySort" generates a 
  16491.  PPWIZARD #evaluate command to perform the sort and "GenRexx2Sort" which 
  16492.  generates the rexx code. 
  16493.  
  16494.  The first element in the array(s) is element 1 (not 0). 
  16495.  
  16496.  The Generic Macro Parameters 
  16497.  
  16498.        1. COUNT 
  16499.           This is used to supply the number of elements that you are sorting. 
  16500.  
  16501.        2. PREFIX 
  16502.           By default the all variables used in the generated sort code are 
  16503.           prefixed by "Srt" this parameter gives you the chance to remove any 
  16504.           conflicts you may have (you may already have your own variables that 
  16505.           begin with "Srt"). 
  16506.  
  16507.        3. GREATER 
  16508.           You need to supply the rexx code which sets the "SrtGreater" variable 
  16509.           to "1" if the first element is greater than the second or '0' 
  16510.           otherwise. If the name of the array can't be hard coded (its name is 
  16511.           held in a variable), the rexx value() routine will need to be used 
  16512.           for all variable accesses. 
  16513.  
  16514.        4. SWAP 
  16515.           You need to supply the rexx code which swaps elements. 
  16516.  
  16517.  The last two macro parameters will need to use the "SrtIndex1" and "SrtIndex2" 
  16518.  variables (using default prefix!) which hold the indexes of the elements to be 
  16519.  compared or swapped. 
  16520.  
  16521.  Some Non-Generic macros 
  16522.  
  16523.  While the generic macros above are very powerful (you can do anything after 
  16524.  all) most people will probably never use them and use the macros described 
  16525.  below (some of the same generic macro parameters are supported). 
  16526.  
  16527.  There are 2 macros which you can use to sort either 1 or 2 arrays (whose names 
  16528.  are known - fixed). The default is that the ".0" element holds the number of 
  16529.  items in the array and the sort is ascending. The macros are 
  16530.  "GenRexx2Sort1Array" and "GenRexx2Sort2Arrays". With the 2 array sort macro 
  16531.  the first array is sorted and the 2nd array is assumed to hold associated 
  16532.  data. 
  16533.  
  16534.  There is one macros which you can use to sort a single array whose name is 
  16535.  only known at runtime (not fixed), its name is "GenRexx2Sort1ArrayIndirect". 
  16536.  
  16537.  EXAMPLES 
  16538.  
  16539.  This example shows the named array "Fred" being sorted: 
  16540.  
  16541.          <$GenRexx2Sort1Array ARRAY="Fred">;
  16542.  
  16543.  This time we want the first 4 items sorted in decending order: 
  16544.  
  16545.          <$GenRexx2Sort1Array ARRAY="Fred" Compare="<" Count="4">;
  16546.  
  16547.  We want a "ArraySort" routine in our generated rexx code: 
  16548.  
  16549.          ...
  16550.          call ArraySort "fred";
  16551.          return;
  16552.          ...
  16553.          ...
  16554.          /*==========*/
  16555.          ArraySort:
  16556.          /*==========*/
  16557.              ArrayNamedIn = translate(arg(1));  ;;Holds name of array
  16558.  
  16559.              <$GenRexx2Sort1ArrayIndirect NamedIn="ArrayNamedIn">;
  16560.              return;
  16561.  
  16562.  PPWSORT.H 
  16563.  
  16564.   ;----------------------------------------------------------------------------
  16565.   ;     MODULE NAME:   PPWSORT.H
  16566.   ;
  16567.   ;         $Author:   USER "Dennis"  $
  16568.   ;       $Revision:   1.0  $
  16569.   ;           $Date:   30 Mar 2001 18:05:30  $
  16570.   ;        $Logfile:   C:/DBAREIS/Projects.PVCS/MultiOs/PPWIZARD/ppwsort.h.pvcs  $
  16571.   ;
  16572.   ;     DESCRIPTION:   PPWIZARD has a "ArraySort()" routine which can be used
  16573.   ;                    to sort a single array.  It does have some flexability
  16574.   ;                    in how it compares entries.
  16575.   ;
  16576.   ;                    This header file would be used to handle sort
  16577.   ;                    requirements that are not possible using "ArraySort()".
  16578.   ;
  16579.   ;                    This header allows you to:
  16580.   ;
  16581.   ;                         * Imbed the sort routine between PPWIZARD commands.
  16582.   ;
  16583.   ;                         * Imbed the sort routine between rexx     commands.
  16584.   ;
  16585.   ;                         * Sort more than one array at a time, for example
  16586.   ;                           you may have multiple arrays storing associated
  16587.   ;                           information that should all be sorted together.
  16588.   ;
  16589.   ;                         * Do any sort of compare, no matter how complex.
  16590.   ;
  16591.   ;
  16592.   ;                     EXAMPLE1 - Inline Rexx code (use "SortArray" for inline
  16593.   ;                                PPWIZARD code). Array 'A' is being sorted.
  16594.   ;                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  16595.   ;                     ArrayName = arg(1);      ;;Caller passed "A"
  16596.   ;                     <$GenRexx2Sort                                                                                      \
  16597.   ;                          COUNT=^_valueG(ArrayName || '.0')^                                                             \
  16598.   ;                        GREATER=^SrtGreater = _valueG(ArrayName || '.SrtIndex1') >> _valueG(ArrayName || '.SrtIndex2')^  \
  16599.   ;                           SWAP=^SrtTemp = _valueG(ArrayName || '.SrtIndex1');                                          -\
  16600.   ;                                 call _valueS ArrayName || '.SrtIndex1', _valueG(ArrayName || '.SrtIndex2');            -\
  16601.   ;                                 call _valueS ArrayName || '.SrtIndex2', SrtTemp                                        -\
  16602.   ;                                ^                                                                                       -\
  16603.   ;                     >
  16604.   ;
  16605.   ;                     Note ">>" being used in the compare, if the data being
  16606.   ;                     sorted is numeric use '>' instead (or else)!!!!!!
  16607.   ;
  16608.   ;                     EXAMPLE2 - Exactly same as Example 1
  16609.   ;                                hardcoded - can't handle other arrays).
  16610.   ;                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  16611.   ;                     ArrayName = translate(arg(1));      ;;Caller passed "A" (handle possible value() bug!)
  16612.   ;                     <$GenRexx2Sort1ArrayIndirect NamedIn="ArrayName">
  16613.   ;
  16614.   ;                     EXAMPLE3 - In this case the name of the array ("A" is
  16615.   ;                                hardcoded - can't handle other arrays).
  16616.   ;                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  16617.   ;                     <$GenRexx2Sort1Array ARRAY="A">
  16618.   ;
  16619.   ;----------------------------------------------------------------------------
  16620.  
  16621.  
  16622.   ;--- Only include once ------------------------------------------------------
  16623.   #ifndef VERSION_PPWSORT_H
  16624.  
  16625.  
  16626.   ;--- Define the version number of this header file --------------------------
  16627.   #define   VERSION_PPWSORT_H    99.269
  16628.   #require  99.269
  16629.  
  16630.  
  16631.   ;--- For use within PPWIZARD for immediate sorting of array (PPWIZARD Command!) ---
  16632.   #define SortArray    \
  16633.           #evaluate '' ^<$GenRexx2Sort COUNT={$COUNT} GREATER={$GREATER} SWAP={$SWAP}>^
  16634.  
  16635.   ;--- Generates the rexx code to perform sorting (sort one "NAMED" array) ----
  16636.   #define GenRexx2Sort1Array                                        \
  16637.           <$GenRexx2Sort                                            \
  16638.                COUNT=^{$Count="{$Array}.0"}^                        \
  16639.               PREFIX=^{$Prefix="Srt"}^                              \
  16640.              GREATER=^SrtGreater = {$Array}.SrtIndex1 {$Compare=">"} {$Array}.SrtIndex2^  \
  16641.                 SWAP=^SrtTemp = {$Array}.SrtIndex1;                -\
  16642.                       {$Array}.SrtIndex1 = {$Array}.SrtIndex2;     -\
  16643.                       {$Array}.SrtIndex2 = SrtTemp                 -\
  16644.                      ^                                             -\
  16645.           >
  16646.  
  16647.   ;--- Generates the rexx code to perform sorting (sort 2 "NAMED" arrays) -----
  16648.   #define GenRexx2Sort2Arrays                                                    \
  16649.           <$GenRexx2Sort                                                         \
  16650.                COUNT=^{$Count="{$Array1}.0"}^                                    \
  16651.               PREFIX=^{$Prefix="Srt"}^                                           \
  16652.              GREATER=^{$Prefix}Greater = {$Array1}.{$Prefix}Index1 {$Compare=">"} {$Array1}.{$Prefix}Index2^ \
  16653.                 SWAP=^{$Prefix}Temp = {$Array1}.{$Prefix}Index1;                -\
  16654.                       {$Array1}.{$Prefix}Index1 = {$Array1}.{$Prefix}Index2;    -\
  16655.                       {$Array1}.{$Prefix}Index2 = {$Prefix}Temp;                -\
  16656.                       {$Prefix}Temp = {$Array2}.{$Prefix}Index1;                -\
  16657.                       {$Array2}.{$Prefix}Index1 = {$Array2}.{$Prefix}Index2;    -\
  16658.                       {$Array2}.{$Prefix}Index2 = {$Prefix}Temp                 -\
  16659.                      ^                                                          -\
  16660.           >
  16661.  
  16662.  
  16663.   ;--- Generates the rexx code to perform sorting (array name not hard coded) -
  16664.   #define GenRexx2Sort1ArrayIndirect                                                                             \
  16665.           <$GenRexx2Sort                                                                                         \
  16666.                COUNT=^{$Count="_valueG({$NamedIn} || '.0')"}^                                                    \
  16667.               PREFIX=^{$Prefix="SRT"}^                                                                           \
  16668.              GREATER=^{$Prefix}Greater = _valueG({$NamedIn} || '.{$Prefix}INDEX1') {$Compare=">"} _valueG({$NamedIn} || '.{$Prefix}INDEX2')^  \
  16669.                 SWAP=^{$Prefix}Temp = _valueG({$NamedIn} || '.{$Prefix}INDEX1');                                -\
  16670.                       call _valueS {$NamedIn} || '.{$Prefix}INDEX1', _valueG({$NamedIn} || '.{$Prefix}INDEX2'); -\
  16671.                       call _valueS {$NamedIn} || '.{$Prefix}INDEX2', {$Prefix}Temp                              -\
  16672.                      ^                                                                                          -\
  16673.           >
  16674.  
  16675.   ;--- Generates the rexx code to perform sorting (GENERIC) -------------------
  16676.   #DefineRexx GenRexx2Sort
  16677.              {$Prefix="SRT"}M = 1
  16678.              {$Prefix}Count   = {$COUNT};
  16679.              do  while (9 * {$Prefix}M + 4) < {$Prefix}Count
  16680.                  {$Prefix}M = {$Prefix}M * 3 + 1
  16681.              end /* do while */
  16682.              do  while {$Prefix}M > 0
  16683.                  {$Prefix}K = {$Prefix}Count - {$Prefix}M
  16684.                  do  {$Prefix}J = 1 to {$Prefix}K
  16685.                      {$Prefix}Index1 = {$Prefix}J
  16686.                      do while {$Prefix}Index1 > 0
  16687.                          ;--- Work out what to compare it with ----------------
  16688.                          {$Prefix}Index2 = {$Prefix}Index1 + {$Prefix}M;
  16689.  
  16690.                          ;--- User user supplied logic to check for greater ---
  16691.                          {$Greater};
  16692.  
  16693.                          ;--- Swap if required --------------------------------
  16694.                          if {$Prefix}Greater then
  16695.                          do
  16696.                              {$Swap};
  16697.                          end;
  16698.                          else
  16699.                              leave;
  16700.  
  16701.                          ;--- Prepare for the next loop -----------------------
  16702.                          {$Prefix}Index1 = {$Prefix}Index1 - {$Prefix}M
  16703.  
  16704.                      end /* do while {$Prefix}Index1 > 0 */
  16705.                  end     /* do {$Prefix}J = 1 to {$Prefix}K */
  16706.                  {$Prefix}M = {$Prefix}M % 3
  16707.              end         /* while {$Prefix}M > 0 */
  16708.   #DefineRexx
  16709.  
  16710.  
  16711.  
  16712.  
  16713.   #ifdef   CommentBlock  /* (Saturday 07/08/1999, 20:32:20, by Dennis_Bareis) */
  16714.   **+--------------------------------------------------------------------------
  16715.   **|;--- Generates the rexx code to perform sorting (GENERIC) -------------------
  16716.   **|#DefineRexx GenRexx2Sort
  16717.   **|        {$Prefix="Srt"}Count    = {$COUNT};
  16718.   **|        {$Prefix}Distance = {$Prefix}Count % 2;
  16719.   **|        do  while {$Prefix}Distance > 0
  16720.   **|            do  until {$Prefix}Finished;      /* start of mini-bubblesort loop */
  16721.   **|                {$Prefix}Finished = 1;
  16722.   **|                do  {$Prefix}Index1 = 1 to {$Prefix}Count - {$Prefix}Distance
  16723.   **|                    ;--- We now compare and swap items {$Prefix}Index1 and {$Prefix}Index1+{$Prefix}Distance ---
  16724.   **|                    {$Prefix}Index2 = {$Prefix}Index1 + {$Prefix}Distance;
  16725.   **|
  16726.   **|                    ;--- User user supplied logic to check for greater ---
  16727.   **|                    {$GREATER};
  16728.   **|
  16729.   **|                    ;--- Swap if required --------------------------------
  16730.   **|                    if {$Prefix}Greater then
  16731.   **|                    do
  16732.   **|                        ;--- User user supplied logic to swap items ------
  16733.   **|                        {$Swap};
  16734.   **|                        {$Prefix}Finished = 0;
  16735.   **|                    end;
  16736.   **|                end;
  16737.   **|            end;                       /* end of mini-bubblesort loop */
  16738.   **|            {$Prefix}Distance = {$Prefix}Distance % 2;
  16739.   **|        end;
  16740.   **|#DefineRexx
  16741.   **+--------------------------------------------------------------------------
  16742.   #endif                 /* (Saturday 07/08/1999, 20:32:20, by Dennis_Bareis) */
  16743.  
  16744.  
  16745.   #endif
  16746.  
  16747.  
  16748.  
  16749.  
  16750.  
  16751.  
  16752. ΓòÉΓòÉΓòÉ 14. Performance ΓòÉΓòÉΓòÉ
  16753.  
  16754. Performance 
  16755.  
  16756. While PPWIZARD is written in rexx a lot of work has gone into keeping it fast. 
  16757. It has a lot of features and I'll probably add more.  In general I have added 
  16758. these with no loss of performance (in fact I've generally gained as I've 
  16759. rewritten parts to add new functionality). 
  16760.  
  16761. As PPWIZARD is so powerful you will be tempted to do some very complex things, 
  16762. much like I have in writing the document you are now reading in PPWIZARD 
  16763. macros.  This section aims to give you some hints as to what you can do to 
  16764. speed up processing (if you need to). 
  16765.  
  16766. Macro Performance 
  16767.  
  16768.        1. Macro performance is not affected by the number of macros you create. 
  16769.  
  16770.        2. Macro performance is not affected by the length of a definition's 
  16771.           name. 
  16772.  
  16773.        3. The #evaluate & #if commands are very slow (on a Pentium 100 you can 
  16774.           do about 380/second). If you have large numbers of these in your 
  16775.           source then where possible use the #define or #RexxVar command in 
  16776.           place of "#evaluate". The #if [] form is very quick and should be 
  16777.           used where possible. Better yet for complex logic consider using 
  16778.           straight rexx code, possibly defined using #DefineRexx, this allows 
  16779.           you to use rexx's "select" etc and rapidly perform complex logic. 
  16780.  
  16781.        4. Keep the macros as short as possible (particularly the line count). 
  16782.  
  16783.        5. Don't include conditional logic where possible. For example if you 
  16784.           know at macro definition time that you will never follow a certain 
  16785.           path then don't include it (that is conditionally generate the macro 
  16786.           once). Not only will the line count decrease but a #if command is one 
  16787.           of the slower ones. Another benefit is that it's easier to watch what 
  16788.           is going on when debug mode is on. 
  16789.  
  16790.        6. In a similar vein to the previous point, if you have to pass a 
  16791.           parameter to a macro to conditionally execute a certain path, then it 
  16792.           would be better to create multiple variations of the macro and drop 
  16793.           the parameter and conditional generation code. 
  16794.  
  16795.        7. To make code easier to understand I usually do one rexx task per 
  16796.           #evaluate, however as an evaluate is slow you could bunch a number of 
  16797.           rexx commands in one #evaluate command (at least in any of your high 
  16798.           use macros). The #DefineRexx command can be used to define a whole 
  16799.           series of rexx statements in an easy to read/understand way. 
  16800.  
  16801.        8. You have the choice of storing information in a macro or rexx 
  16802.           variable.  Look at your main uses for the variable and decide which 
  16803.           is best for each situation.  If you are doing heaps of rexx 
  16804.           manipulations or tests (#if etc) then it would normally be better as 
  16805.           a rexx variable. 
  16806.  
  16807.        9. You can save steps in a macro by using "<??RexxVariable>" to get 
  16808.           access to a rexx variable without first having to get a copy with 
  16809.           #evaluate. 
  16810.  
  16811.       10. You can use "#define+" & "#evaluate+" instead of #undef. 
  16812.  
  16813.       11. For simple text macros you might want to consider using rexx 
  16814.           variables. Depending on how you use the information using rexx 
  16815.           variables can be much faster, for example in a #if or #evaluate 
  16816.           statement you can remove the need for the substitution syntax and use 
  16817.           the value directly. Where you do need to specify substitution use the 
  16818.           <??RexxVariable> syntax. 
  16819.  
  16820.  #AutoTag Performance 
  16821.  
  16822.        1. Unlike macros, the more autotags you have defined the slower it will 
  16823.           be to tag each line. 
  16824.  
  16825.        2. Replacing autotags (defined with #AutoTag) are slow. Only use if no 
  16826.           other way and for as few lines as possible. 
  16827.  
  16828.        3. To temporarily reduce your autotag count (remove ones you don't need) 
  16829.           you can use the #AutoTagState to hide current definitions before 
  16830.           creating your own command. Making good use of named states will 
  16831.           simplify this process. 
  16832.  
  16833.  #AsIs Performance 
  16834.  
  16835.        1. Unlike macros, the more changes you have defined the slower it will 
  16836.           be to tag each line. 
  16837.  
  16838.        2. There is inbuilt optimization for single character "from" text, if 
  16839.           possible  group these together. This allows the BulkChar2String() 
  16840.           routine to be used to greater effect. Tagging must take place in the 
  16841.           order you specify so PPWIZARD does not reorder the items to improve 
  16842.           performance. 
  16843.  
  16844.  Other Performance Hints 
  16845.  
  16846.        1. This may be obvious but PPWIZARD is CPU bound. What this means is the 
  16847.           speed of the CPU is directly proportional with the time PPWIZARD 
  16848.           takes. If your CPU is twice as fast PPWIZARD will take half the time. 
  16849.           Do yourself a favor and use the fastest machine you can find. 
  16850.  
  16851.        2. Under OS/2 you have multiple choices as to which rexx interpreter you 
  16852.           can use (DOS has 2 as well). There is the REGINA version as well as 
  16853.           traditional rexx (as exists after OS/2 install) or Object Orientated 
  16854.           Rexx. If you find things a bit slow it is probably worth your while 
  16855.           experimenting. Different interpreters will do some things better than 
  16856.           others. You really need to time your particular situation. 
  16857.  
  16858.        3. For common headers etc it may be better if they were not on a network 
  16859.           drive. Better yet a RAM disk would be good. Maybe increasing your 
  16860.           hard disk cache size could improve things. 
  16861.  
  16862.        4. You might wish to try the /Inc2Cache switch. 
  16863.  
  16864.        5. You might wish to try PPWSORT.H macros rather than ArraySort(). 
  16865.  
  16866.        6. Ppwizard is optimised for fast execution with debug turned off, and 
  16867.           in fact may perform extra work when debug is on (on the assumption 
  16868.           that execution time is not an issue). So for high performance turn 
  16869.           debug off! 
  16870.  
  16871.  
  16872. ΓòÉΓòÉΓòÉ 15. e-Zine! Articles ΓòÉΓòÉΓòÉ
  16873.  
  16874. e-Zine! Articles 
  16875.  
  16876. The e-Zine! magazine (http://www.os2ezine.com) as well as the OS/2 Supersite 
  16877. (http://www.os2ss.com/) both use this preprocessor. 
  16878.  
  16879. Chris Wenham (the Senior Editor of OS/2 e-Zine! chris@os2ezine.com) has written 
  16880. a series of articles for e-Zine! which he has allowed me to include in my 
  16881. documentation. 
  16882.  
  16883. The following articles are available: 
  16884.  
  16885.        1. http://www.os2ezine.com/v3n05/htmlpp1.htm 
  16886.  
  16887.        2. http://www.os2ezine.com/v3n06/htmlpp.htm 
  16888.  
  16889.        3. http://www.os2ezine.com/v3n12/dyn3.htm 
  16890.  
  16891.        4. http://www.os2ezine.com/v3n14/dws.htm 
  16892.  
  16893.        5. http://www.os2ezine.com/v4n3/dws.htm 
  16894.  
  16895.  
  16896. ΓòÉΓòÉΓòÉ 16. Examples / Tips ΓòÉΓòÉΓòÉ
  16897.  
  16898. Examples / Tips 
  16899.  
  16900. As well as the many examples that follow, you should also have a look at the 
  16901. PPWIZARD Extensions section as it contains many header files that make 
  16902. excellent examples. 
  16903.  
  16904.  
  16905. ΓòÉΓòÉΓòÉ 16.1. A Macro Which Expands Another ΓòÉΓòÉΓòÉ
  16906.  
  16907. A Macro Which Expands Another 
  16908.  
  16909. Sometimes you wish to delay the expansion of a macro. This might be so that you 
  16910. can display a symbols name as well as refer to it's value. 
  16911.  
  16912. The following is a very simple macro which expands a macro whose name is 
  16913. passed: 
  16914.  
  16915.     ;--- Expands a macro (macros name is passed) ---
  16916.     #define ExpandMacro <${$#1}>
  16917.  
  16918. The following macro makes use of the above macro to display the color name in a 
  16919. "C" style comment as well as expanding the color into the integer some 
  16920. fictional subroutine requires: 
  16921.  
  16922.     ;--- Define a macro to change color ------------
  16923.     #define RED    1
  16924.     #define GREEN  2
  16925.     #define BLUE   3
  16926.     #define ChangeColor                               \
  16927.             /*--- The color used was "{$#1}" ---*/   %\
  16928.             ChangeColor(<$ExpandMacro "{$#1}">);
  16929.  
  16930. This: 
  16931.  
  16932.     <$ChangeColor "RED">
  16933.  
  16934. Expands to: 
  16935.  
  16936.     /*--- The color used was "RED" ---*/
  16937.     ChangeColor(1);
  16938.  
  16939.  
  16940. ΓòÉΓòÉΓòÉ 16.2. Creating HTML pages from Windows URL Shortcuts or OS/2 URL Objects ΓòÉΓòÉΓòÉ
  16941.  
  16942. Creating HTML pages from Windows URL Shortcuts or OS/2 URL Objects 
  16943.  
  16944. Example - WPS URL Objects to HTML 
  16945.  
  16946. I keep all my WPS URL objects off a main URL folder, I then create HTML pages 
  16947. from this so I can effectively access my URL objects from anywhere via the 
  16948. internet (pages at http://www.labyrinth.net.au/~dbareis/bookmark.htm). 
  16949. Different categories can have their own look and feel! 
  16950.  
  16951. This code highly customises how the header "FTPLIKE.IH" works. At the moment I 
  16952. am still working on separating the code to a generic header file and my 
  16953. specific configuration of this. Ffor this reason there will be things in 
  16954. "bookmark.ih" which should not be and vise versa. <HR SIZE="1" 
  16955. COLOR="red"><CENTER><h1>BOOKMARK.IT</h1></center> 
  16956.  
  16957. This is the code I use for my specific customisations (as at 16 Nov 01, 
  16958. 6:05pm): 
  16959.  
  16960.     ;----------------------------------------------------------------------------
  16961.     ;--------------------------------[ BOOKMARK.IT ]-----------------------------
  16962.     ;----------------------------------------------------------------------------
  16963.     ;
  16964.     ; *************************************************************************
  16965.     ; WORK IN PROGRESS, I AM GRADUALLY SEPARATING BOOKMARK.IT/.IH so that there
  16966.     ; is a generic component anyone can use and my separate customisations
  16967.     ; (in "BOOKMARK.IT").
  16968.     ; *************************************************************************
  16969.     ;
  16970.     ; This file contains specific customisations to bookmarks for Dennis
  16971.     ; Bareis' site.
  16972.     ;
  16973.     ;----------------------------------------------------------------------------
  16974.  
  16975.     ;--- Include my common header -----------------------------------------------
  16976.     #define   HITCOUNT_NAME           bookmark_pages
  16977.     ;#define  PAGE_TRANSITION_ENTER   Duration=1,Transition=3
  16978.     #define  PAGE_TRANSITION_EXIT     Duration=1,Transition=2
  16979.     #define  Title             "Dennis' Personal Bookmarks"
  16980.     #define  AddToDescription  Dennis' Personal Bookmarks, straight from OS/2 WPS URL Objects
  16981.     #define  COLOR_PAGE_TITLE   #003366      ;;Original Dark Blue
  16982.     ;;#define  COMPUTER_NO_DESC_KEYWORD_META
  16983.     #define CSSSTYLE_EXTRA                                     \
  16984.             .LinkErr A:hover                                   \
  16985.             {                                                 -\
  16986.               color: yellow;                                  -\
  16987.               text-decoration:underline                       -\
  16988.             }
  16989.  
  16990.     #include "computer.ih"
  16991.  
  16992.     ;--- Add counter to this page -----------------------------------------------
  16993.     #define  COUNTER_ID        685720
  16994.     #define  COUNTER_ROOT      c1
  16995.     #include "counter.ih"
  16996.  
  16997.     ;--- Title ------------------------------------------------------------------
  16998.     <$BackgroundMainWindows>
  16999.     <$PageTitle TITLE="Dennis' Personal Bookmarks">
  17000.  
  17001.  
  17002.  
  17003.     ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  17004.     ;%%%[ Definitions for use in my "DIRATTR.$$$" files ]%%%%%%%%%%%%%%%%%%%%%%%%
  17005.     ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  17006.     #evaluate "Eol"         "d2c(10)"
  17007.     #define   LookAndFeelForOs2                     \
  17008.               BgImage = graphics/os2warp.jpg<$Eol> -\
  17009.               BgColor = #E0E0E0
  17010.     #define   LookAndFeelForPpwizard                \
  17011.               BgImage = ppwizard/ppw_bg.jpg<$Eol>  -\
  17012.               BgColor = WHITE
  17013.     #define   LookAndFeelForFlowers                 \
  17014.               BgImage = graphics/flowers.jpg<$Eol> -\
  17015.               BgColor = #F7FFCE
  17016.     #define   LookAndFeelForLinux                    \
  17017.               BgImage = graphics/linux_bg.gif<$Eol> -\
  17018.               BgColor = #FFFFC6
  17019.     #define   LookAndFeelForWindows                 \
  17020.               BgImage = graphics/bg_win.jpg<$Eol>  -\
  17021.               BgColor = #E0E0E0<$Eol>              -\
  17022.               DirIcon    = <IMG SRC="graphics/win16x12.gif" VALIGN="MIDDLE" WIDTH=16 HEIGHT=12 BORDER=0><$Eol> -\
  17023.               DotDotIcon = <IMG SRC="graphics/win16x12.gif" VALIGN="MIDDLE" WIDTH=16 HEIGHT=12 BORDER=0>
  17024.  
  17025.  
  17026.     ;--- At end of file listing... ----------------------------------------------
  17027.     #define? ALL_URL_TOOLTIP                                            \
  17028.              This page contains all URLS along with any comments        \
  17029.              and all categories the URL is contained in.                \
  17030.              You can use your browser's search facility                 \
  17031.              (CTRL+F in Internet Explorer) to locate URLS you           \
  17032.              might be interested in.                                    \
  17033.              Click on the category to view similar URLs.
  17034.     #define FTPLIKE_END_PAGE_ABOVE_FOOTER                            \
  17035.             #ifdef ALL_URL_NAME                                     -\
  17036.                    <CENTER>                                         -\
  17037.                    <P>A <A HREF="<$ALL_URL_NAME>" TITLE="<$ALL_URL_TOOLTIP>"> -\
  17038.                       complete listing of all URLS</A>               \
  17039.                       is available if you are having trouble         \
  17040.                       locating a URL.                               -\
  17041.                    </CENTER>                                        -\
  17042.             #endif                                                  -\
  17043.             <$ImgBarbedWire>                                        -\
  17044.             <CENTER>                                                -\
  17045.                <H2>Creating These Book Mark Pages</H2>              -\
  17046.             </CENTER>                                               -\
  17047.                                                                     -\
  17048.             <P>This page was automatically created from Windows      \
  17049.             Internet Explorer URL objects created with IE 5 or       \
  17050.             converted from my OS/2 Netscape WPS URLs (which are      \
  17051.             also supported).                                         \
  17052.                                                                      \
  17053.             The free tool used was                                   \
  17054.             <A HREF="ppwizard.htm">PPWIZARD</A>                      \
  17055.             (for Windows, Unix & OS/2) using                     \
  17056.             <A HREF="ppwizard/bookmarks.htm">                       -\
  17057.                this source code                                      \
  17058.             </A>.                                                   -\
  17059.                                                                     -\
  17060.             <P>All URLs are checked periodically using the           \
  17061.             <A HREF="checkurl.htm">my free URL validation tool</A>   \
  17062.             (for Windows and OS/2).                                  \
  17063.             This ensures that very few if any links point to moved   \
  17064.             pages or return 404 errors etc.
  17065.  
  17066.  
  17067.     ;--- Look and feel of Good and bad links ------------------------------------
  17068.     #DefineRexx BOOKMARK_URL_OK_INFO
  17069.        if  eUrl_LASTUPD = '' then
  17070.            UtTT = '"OK when tested at ' || eUrl_DATE || '"'
  17071.        else
  17072.            UtTT = ' "OK when tested at ' || eUrl_DATE || ' (HTML page dated ' || eUrl_LASTUPD || ')"'
  17073.        UtTT_A   = ' title=' || UtTT;
  17074.        UtTT_IMG = ' title=' || UtTT || ' alt=' || UtTT
  17075.        OkTick = '<img src="graphics/cb_tick.gif" hspace="2" vspace="2" align="top" border="0"' || UtTT_IMG || '>'
  17076.     #DefineRexx
  17077.     #DefineRexx BOOKMARK_URL_NOT_YET_CHECKED
  17078.        OkTick   = ''
  17079.        UtTT     = '"This link has not been tested yet"'
  17080.        UtTT_A   = ' title=' || UtTT;
  17081.        UtTT_IMG = ' title=' || UtTT || ' alt=' || UtTT
  17082.     #DefineRexx
  17083.  
  17084.  
  17085.     ;--- Include common support code --------------------------------------------
  17086.     #define BOOKMARK_DIRECTORY          C:\DBAREIS\Bookmarks
  17087.     ;#define+ BOOKMARK_DIRECTORY        C:\DBAREIS\Bookmarks\My Computer
  17088.     ;#define+ BOOKMARK_DIRECTORY        C:\DBAREIS\Bookmarks\Donate (FOR FREE)
  17089.     ;#define+ BOOKMARK_DIRECTORY         C:\DBAREIS\Bookmarks\Computer\OpSys\Windows\WIN NT or 2000
  17090.     ;#define+ BOOKMARK_DIRECTORY         C:\DBAREIS\Bookmarks\Computer\Hardware
  17091.     ;#define BOOKMARK_OPEN_LINK_IN      _BareisSame    ;;Creates one new window which is reused by all links
  17092.     #define  CHECKURL_MEMFILE           C:\DBAREIS\Projects\HOMEPAGE\html\out\REMOTE.URL\checkurl.mem
  17093.     #include "BOOKMARK.IH"
  17094.  
  17095. <HR SIZE="1" COLOR="red"><CENTER><h1>BOOKMARK.IH</h1></center> 
  17096.  
  17097. This is the (becoming) generic header code I use ( as at 6 Nov 01, 3:05pm): 
  17098.  
  17099.     ;----------------------------------------------------------------------------
  17100.     ;--------------------------------[ BOOKMARK.IH ]-----------------------------
  17101.     ;----------------------------------------------------------------------------
  17102.     ;
  17103.     ; *************************************************************************
  17104.     ; WORK IN PROGRESS, I AM GRADUALLY SEPARATING BOOKMARK.IT/.IH so that there
  17105.     ; is a generic component anyone can use and my separate customisations
  17106.     ; (in "BOOKMARK.IT").
  17107.     ; *************************************************************************
  17108.     ;
  17109.     ; This header file expands on the basic functionality provided by the
  17110.     ; "FTPLIKE" header to allow you to organise Netscape or Internet Explorer
  17111.     ; URL objects in categories and then generate HTML pages for these.
  17112.     ;
  17113.     ; You can see my bookmarks at:
  17114.     ;
  17115.     ;      http://www.labyrinth.net.au/~dbareis/bookmark.htm
  17116.     ;
  17117.     ; Some of the features:
  17118.     ;
  17119.     ;    * You can nest categories to any level.
  17120.     ;
  17121.     ;    * Categories (tree) can appear in more than one place
  17122.     ;      WITHOUT duplicating the URLS.
  17123.     ;
  17124.     ;    * Url's can be commented, giving you the ability to use normal
  17125.     ;      browser URL (shortcut) creation and add comments to your
  17126.     ;      generated pages.
  17127.     ;
  17128.     ;
  17129.     ; Some details:
  17130.     ;
  17131.     ;    * The main (top level) URLS are incorporated into the page that
  17132.     ;      includes this one, all others are generated from start to finish.
  17133.     ;
  17134.     ;
  17135.     ;
  17136.     ; Improvements I need to make
  17137.     ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  17138.     ; * Make user customisable "BOOKMARK.IT" header, removing any of my
  17139.     ;   stuff into a new private header.
  17140.     ;
  17141.     ; * Use Java (or JavaScript) Tree Navigation
  17142.     ;
  17143.     ; * As well as ALL URLS listed what about being able to indicate
  17144.     ;   categories example "all windows".
  17145.     ;
  17146.     ; * What about index similar to all url list.  Probably supply list of
  17147.     ;   words (but maybe exceptions) so as to exclude "the" etc.
  17148.     ;
  17149.     ;
  17150.     ; * BUG in ">DIRTEXT" etc, only takes first line?
  17151.     ;
  17152.     ; * Files/Dirs starting with '$$' invisible and don't appear
  17153.     ;   in generated pages. #define will allow disable or selection
  17154.     ;   of different prefix.
  17155.     ;
  17156.     ; * Have dir attributes, need easy way to assign "file"
  17157.     ;   attribs (priority , alias etc). Maybe use "[*BOOKMARK*]" to
  17158.     ;   mark off section of file, probablt then go to 1st '['?
  17159.     ;
  17160.     ; * Allow option define of collon URLS ALIAS defined in UTL name:
  17161.     ;
  17162.     ;         URL TITLE$$$URL ALIAS
  17163.     ;
  17164.     ; * Once mechanism for giving a URL an alias need new DIR command
  17165.     ;   (IncludeUrls) to include common file/url Aliases.
  17166.     ;
  17167.     ; * Too much to write down
  17168.     ;----------------------------------------------------------------------------
  17169.  
  17170.  
  17171.     ;--- Initialization ---------------------------------------------------------
  17172.     #define OpSys   <?OpSys>
  17173.     #if     left('<$OpSys>', 3) = 'WIN'
  17174.             #define+ OpSys   WINDOWS
  17175.     #endif
  17176.     #if    '<$OpSys>' <> 'WINDOWS' & '<$OpSys>' <> 'OS/2'
  17177.            #error  "Sorry but you will need to modify this file to work on operating systems other than Windows & OS/2! These changes are expected to be relatively minor."
  17178.     #endif
  17179.     #if    ['<$OpSys>' = 'OS/2']
  17180.            ;--- In OS/2 can get "real name" of file from EA's -------------------
  17181.            #evaluate   ""  "call RxFuncAdd  'SysGetEA', 'RexxUtil', 'SysGetEA'"
  17182.     #endif
  17183.     #RexxVar    AllUrlCount = 0
  17184.     #define     ALL_URL_NAME  bookmark_all_urls.htm
  17185.  
  17186.     ;--- Need sorting support for URLS ------------------------------------------
  17187.     #include "PpwSort.h"
  17188.  
  17189.  
  17190.  
  17191.     ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  17192.     ;%%%[ Override FTPLIKE Header Defaults ]%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  17193.     ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  17194.  
  17195.  
  17196.     ;--- Used as separator ------------------------------------------------------
  17197.     #define SPACE <IMG SRC="graphics/clear1x1.gif" ALIGN=middle ALT=" " BORDER=0 WIDTH={$HSIZE=^1^} HEIGHT={$VSIZE=^1^}>
  17198.  
  17199.     ;--- Define the "window" that a bookmark URL opens in -----------------------
  17200.     #ifndef    BOOKMARK_OPEN_LINK_IN
  17201.                ;--- Each link opens its own window ------------------------------
  17202.                #define BOOKMARK_OPEN_LINK_IN  _blank
  17203.     #endif
  17204.  
  17205.     ;--- Save values of this pages info (they get modified below!) --------------
  17206.     ;;#ifndef VERSION_PUSHPOPM_H
  17207.     ;;        #include "PushPopM.H"
  17208.     ;;#endif
  17209.     #push Macro 'ShortNameHtml'
  17210.     #push Macro 'ShortNameHtmlLowerCase'
  17211.  
  17212.     ;--- Don't just want filename! We want Title + URL --------------------------
  17213.     #DefineRexx REXX_PREPARE_LEFT_SIDE
  17214.        ;--- Get the URL, we know a filename -------------------------------------
  17215.        CloseRc = stream(FtpFile, 'c', 'close');
  17216.        #if ['<$OpSys>' = 'OS/2']
  17217.            ;--- First line of OS/2 WPS URL file contains the URL ----------------
  17218.            eUrl = linein(FtpFile);
  17219.        #endif
  17220.        #if ['<$OpSys>' = 'WINDOWS']
  17221.            ;--- In WINDOWS Look for "URL=" in column 1 --------------------------
  17222.            eUrl = '';
  17223.            do  while lines(FtpFile) <> 0
  17224.                ;--- Look for URL line -------------------------------------------
  17225.                ThisLine = linein(FtpFile);
  17226.                if  left(ThisLine, 4) = "URL=" then
  17227.                do
  17228.                    ;--- Found it! -----------------------------------------------
  17229.                    eUrl = substr(ThisLine, 5);     ;;Rest of line is URL
  17230.                    leave;                          ;;Look no further!
  17231.                end;
  17232.            end;
  17233.  
  17234.            ;--- Found the URL within the file? ----------------------------------
  17235.            if  eUrl = '' then
  17236.            do
  17237.                ;--- Did not find it! --------------------------------------------
  17238.                eUrl = 'URL not found in "' || FtpFile || '"';
  17239.                call Warning 'URL_NF', eUrl;
  17240.                eUrl = 'Error: ' || eUrl;
  17241.            end;
  17242.        #endif
  17243.        CloseRc = stream(FtpFile, 'c', 'close');
  17244.  
  17245.        ;--- Under windows TITLE will end with ".url" ----------------------------
  17246.        ThinTitle = '{$TITLE}';
  17247.        #if ['<$OpSys>' = 'WINDOWS']
  17248.            if translate(right(ThinTitle, 4)) = '.URL' then
  17249.               ThinTitle = left(ThinTitle, length(ThinTitle)-4);
  17250.        #endif
  17251.  
  17252.        ;--- Make sure title not too "wide" --------------------------------------
  17253.        ThinTitle = ReplaceString(ThinTitle, '<BR>', ' ');   ;;Not sure why this is here...
  17254.        ThinTitle = BreakAt(30, ThinTitle, ' -', '<br>');
  17255.        ThinTitle = ReplaceString(ThinTitle, ' <br>', '<br>');
  17256.        ThinTitle = ReplaceString(ThinTitle, '<br> ', '<br>');
  17257.  
  17258.        ;--- Fix quote char on some titles ---------------------------------------
  17259.        ThinTitle = ReplaceString(ThinTitle, '`',   "'");
  17260.        ThinTitle = ReplaceString(ThinTitle, 'EF'x, "'");
  17261.  
  17262.        ;--- Make sure URL not too "wide" ----------------------------------------
  17263.        ThinUrl   = BreakAt(25, eURL);
  17264.  
  17265.        ;--- Was the URL OK? -----------------------------------------------------
  17266.        OkTick   = '';
  17267.        UtTT     = '';
  17268.        UtTT_A   = '';
  17269.        UtTT_IMG = '';
  17270.        <$SetUpOkCheckUrlInfo>
  17271.     #DefineRexx
  17272.     #define FTPLIKE_FILE_LEFT_SIDE_DISPLAY                     \
  17273.             #evaluate  ''  ^<$REXX_PREPARE_LEFT_SIDE TITLE='<??FtpShortD $$SQx2>'>;^ -\
  17274.             <TR>                 ;;Start New File row         %\
  17275.             <TD ALIGN=CENTER>    ;;Start filename cell        %\
  17276.                 <A HREF="<??eURL>" TARGET=<$BOOKMARK_OPEN_LINK_IN><??UtTT_A>> -\
  17277.                    <??ThinTitle>                              -\
  17278.                 </A>                                          %\
  17279.             </TD>                ;;End cell                    \
  17280.             <TD ALIGN=CENTER>    ;;Start filename cell        %\
  17281.                 <A HREF="<??eURL>" TARGET=<$BOOKMARK_OPEN_LINK_IN><??UtTT_A>> -\
  17282.                    <??ThinUrl>                                -\
  17283.                    <??OkTick>                                 -\
  17284.                 </A>                                          -\
  17285.             </TD>                ;;End cell
  17286.  
  17287.     ;--- How to handle external links in the comment (use VALRURL.H") -----------
  17288.     #define     FTPLIKE_WEBLINK_TEMPLATE_HTTP  \
  17289.                 '<' || '$ExtHttp VISIBLE=^{URL}^ HTTPURL=^{URL-}^ target="<$BOOKMARK_OPEN_LINK_IN>">' || d2c(10)
  17290.     #define     FTPLIKE_WEBLINK_TEMPLATE_FTP   \
  17291.                 '<' || '$ExtFtp VISIBLE=^{URL}^  FTPURL=^{URL-}^ target="<$BOOKMARK_OPEN_LINK_IN>">' || d2c(10)
  17292.     #DefineRexx+ ValidateUrlR_REXX_Location
  17293.        UrlSourceLocation = 'URL COMMENT - ' || FtpFile;
  17294.     #DefineRexx
  17295.  
  17296.     ;--- Right side display (comment) + capture URL -----------------------------
  17297.     #DefineRexx FTPLIKE_GET_FILE_COMMENT    ;;Note comment's are not allowed to contain <ENTER> (don't know how to handle)!
  17298.                 ;--- Find comment for URL, we know a filename -------------------
  17299.                 #if ['<$OpSys>' = 'OS/2']
  17300.                     ;--- In OS/2 comments are stored in OS/2 Extended Attributes -
  17301.                     if SysGetEA(FtpFile, ".COMMENTS", "FtpComment") <> 0 then
  17302.                        FtpComment = '';
  17303.                     else
  17304.                        FtpComment = substr(FtpComment, 11); ;;Drop EA Type info
  17305.                     FtpComment = space(ReplaceString(FtpComment, '0D0A'x, '<BR>'));
  17306.                 #endif
  17307.                 #if ['<$OpSys>' = 'WINDOWS']
  17308.                     ;--- Look for bookmark comment section (freeform text) ------
  17309.                     CommentSection = "[BMCOMMENTS]";
  17310.                     CommentNl      = d2c(10);
  17311.                     FoundComment   = 'N';
  17312.                     FtpComment     = '';
  17313.                     CloseRc = stream(FtpFile, 'c', 'close');
  17314.                     do  while lines(FtpFile) <> 0
  17315.                         ;--- Get next line (ignore leading/trailing spaces) -----
  17316.                         ThisLine = strip(linein(FtpFile));
  17317.                         if  left(ThisLine, 1) = '[' then
  17318.                         do
  17319.                            ;--- Found start of Section --------------------------
  17320.                            if  FoundComment = 'Y' then
  17321.                                leave;                    ;;Found end of comment!
  17322.                            ThisLine = translate(ThisLine);
  17323.                            if ThisLine = CommentSection then
  17324.                                FoundComment = 'Y';
  17325.                         end;
  17326.                         else
  17327.                         do
  17328.                            ;--- Just a normal line ------------------------------
  17329.                            if  FoundComment = 'Y' then
  17330.                            do
  17331.                                if  FtpComment == '' then
  17332.                                    FtpComment = space(ThisLine);
  17333.                                else
  17334.                                    FtpComment = FtpComment || CommentNl || space(ThisLine);
  17335.                            end;
  17336.                         end;
  17337.                     end;
  17338.                     CloseRc = stream(FtpFile, 'c', 'close');
  17339.  
  17340.                     ;--- Add "<P>" for paragraphs -------------------------------
  17341.                     FtpComment = ReplaceString(FtpComment, CommentNl || CommentNl, '<P>');
  17342.  
  17343.                     ;--- Sort out line wrapping issues --------------------------
  17344.                     FtpComment = ReplaceString(FtpComment, CommentNl, ' ');
  17345.                 #endif
  17346.  
  17347.                 ;--- Now see if any high ASCII ----------------------------------
  17348.                 HighPos = verify(FtpComment, xrange('80'x, 'FF'x), 'M');
  17349.                 if HighPos <> 0 then
  17350.                 do
  17351.                    HighChar = substr(FtpComment, HighPos, 1);
  17352.                    call Warning 'BM_HAC', 'High ASCII found for "' || FtpFile || '" ("' || HighChar || '" - ASCII ' || c2d(HighChar) || ')';
  17353.                    FtpComment = strip(left(FtpComment, HighPos-1)) || '<HR><FONT COLOR="RED"><BLINK>Truncated here.</BLINK></FONT>' || " <B>Please don't use ENTER to separate paragraphs!</B>";
  17354.                 end;
  17355.  
  17356.                 <$AddCheckUrlErrorInfoToComment>
  17357.  
  17358.                 ;--- Autocreate http/ftp links in comments ----------------------
  17359.                 <$FTPLIKE_ADJUST_FILE_COMMENT>
  17360.  
  17361.  
  17362.                 ;****************************************************************
  17363.                 ;***[ Now keep information about this URL (for all URLs page) ***
  17364.                 ;****************************************************************
  17365.  
  17366.                 ;--- Now compact the title --------------------------------------
  17367.                 Title = ReplaceString(FtpShortD, '<BR>', ' ');
  17368.                 Title = space(Title);
  17369.  
  17370.                 ;--- Under Windows title will end with ".url" -------------------
  17371.                 #if ['<$OpSys>' = 'WINDOWS']
  17372.                     if translate(right(Title, 4)) = '.URL' then
  17373.                        Title = left(Title, length(Title)-4);
  17374.                 #endif
  17375.  
  17376.                 ;--- Increase count and save info in array ----------------------
  17377.                 AllUrlCount = AllUrlCount + 1;
  17378.                 AllUrl.AllUrlCount.!SortKey = translate(Title);
  17379.                 AllUrl.AllUrlCount.!Url     = eURL;
  17380.                 AllUrl.AllUrlCount.!Title   = Title;
  17381.                 AllUrl.AllUrlCount.!Comment = FtpComment;
  17382.                 AllUrl.AllUrlCount.!Category= '<$FTPLIKE_DISPLAY_DIR_TITLETAG $$SQx2>';
  17383.                 AllUrl.AllUrlCount.!Html    = ToLowerCase(_filespec('name', '<?OutputFile>'));
  17384.     #DefineRexx
  17385.     #DefineRexx 'Rexx2AmPm'
  17386.                 TimeAmPmFmt = GetAmPmTimeFromHhMmSs('{$TIME}');
  17387.     #DefineRexx
  17388.     #define FTPLIKE_SHOW_FILE_TIME                                                      \
  17389.             #evaluate ^^ ^<$Rexx2AmPm TIME="<??FtpHour>:<??FtpMinute>:<??FtpSecond>">^ -\
  17390.             <??FtpDay> <??FtpMon> <??FtpYear>                                           \
  17391.             <??TimeAmPmFmt>
  17392.  
  17393.     #define FTPLIKE_ADD_FILE_SIZE_AFTER_TIME  ;;Don't want file size!
  17394.  
  17395.     ;--- Other stuff ------------------------------------------------------------
  17396.     #define FTPLIKE_NO_HEADER_FOOTER_ON_1ST_PAGE
  17397.     #define FTPLIKE_FOLLOW_SUBDIRECTORIES
  17398.     #define FTPLIKE_USE_LONG_FILENAMES    100
  17399.     #define FTPLIKE_BODY_BG_IMG           graphics/bground.jpg
  17400.     #define FTPLIKE_BODY_BG_COLOR         #CCFFFF
  17401.     #define FTPLIKE_BODY_LINK_COLOR       #3333FF
  17402.     #define FTPLIKE_BODY_VLINK_COLOR      green
  17403.     #define FTPLIKE_BODY_ATTR_OTHER       LEFTMARGIN=5 TOPMARGIN=5 MARGINWIDTH=5 MARGINHEIGHT=5
  17404.     #define FTPLIKE_DIRECTORY             <$BOOKMARK_DIRECTORY>
  17405.     #define FTPLIKE_DIRECTORY_WEB
  17406.     #define FTPLIKE_NEWHTML_PREFIX        bookmark_
  17407.     #define FTPLIKE_HEADER                <$PageTitle TITLE="{$Title}">
  17408.     #define FTPLIKE_FOOTER                                                             \
  17409.             #evaluate+ ShortNameHtml            "_filespec('name', '<?OutputFile>')"  -\
  17410.             #evaluate+ ShortNameHtmlLowerCase   "ToLowerCase('<$ShortNameHtml>')"     -\
  17411.             <$EndHtmlWithStandardFooter>
  17412.     #define FTPLIKE_TEXT_FILE              url
  17413.     #define FTPLIKE_TEXT_FILES             urls
  17414.     #define FTPLIKE_TEXT_DIR               category
  17415.     #define FTPLIKE_TEXT_DIRS              categories
  17416.     #define FTPLIKE_MINI_DIR_IMG_TAG       <IMG SRC="graphics/fldrcls.gif" ALIGN="MIDDLE" ALT="*" TITLE="" BORDER=0 WIDTH=14 HEIGHT=11 VSPACE=3>
  17417.     #define FTPLIKE_DONT_USE_C2X           ;;Have longish dirs/names
  17418.     #define FTPLIKE_HEAD_STYLE_TAGS        <$CssStyle>
  17419.     #define FTPLIKE_EXTRA_HEAD_TAGS        \
  17420.             <$FULL_PICS_RATING>           %\
  17421.             <$ENGLISH_CHARSET><?NewLine>
  17422.  
  17423.  
  17424.     ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  17425.     ;%%%[ Handle CHECKURL ".MEM" file - Initialization ]%%%%%%%%%%%%%%%%%%%%%%%%%
  17426.     ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  17427.     #ifdef CHECKURL_MEMFILE
  17428.            ;--- Load CHECKURL support -------------------------------------------
  17429.            #include "CheckUrl.IH"          ;;Interface to my free URL checker
  17430.  
  17431.            ;--- User may not want "OK" indicators -------------------------------
  17432.            #ifdef BOOKMARK_NO_CHECKURL_OK_INDICATORS
  17433.                #DefineRexx 'SetUpOkCheckUrlInfo'
  17434.                    ;--- Get CheckUrl Info (need for error status) ---------------
  17435.                    <$CHECKURL_CHECK_URL URLVAR="eUrl" BaseVar="eUrl">
  17436.                #DefineRexx
  17437.            #else
  17438.                #DefineRexx 'SetUpOkCheckUrlInfo'
  17439.                do
  17440.                    ;--- Get CheckUrl Info ---------------------------------------
  17441.                    <$CHECKURL_CHECK_URL URLVAR="eUrl" BaseVar="eUrl">
  17442.  
  17443.                    ;--- Set up Info ---------------------------------------------
  17444.                    OkTick = '';
  17445.                    if   eURL_STATUS = <$CHECKURL_STATUS_OK> then
  17446.                    do
  17447.                        ;--- URL is OK -------------------------------------------
  17448.                        <$BOOKMARK_URL_OK_INFO>;
  17449.                    end;
  17450.                    else
  17451.                    do
  17452.                        if  eURL_STATUS = <$CHECKURL_STATUS_NO_INFO> then
  17453.                        do
  17454.                            ;--- URL is OK -------------------------------------------
  17455.                            <$BOOKMARK_URL_NOT_YET_CHECKED>;
  17456.                        end;
  17457.                    end;
  17458.                end
  17459.                #DefineRexx
  17460.            #end if
  17461.  
  17462.            ;--- Add ERROR indicators --------------------------------------------
  17463.            #DefineRexx 'AddCheckUrlErrorInfoToComment'
  17464.                if   eURL_STATUS = <$CHECKURL_STATUS_ERROR> then
  17465.                do
  17466.                    ;--- Format error info ---------------------------------------
  17467.                    MemBit = '<' || '?NewLine>'
  17468.                    if  FtpComment <> '' then
  17469.                        MemBit = MemBit || '<br>'
  17470.                    MemBit = MemBit || '<div class="LinkErr" title="Oops, my free URL Checker picked up a problem. I will fix ASAP although sometimes I give them a bit of time to come good again!">'
  17471.                    MemBit = MemBit || '<center><table border=4 bordercolor="black" BGCOLOR="#ff6342"><tr><td>'
  17472.                    MemBit = MemBit || '<font size="-1" color="white"><center>[CHECKURL Validation ' || eUrl_DATE || ']<br>' || eUrl_ERROR || '<center></font>'
  17473.                    MemBit = MemBit || '</td></tr></table></center>'
  17474.                    MemBit = MemBit || '</div>'
  17475.                    FtpComment = FtpComment || MemBit
  17476.                end;
  17477.            #DefineRexx
  17478.     #elseif
  17479.            #define SetUpOkCheckUrlInfo
  17480.            #define AddCheckUrlErrorInfoToComment
  17481.     #endif
  17482.  
  17483.  
  17484.     ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  17485.     ;%%%[ Include FTPLIKE Header ]%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  17486.     ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  17487.     #include  "FTPLIKE.IH"
  17488.  
  17489.  
  17490.  
  17491.     ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  17492.     ;%%%[ Add Footer to "ROOT" Page ]%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  17493.     ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  17494.     #pop Macro 'ShortNameHtmlLowerCase'
  17495.     #pop Macro 'ShortNameHtml'
  17496.     <$EndHtmlWithStandardFooter>
  17497.  
  17498.  
  17499.  
  17500.     ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  17501.     ;%%%[ Produce ALL URLS List Page ]%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  17502.     ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  17503.     #ifdef ALL_URL_NAME
  17504.            #output "<$ALL_URL_NAME>"
  17505.  
  17506.            ;--- Output Header stuff ---------------------------------------------
  17507.            #define+ FTPLIKE_DISPLAY_DIR_TITLETAG     ALL <??AllUrlCount> LINKS
  17508.            #define+ FTPLIKE_DISPLAY_DIR_CATEGORY_LT  <$FTPLIKE_DISPLAY_DIR_TITLETAG>
  17509.            <$FTPLIKE_START_HTML_PAGE>
  17510.  
  17511.            ;--- Generate BODY ---------------------------------------------------
  17512.            <?NewLine>
  17513.            #if [AllUrlCount = 0]
  17514.                <P>No URLs at all!
  17515.            #elseif
  17516.                ;--- Generate body -----------------------------------------------
  17517.                #DefineRexx ""
  17518.                            ;--- Sort the array by Title -------------------------
  17519.                            <$GenRexx2Sort                                                                \
  17520.                                 COUNT=^AllUrlCount^                                                      \
  17521.                               GREATER=^SrtGreater = AllUrl.SrtIndex1.!SortKey > AllUrl.SrtIndex2.!SortKey^   \
  17522.                                  SWAP=^                                                                  \
  17523.                                         SrtTemp = AllUrl.SrtIndex1.!SortKey;                               \
  17524.                                         AllUrl.SrtIndex1.!SortKey = AllUrl.SrtIndex2.!SortKey;               \
  17525.                                         AllUrl.SrtIndex2.!SortKey = SrtTemp;                               \
  17526.                                         SrtTemp = AllUrl.SrtIndex1.!Title;                               \
  17527.                                         AllUrl.SrtIndex1.!Title = AllUrl.SrtIndex2.!Title;               \
  17528.                                         AllUrl.SrtIndex2.!Title = SrtTemp;                               \
  17529.                                         SrtTemp = AllUrl.SrtIndex1.!Url;                                 \
  17530.                                         AllUrl.SrtIndex1.!Url = AllUrl.SrtIndex2.!Url;                   \
  17531.                                         AllUrl.SrtIndex2.!Url = SrtTemp;                                 \
  17532.                                         SrtTemp = AllUrl.SrtIndex1.!Comment;                             \
  17533.                                         AllUrl.SrtIndex1.!Comment = AllUrl.SrtIndex2.!Comment;           \
  17534.                                         AllUrl.SrtIndex2.!Comment = SrtTemp;                             \
  17535.                                         SrtTemp = AllUrl.SrtIndex1.!Category;                            \
  17536.                                         AllUrl.SrtIndex1.!Category = AllUrl.SrtIndex2.!Category;         \
  17537.                                         AllUrl.SrtIndex2.!Category = SrtTemp;                            \
  17538.                                         SrtTemp = AllUrl.SrtIndex1.!Html;                                \
  17539.                                         AllUrl.SrtIndex1.!Html = AllUrl.SrtIndex2.!Html;                 \
  17540.                                         AllUrl.SrtIndex2.!Html = SrtTemp;                                \
  17541.                                       ^                                                                  \
  17542.                            >
  17543.  
  17544.                            ;--- Display Each item -------------------------------
  17545.                            AllOutput = '';
  17546.                            Index = 1;
  17547.                            do while Index <= AllUrlCount
  17548.                                ;--- Get main information ------------------------
  17549.                                StartName    = AllUrl.Index.!Title;
  17550.                                StartUrl     = AllUrl.Index.!Url;
  17551.                                StartComment = AllUrl.Index.!Comment;
  17552.  
  17553.                                ;--- Output Name & URL ---------------------------
  17554.                                UrlLink   = '<A HREF="' || StartUrl || '" TARGET=<$BOOKMARK_OPEN_LINK_IN>>'  || StartUrl || '</A>';
  17555.                                AllOutput = AllOutput || '<P>';
  17556.                                AllOutput = AllOutput || '<TABLE BORDER=0 WIDTH="100%" CELLPADDING=1 cellspacing=0>';
  17557.                                AllOutput = AllOutput || '<TR><TD BGCOLOR=SILVER>'    || StartName || '</TD></TR>';
  17558.                                AllOutput = AllOutput || '<TR><TD BGCOLOR="#FFFF9C">' || UrlLink   || '</TD></TR>';
  17559.  
  17560.                                ;--- Add category information to comments --------
  17561.                                Comment = StartComment;
  17562.                                do  Index = Index to AllUrlCount
  17563.                                    ;--- Only category differs? ------------------
  17564.                                    if  StartName <> AllUrl.Index.!Title | StartUrl <> AllUrl.Index.!Url | StartComment <> AllUrl.Index.!Comment then
  17565.                                        leave;
  17566.  
  17567.                                    ;--- Add category ----------------------------
  17568.                                    MoreLikeThis = '<A HREF="' || AllUrl.Index.!Html || '"><SMALL>Category: ' || AllUrl.Index.!Category || '</SMALL></A>';
  17569.                                    if  Comment = '' then
  17570.                                        Comment = MoreLikeThis;
  17571.                                    else
  17572.                                        Comment = Comment || '<BR>' || MoreLikeThis;
  17573.                                end;
  17574.  
  17575.                                ;--- Output comments and category information ----
  17576.                                AllOutput = AllOutput || '<TR><TD BGCOLOR=WHITE>';
  17577.                                AllOutput = AllOutput || Comment;
  17578.                                AllOutput = AllOutput || '</TD></TR>';
  17579.  
  17580.                                ;--- End the entries table etc -------------------
  17581.                                AllOutput = AllOutput || '</TABLE>';
  17582.  
  17583.                                ;--- How many items did we just handle? ----------
  17584.                            end;
  17585.                #DefineRexx
  17586.                <??AllOutput>
  17587.            #endif
  17588.  
  17589.        ;--- Thats All for this file ---------------------------------------------
  17590.        <$FTPLIKE_FOOTER>
  17591.        #output
  17592.     #endif
  17593.  
  17594.  
  17595. ΓòÉΓòÉΓòÉ 16.3. Importing fields into 3 HTML documents ΓòÉΓòÉΓòÉ
  17596.  
  17597. Importing fields into 3 HTML documents 
  17598.  
  17599. This example shows how to import a comma delimited file into multiple HTML 
  17600. pages. The page each record goes into depends on the first character of the 
  17601. "surname" field. This basic process would also work for Fixed Field and Multi 
  17602. Line imports. 
  17603.  
  17604. Example 
  17605.  
  17606. ;----------------------------------------------------------------------------
  17607. ;    MODULE NAME:   IMPORT.IT
  17608. ;
  17609. ;    DESCRIPTION:   Example file of import of a comma delimited file into
  17610. ;                   3 separate HTML files based on the surname field (the
  17611. ;                   second field).
  17612. ;
  17613. ;
  17614. ;                   Imported file looks like:
  17615. ;                   ~~~~~~~~~~~~~~~~~~~~~~~~~
  17616. ;                   Dennis,Bareis,Programmer
  17617. ;                   Wendy,Buxton,Librarian
  17618. ;                   Fred,Nerk,Idiot
  17619. ;
  17620. ;----------------------------------------------------------------------------
  17621.  
  17622.  
  17623. ;--- Start and end main HTML file -------------------------------------------
  17624. <HTML>
  17625. <HEAD>
  17626.    <TITLE>MAIN FILE</TITLE>
  17627. </HEAD>
  17628. <BODY>
  17629. <H1>MAIN FILE</H1>
  17630. <P>This is a fairly basic example kept simple on purpose to hopefully
  17631. make things easier to understand.
  17632. Basically we imported a comma delimited
  17633. file (could have been fixed or other format) and put the record into a
  17634. particular html page based on the surname field.
  17635.  
  17636. <P>The following imported tables are available:
  17637. <OL>
  17638.    <LI><A HREF="p_a2l.htm">A - L</A>
  17639.    <LI><A HREF="p_m2z.htm">M - Z</A>
  17640.    <LI><A HREF="p_oth.htm">Others</A>
  17641. </OL>
  17642. </BODY></HTML>
  17643.  
  17644.  
  17645.  
  17646. ;--- Define HTML to start the import data files -----------------------------
  17647. #define StartsImportFiles                           \
  17648.         #output 'p_{$Suffix}.htm' ASIS             -\
  17649.         <HTML>                                     %\
  17650.         <HEAD>                                     %\
  17651.            <TITLE>IMPORTED: {$DESCRIPTION}</TITLE> %\
  17652.            <?PpwizardGeneratorMetaTags>            %\
  17653.         </HEAD>                                    %\
  17654.         <BODY>                                     %\
  17655.         <CENTER>                                   %\
  17656.         <H1>IMPORTED: {$DESCRIPTION}</H1>          %\
  17657.         <TABLE BORDER=5 CELLSPACING=5>             %\
  17658.         <TR><TH ALIGN=CENTER>First<BR>Name<TH ALIGN=CENTER>Surname<TH ALIGN=CENTER>Job</TR> %\
  17659.         #output
  17660.  
  17661. ;--- Define HTML to end the import data files -------------------------------
  17662. #define TrNoRecords   <TD ALIGN=CENTER><FONT COLOR="RED">No records</FONT></TD>
  17663. #define EndsImportFiles                                          \
  17664.         #output 'p_{$Suffix}.htm' ASIS APPEND                   -\
  17665.         #if {$Suffix} = 'N'                                     -\
  17666.             <TR><$TrNoRecords><$TrNoRecords><$TrNoRecords></TR> -\
  17667.         #endif                                   -\
  17668.         </TABLE>                                 %\
  17669.         </CENTER>                                %\
  17670.         </BODY></HTML>                           %\
  17671.         #output
  17672.  
  17673.  
  17674.  
  17675. ;--- Create 3 output files and fill with start of HTML and start table etc ---
  17676. <$StartsImportFiles SUFFIX="oth" DESCRIPTION="OTHER">
  17677. <$StartsImportFiles SUFFIX="a2l" DESCRIPTION="A to L">
  17678. <$StartsImportFiles SUFFIX="m2z" DESCRIPTION="M to Z">
  17679.  
  17680. ;--- Prepare for import -----------------------------------------------------
  17681. #evaluate ''  'NL = d2c(10)'                        ;;NL = Newline Code
  17682. #evaluate ''  'oth = 'N'; a2l = 'N'; m2z = 'N';'    ;;No records output yet
  17683. #define     IMPORT_PROTECT_START                    ;;We don't want imported data "protected" or #output etc won't get executed
  17684. #define     IMPORT_PROTECT_END
  17685. #define     IMPORT_HEADER                           ;;We will output our own headers
  17686. #define     IMPORT_BEFORE
  17687. #define     IMPORT_AFTER                            ;;We will output our own trailers
  17688. #DefineRexx IMPORT_RECORD_FILTER
  17689.         ;--- Which output file should contain this record? ---
  17690.         Char1 = translate(left(Column.2, 1));
  17691.         if Char1 < 'A' & Char1 > 'Z' then
  17692.         do;
  17693.            Suffix = 'oth';    ;;Not a letter
  17694.            oth    = 'Y';
  17695.         end;
  17696.         else;
  17697.         do;
  17698.            ;--- We have a letter ---
  17699.            if Char1 < 'M' then
  17700.            do;
  17701.               Suffix = 'a2l';
  17702.               a2l    = 'Y';
  17703.            end;
  17704.            else;
  17705.            do;
  17706.               Suffix = 'm2z';
  17707.               m2z    = 'Y';
  17708.            end;
  17709.         end;
  17710.  
  17711.         ;--- make sure output will go to correct file ---
  17712.         call WriteLineToTmpImportFile '#if <?OutputLevel> > 1' || NL || '   #output' || NL || '#endif';
  17713.         call WriteLineToTmpImportFile '#output ^p_' || Suffix || '.htm^ ASIS APPEND';
  17714. #DefineRexx
  17715.  
  17716. ;--- Import the data into the 3 files ---------------------------------------
  17717. #import Import.CMA CMA "" "First Name" "Surname" "Job"
  17718.  
  17719. ;--- Close last file --------------------------------------------------------
  17720. #if <?OutputLevel> > 1
  17721.     #output
  17722. #endif
  17723.  
  17724. ;--- Finish off 3 html tables and files ----
  17725. <$EndsImportFiles SUFFIX="oth">
  17726. <$EndsImportFiles SUFFIX="a2l">
  17727. <$EndsImportFiles SUFFIX="m2z">
  17728.  
  17729. Note that the example above overrides "IMPORT_PROTECT_START" and 
  17730. "IMPORT_PROTECT_END"; this allows the generated PPWIZARD commands such as #if 
  17731. and #output to be interpreted, rather than simply passed through as data. 
  17732.  
  17733. In some cases this may not be desirable, as depending on exactly what you are 
  17734. doing you could put PPWIZARD into a situation where it could "make mistakes" 
  17735. (such as if a field contained '<$'). 
  17736.  
  17737. Although it can be desirable that PPWIZARD interpret macros and expand them if 
  17738. you catered for this in your design, I will demonstrate how you can ensure that 
  17739. they will not be - no matter what.  This will demonstrate an alternative 
  17740. approach to using the two "WriteLineToTmpImportFile" lines in the example above 
  17741. and will also ensure that the record line is "protected" from PPWIZARD: 
  17742.  
  17743.         ;--- Update what will get written to temp file ---                                     \
  17744.         AddB =         '#if <?OutputLevel> > 1' || NL || '   #output' || NL || '#endif' || NL; \
  17745.         AddB = AddB || '#output ^p_' || Suffix || '.htm^ ASIS APPEND' || NL;                   \
  17746.         AddB = AddB || '<?ProtectFromPpwStart>' || NL;                                         \
  17747.         AddA = NL   || '<?ProtectFromPpwEnd>';                                                 \
  17748.         ThisRecordsCodes = AddB || ThisRecordsCodes || AddA;
  17749.  
  17750. You should also have a look at the other multiple import example. The example 
  17751. on that page is similar but does things in a completely different way. 
  17752.  
  17753.  
  17754. ΓòÉΓòÉΓòÉ 16.4. Importing Fields, Each Record To It's Own File ΓòÉΓòÉΓòÉ
  17755.  
  17756. Importing Fields, Each Record To It's Own File 
  17757.  
  17758. I wrote this example for someone who wanted to do pretty much what you see 
  17759. here, each record of a CSV file creates its own HTML page. The name of the file 
  17760. is determined by the record number. 
  17761.  
  17762. You should also have a look at the other multiple import example. The example 
  17763. on this page is similar but does things in a completely different way. 
  17764.  
  17765. ;----------------------------------------------------------------------------
  17766. ;    MODULE NAME:   IMPORT.IT
  17767. ;
  17768. ;    DESCRIPTION:   Example file of import of a comma delimited file where
  17769. ;                   each record goes into its own file. The line number is
  17770. ;                   used to name the file.
  17771. ;
  17772. ;
  17773. ;                   Imported file looks like:
  17774. ;                   ~~~~~~~~~~~~~~~~~~~~~~~~~
  17775. ;                   Dennis,Bareis,Programmer
  17776. ;                   Wendy,Buxton,Librarian
  17777. ;                   Fred,Nerk,Idiot
  17778. ;
  17779. ;----------------------------------------------------------------------------
  17780.  
  17781.  
  17782. ;--- Start and end main HTML file -------------------------------------------
  17783. <HTML>
  17784. <HEAD>
  17785.    <TITLE>MAIN FILE</TITLE>
  17786. </HEAD>
  17787. <BODY>
  17788. <H1>MAIN FILE</H1>
  17789. <P>This is a fairly basic example kept simple on purpose to hopefully
  17790. make things easier to understand.
  17791. Basically we imported a comma delimited
  17792. file (could have been fixed or other format) and generate the record into a
  17793. new html page whose name depends on the line Number.
  17794.  
  17795.  
  17796. ;--- Initialize a line count ------------------------------------------------
  17797. #RexxVar RecordLineCount = 0
  17798.  
  17799.  
  17800. ;--- Define HTML to start the import data files -----------------------------
  17801. #define StartsImportFiles                           \
  17802.         ;--- Open the record's file ------------   -\
  17803.         #output 'file_{$LineNum}.htm' ASIS         -\
  17804.                                                    -\
  17805.         ;--- Output Start of HTML page ---------   -\
  17806.         <HTML>                                     %\
  17807.         <HEAD>                                     %\
  17808.            <TITLE>IMPORTED: {$Desc}</TITLE>        %\
  17809.            <?PpwizardGeneratorMetaTags>            %\
  17810.         </HEAD>                                    %\
  17811.         <BODY>                                     %\
  17812.         <H1>IMPORTED: {$Desc}</H1>
  17813.  
  17814. ;--- Define HTML to end the import data files -------------------------------
  17815. #define EndsImportFiles                             \
  17816.         ;--- Output end of html page -----------   -\
  17817.         </BODY></HTML>                             -\
  17818.                                                    -\
  17819.         ;--- Close this HTML file --------------   -\
  17820.         #output
  17821.  
  17822.  
  17823. ;--- Prepare for import -----------------------------------------------------
  17824. #evaluate ''  'NL = d2c(10)'                        ;;NL = Newline Code
  17825. #define     IMPORT_PROTECT_START                    ;;We don't want imported data "protected" or #output etc won't get executed
  17826. #define     IMPORT_PROTECT_END
  17827. #define     IMPORT_HEADER                           ;;We will output our own headers
  17828. #define     IMPORT_BEFORE
  17829. #define     IMPORT_AFTER                            ;;We will output our own trailers
  17830. #DefineRexx IMPORT_RECORD_FILTER
  17831.         ;--- Which output file should contain this record? ---
  17832.         RecordLineCount = RecordLineCount + 1;
  17833.  
  17834.         ;--- Make sure output will go to correct file --------
  17835.         Codes =          '<' || '$StartsImportFiles LineNum="' || RecordLineCount || '" Desc="FILE #' || RecordLineCount || '">'
  17836.         Codes = Codes || NL;
  17837.         Codes = Codes || '  <P>Column 1 = ' || Column.1;
  17838.         Codes = Codes || NL;
  17839.         Codes = Codes || '  <P>Column 2 = ' || Column.2;
  17840.         Codes = Codes || NL;
  17841.         Codes = Codes || '  <P>Column 3 = ' || Column.3;
  17842.         Codes = Codes || NL;
  17843.         Codes = Codes || '<' || '$EndsImportFiles>';
  17844.         Codes = Codes || NL;
  17845.         Codes = Codes || NL;
  17846.         ThisRecordsCodes = Codes;
  17847. #DefineRexx
  17848.  
  17849.  
  17850. ;--- Import the data into the 'x' files -------------------------------------
  17851. #import INPUT.CMA CMA "" "First Name" "Surname" "Job"
  17852.  
  17853.  
  17854. ;--- Report on the number of files created/records imported -----------------
  17855. <P>Thats all folks, created <??RecordLineCount $$AddComma> files.
  17856.  
  17857. ;--- Finish off HTML for "control" page -------------------------------------
  17858. </BODY></HTML>
  17859.  
  17860.  
  17861. ΓòÉΓòÉΓòÉ 16.5. #import - EXCEL via VbScript ΓòÉΓòÉΓòÉ
  17862.  
  17863. #import - EXCEL via VbScript 
  17864.  
  17865. This is an example of how Excel data can be automatically exported from a 
  17866. spreadsheet into a CSV and then read into ppwizard. 
  17867.  
  17868. It is a bit crude but would provide an excellent starting point for anyone 
  17869. wishing to do similar. 
  17870.  
  17871. The spread-sheet has 3 columns and ends when the "A" column contains an empty 
  17872. value, the code follows: 
  17873.  
  17874.     ;----------------------------------------------------------------------------
  17875.     ;--- Create VbScript --------------------------------------------------------
  17876.     ;----------------------------------------------------------------------------
  17877.     #Output "out\DOIT.VBS" ASIS
  17878.        '--- Some values ---------------------------------------------------------
  17879.        CsvName = "EXCEL.CSV"             'Short name (created in "TMP" dir)
  17880.        XlSheet = 1                       'WorkSheet Number
  17881.  
  17882.        '--- Create Log File -----------------------------------------------------
  17883.        set WshShell  = WScript.CreateObject("WScript.Shell")
  17884.        set WshSysEnv = WshShell.Environment("USER")
  17885.        set fso       = CreateObject("Scripting.FileSystemObject")
  17886.        CsvName       = WshShell.ExpandEnvironmentStrings(WshSysEnv("TMP")) & "\" & CsvName
  17887.        set CsvFile   = fso.CreateTextFile(CsvName, True)
  17888.  
  17889.        '--- Create Excel object -------------------------------------------------
  17890.        set XlObj = Wscript.CreateObject("Excel.Application")
  17891.  
  17892.        '--- Open the EXCEL Spread sheet -----------------------------------------
  17893.        call XlObj.Workbooks.Open("C:\TMP\EXCEL\SIMPLE.XLS",0)
  17894.        XlObj.Sheets(XlSheet).Activate
  17895.  
  17896.        '--- Loop through rows until we find a cell in "A" that is empty ---------
  17897.        Row = 1
  17898.        do  until XlObj.Range("A:A").Cells(Row).Text = ""
  17899.            'Wscript.Echo ">>>>>>>>>>>>>>" & XlObj.Range("A:A").Cells(1).Text
  17900.            'Wscript.Echo "@@@@@" & XlObj.Range("A1").value & "@@@@@@@@"
  17901.  
  17902.            '--- Get data from first 3 cells -------------------------------------
  17903.            Cell1 = XlObj.Range("A:A").Cells(Row).Text
  17904.            Cell2 = XlObj.Range("B:B").Cells(Row).Text
  17905.            Cell3 = XlObj.Range("C:C").Cells(Row).Text
  17906.  
  17907.            '--- Display Data ----------------------------------------------------
  17908.            Record = Quote(Cell1) & "," + Quote(Cell2) & "," + Quote(Cell3)
  17909.            CsvFile.WriteLine(Record)
  17910.  
  17911.            '--- Look at next row ------------------------------------------------
  17912.            Row = Row + 1
  17913.        loop
  17914.        Wscript.Echo "Wrote " & cstr(Row-1) & " rows to """ & CsvName & """"
  17915.  
  17916.        '--- Close Generated file ------------------------------------------------
  17917.        CsvFile.close()
  17918.  
  17919.        '--- Close Excel object --------------------------------------------------
  17920.        XlObj.Quit
  17921.  
  17922.        '--- That's All Folks ----------------------------------------------------
  17923.        Wscript.Quit 0
  17924.  
  17925.  
  17926.  
  17927.        '=========================================================================
  17928.        function Quote(What)
  17929.        '
  17930.        ' If the cell contains a value that needs quoting then quote it, take care of
  17931.        ' any double quotes (get doubled up)
  17932.        '=========================================================================
  17933.            if  instr(1, What, " ") <> 0 OR instr(1, What, ",") <> 0 OR instr(1, What, """")  <> 0 then
  17934.                Quote = """" & replace(What, """", """""") & """"
  17935.            else
  17936.                Quote = What                   'No need to quote
  17937.            end if
  17938.        end function
  17939.     #Output
  17940.  
  17941.  
  17942.     ;----------------------------------------------------------------------------
  17943.     ;--- Executes the VbScript --------------------------------------------------
  17944.     ;----------------------------------------------------------------------------
  17945.     #DefineRexx ''
  17946.        VbRc = AddressCmd("cscript out\doit.vbs")
  17947.        if  VbRc <> 0 then
  17948.            error("The VbScript to create CSV from Excel failed", "RC = " || VbRc);
  17949.     #DefineRexx
  17950.  
  17951.     ;----------------------------------------------------------------------------
  17952.     ;--- Import the result ------------------------------------------------------
  17953.     ;----------------------------------------------------------------------------
  17954.     #import ^<?=getenv("TMP") || "\EXCEL.CSV">^ "CMA" ""   \
  17955.             "First Name"                                   \
  17956.             "Surname"                                      \
  17957.             "Age"
  17958.  
  17959.  
  17960. ΓòÉΓòÉΓòÉ 16.6. Automatically Create Chart Images ΓòÉΓòÉΓòÉ
  17961.  
  17962. Automatically Create Chart Images 
  17963.  
  17964. PPWIZARD is all about automation and reducing your work load. For this reason I 
  17965. have included a crude example of how a bar/pie or other type of chart can be 
  17966. automatically created. 
  17967.  
  17968. This sample shows the data hardcoded, in real life it would come from a 
  17969. database or some other source. The source has enough detail (keywords!) in it 
  17970. that you should have little trouble finding more information on the web. 
  17971.  
  17972. The data could be "hardcoded" via an SQL import (ie generate VB code instead of 
  17973. HTML table) if the VbScript was generated in a similar manner to that shown in 
  17974. the Excel example. 
  17975.  
  17976. The VbScript code follows (tested in Windows 2000 with Office 2000): 
  17977.  
  17978.     '--- Initialize chart -------------------------------------------------------
  17979.     set oChart = WScript.CreateObject("OWC.Chart")
  17980.     'oChart.Clear()
  17981.     'oChart.Refresh()
  17982.  
  17983.     '--- Some Handy "hooks" -----------------------------------------------------
  17984.     set Con   = oChart.Constants           'Access to predefined constants
  17985.     set Chart = oChart.Charts.Add
  17986.     set SC    = Chart.SeriesCollection
  17987.     set SCA   = Chart.SeriesCollection.Add  'Need! (VbScript bug?, looks likely)
  17988.  
  17989.     '--- Set colors -------------------------------------------------------------
  17990.     'oChart.Border.Color = Con.chColorNone
  17991.     'oChart.Border.Color = Con.chColor
  17992.  
  17993.     '--- Add Title --------------------------------------------------------------
  17994.     Chart.hasTitle        = true
  17995.     Chart.title.caption   = "Dennis' Test Chart"
  17996.     Chart.title.font.name = "tahoma"
  17997.     Chart.title.font.size = 10
  17998.     Chart.title.font.bold = true
  17999.  
  18000.     '--- Make up some data ------------------------------------------------------
  18001.     dim x(10), y(10)
  18002.     x(1) = "RED"
  18003.     x(2) = "GREEN"
  18004.     x(3) = "BLUE"
  18005.     y(1) = "20"
  18006.     y(2) = "61"
  18007.     y(3) = "70"
  18008.  
  18009.     '--- Chart above data -------------------------------------------------------
  18010.     SCA.setData Con.chDimCategories, Con.chDataLiteral, x
  18011.     SCA.setData Con.chDimValues,     Con.chDataLiteral, y
  18012.  
  18013.     '--- Want Exploded PIE Chart (default is bar graph) -------------------------
  18014.     'Chart.Type = Con.chChartTypePie
  18015.     'SC.Item(0).Explosion = 10
  18016.  
  18017.     '--- Label the values -------------------------------------------------------
  18018.     'with SC(0).DataLabelsCollection.Add            'Add values to slices/on top of bar
  18019.     '   .Interior.Color = RGB(255, 255, 255)
  18020.     '   .Font.Size      = 8
  18021.     'end with
  18022.  
  18023.     '--- Create the GIF ---------------------------------------------------------
  18024.     oChart.ExportPicture "c:\tmp\excel\t_chart.gif", "gif", 200, 200
  18025.  
  18026.  
  18027. ΓòÉΓòÉΓòÉ 16.7. Create Multiple Files From Template ΓòÉΓòÉΓòÉ
  18028.  
  18029. Create Multiple Files From Template 
  18030.  
  18031. This page demonstrates one way a set of data files could be created based on a 
  18032. template. 
  18033.  
  18034. In this particular case multiple XML files are created for Jetform Central test 
  18035. data. We wish to generate quite a few variations for each basic type of form 
  18036. that we support. 
  18037.  
  18038. We also wish to support the generation of XML data with real "life like" 
  18039. customer data as well as use of the XML field name as data (helps pinpoint 
  18040. errors). 
  18041.  
  18042. The following is the contents of "JFTDATA.H" which is a common header file I 
  18043. will use in all similar Jetform template files: 
  18044.  
  18045. ;----------------------------------------------------------------------------
  18046. ;
  18047. ;    MODULE NAME:   JFTDATA.H
  18048. ;
  18049. ;        $Author:   USER "Dennis"  $
  18050. ;      $Revision:   1.4  $
  18051. ;          $Date:   29 Oct 2001 19:59:30  $
  18052. ;       $Logfile:   C:/DBAREIS/Projects.PVCS/MultiOs/PPWIZARD/examples.dh.pvcs  $
  18053. ;
  18054. ;    DESCRIPTION:   Common include file for all test data.
  18055. ;                   Tries to hide as much impementation detail as possible.
  18056. ;                   This will allow us to make major changes in future
  18057. ;                   without affecting user templates (if required).
  18058. ;----------------------------------------------------------------------------
  18059.  
  18060. ;--- Define Defaults --------------------------------------------------------
  18061. #define? PRINTER  PRINTR01
  18062.  
  18063. ;--- What is the output directory? ------------------------------------------
  18064. #evaluate OutputDir ^_filespec('location', '<?OutputFile>')^
  18065.  
  18066.  
  18067.  
  18068. ;----------------------------------------------------------------------------
  18069. ;--- How to create a field --------------------------------------------------
  18070. ;----------------------------------------------------------------------------
  18071. #( ''
  18072.    #define FIELD
  18073.    #ifdef USE_FIELD_NAMES_AS_DATA
  18074.            ;--- Override data supplied by using fieldname as the data ---
  18075.            <{$Name} {$FLDATTR=^xfa:match="many"^}>{$Name}</{$Name}>
  18076.    #elseif
  18077.            ;--- Use the supplied data as field data ----
  18078.            <{$Name} {$FLDATTR=^xfa:match="many"^}>{$Data}</{$Name}>
  18079.    #endif
  18080. #)
  18081.  
  18082.  
  18083. ;----------------------------------------------------------------------------
  18084. ;--- START XML --------------------------------------------------------------
  18085. ;----------------------------------------------------------------------------
  18086. #( ''
  18087.    ;--- Define Macro --------------------------------------------------------
  18088.    #define StartJfXML
  18089.  
  18090.    ;--- Build filename from filename template user supplied -----------------
  18091.    #option PUSH DefineMacroReplace=ON
  18092.        ;--- Expand "parameters" ---------------------------------------------
  18093.        #define+ XML_FILE  <$XML_FILE_TEMPLATE {$?}>
  18094.    #option POP
  18095.  
  18096.    ;--- Output to the log file ----------------------------------------------
  18097.    Building :  "<$XML_FILE>"
  18098.  
  18099.    ;--- Create new test data file -------------------------------------------
  18100.    #info   "<$XML_FILE>"
  18101.    #output "<$XML_FILE>" ASIS
  18102.  
  18103.    ;--- Start The XML -------------------------------------------------------
  18104.    #( '<?NewLine>'
  18105.        <?xml version="1.0" encoding="UTF-8" standalone="yes"?><?NewLine>
  18106.        <!--
  18107.            <?space>         TIME: <?CompileTime>
  18108.            <?space>      MADE BY: <?=GetEnv("VCSID")>
  18109.            <?space>           ON: <?=GetEnv("COMPUTERNAME")>
  18110.            <?space>     TEMPLATE: <?InputFile>
  18111.            <?space>      VERSION: <$TEM_VERSION>
  18112.        --><?NewLine>
  18113.        <xfa:Data xmlns:xfa="http://www.xfa.com/schema/xfa-data">
  18114.        <JFXMLRecord>
  18115.    #)
  18116. #)
  18117.  
  18118.  
  18119. ;----------------------------------------------------------------------------
  18120. ;--- END XML ----------------------------------------------------------------
  18121. ;----------------------------------------------------------------------------
  18122. #( ''
  18123.    ;--- Define Macro --------------------------------------------------------
  18124.    #define EndJfXML
  18125.  
  18126.    ;--- Output end of the XML (close tags) ----------------------------------
  18127.    #( '<?NewLine>'
  18128.        </JFXMLRecord>
  18129.        </xfa:Data>
  18130.    #)
  18131.  
  18132.    ;--- Close the file ------------------------------------------------------
  18133.    #Output
  18134. #)
  18135.  
  18136. The following is the contents of the first part of "REFERRAL.TEM" which is the 
  18137. template component for a "referral": 
  18138.  
  18139. ;----------------------------------------------------------------------------
  18140. ;
  18141. ;    MODULE NAME:   REF.TEM
  18142. ;
  18143. ;        $Author:   USER "Dennis"  $
  18144. ;      $Revision:   1.4  $
  18145. ;          $Date:   29 Oct 2001 19:59:30  $
  18146. ;       $Logfile:   C:/DBAREIS/Projects.PVCS/MultiOs/PPWIZARD/examples.dh.pvcs  $
  18147. ;
  18148. ;    DESCRIPTION:   Referral test data template
  18149. ;----------------------------------------------------------------------------
  18150.  
  18151. ;--- Define VERSION number of template --------------------------------------
  18152. #define TEM_VERSION 01.299
  18153.  
  18154. ;--- Include common test data support ---------------------------------------
  18155. #include "JFTDATA.H"
  18156.  
  18157. ;--- Referral template ------------------------------------------------------
  18158. #define XML_FILE_TEMPLATE \
  18159.        <$OutputDir>REFERRAL_{$TYPE}_{$Jobid}_{$CodeId}_{$TSLCODE}_{$LETTERTYPECODE}.xml
  18160. #( '<?NewLine>'
  18161.    #define TdReferal
  18162.  
  18163.    ;--- Create the new XML file and output start of XML ---------------------
  18164.    <$StartJfXML {$?}>
  18165.  
  18166.    ;--- Contents of the file (starting at the JOBCARD) ----------------------
  18167.    <JF_JOB_CARD>Referral_F -agvTYPE={$TYPE} -aji{$Jobid} -advfax:NUMCOMMANDS=1 -advfax:TO_FAX_NUM_1="(03) 8615 5352" -advfax:TO_NAME_1="Eddie Chow" -advfax:OPTION_1_1=WHO:ADMINISTRATOR -z<$PRINTER></JF_JOB_CARD>
  18168.        <CODEID xfa:match="many">{$CodeId}</CODEID>
  18169.        <TSLCODE xfa:match="many">{$TSLCODE}</TSLCODE>
  18170.        <LETTERTYPECODE xfa:match="many">{$LETTERTYPECODE}</LETTERTYPECODE>
  18171.        <$Field NAME="REFERRERBRANCH"       DATA="Royal Bank Branch">
  18172.        <$Field NAME="REFERRERADDRLINE0"    DATA="156 Collins Street">
  18173.        <$Field NAME="REFERRERADDRLINE1"    DATA="Melbourne Vic 3000">
  18174.        ...
  18175.        (heaps more)
  18176.        ...
  18177.        <START xfa:dataNode="dataGroup"/>
  18178.            <LETTER_DATA></LETTER_DATA>
  18179.  
  18180.    ;--- Output End of XML and close the file --------------------------------
  18181.    <$EndJfXML {$?}>
  18182. #)
  18183.  
  18184. The following is the contents of the last part of "REFERRAL.TEM" which is 
  18185. creating one test file for each set up data (using the above "referral" 
  18186. template): 
  18187.  
  18188. ;--- Create a test file for each combination --------------------------------
  18189. #{  SET                            \
  18190.    "TYPE=F"                        \
  18191.    "JOBID=O P"                     \
  18192.    "CODEID=RAHL RAIL"              \
  18193.    "TSLCODE=24H"                   \
  18194.    "LETTERTYPECODE=LWA LNA LCP"
  18195.  
  18196.    ;--- Create every combination between the sets ---------------------------
  18197.    <$TdReferal TYPE="<??SET_TYPE>" Jobid="<??SET_Jobid>" CodeId="<??SET_CodeId>" TSLCODE="<??SET_TSLCODE>" LETTERTYPECODE="<??SET_LETTERTYPECODE>">
  18198. #}
  18199.  
  18200.  
  18201. ;**      CommentBlock  /* (Friday 26/10/2001, 10:18:39, by Dennis Bareis) */
  18202. ;**+--------------------------------------------------------------------------
  18203. ;**|;--- OLD WAY ----------------------------------------------------------------
  18204. ;**|<$TdReferal TYPE="F" Jobid="P" CodeId="RAHL" TSLCODE="24H" LETTERTYPECODE="LWA">
  18205. ;**|       ...
  18206. ;**|       (heaps more)
  18207. ;**|       ...
  18208. ;**|<$TdReferal TYPE="F" Jobid="O" CodeId="RAIL" TSLCODE="24H" LETTERTYPECODE="LCP">
  18209. ;**+--------------------------------------------------------------------------
  18210. ;**                    /* (Friday 26/10/2001, 10:18:39, by Dennis Bareis) */
  18211.  
  18212. The following is a sample batch file which shows the text data being created 
  18213. twice, once with user supplied data (to the"Field" macro) and once using the 
  18214. XML field names: 
  18215.  
  18216. @echo off
  18217. cls
  18218. @echo ***
  18219. @echo *** Making ALL Referral test data (if required) ***
  18220. @echo ***
  18221.  
  18222. @rem *** Create test data using supplied field info ***
  18223. ppwizard ref.tem /output:out\DATA\ref.log      /dependson:-out\depends\ref_data.dep /ErrorFile:out\ref_data.err
  18224.  
  18225. @rem *** Create test data using XML field names ***
  18226. ppwizard ref.tem /output:out\FLD_NAMES\ref.log /dependson:-out\depends\ref_fld_names.dep /ErrorFile:out\ref_fld_names.err /Define:USE_FIELD_NAMES_AS_DATA
  18227.  
  18228.  
  18229. ΓòÉΓòÉΓòÉ 16.8. Resource Validation - Local ΓòÉΓòÉΓòÉ
  18230.  
  18231. Resource Validation - Local 
  18232.  
  18233. This example shows how you could ensure that your local resources actually 
  18234. exist (you should also have a look at the validation of remote resources 
  18235. support that PPWIZARD supplies). This helps to eliminate mistakes (it's assumed 
  18236. that you won't forget to FTP local resources to the web server!). The example 
  18237. is HTML-based but would work for any language or text file where external 
  18238. resources are referenced. 
  18239.  
  18240. While the macros I will show will work, typically everyone has a different way 
  18241. of working which would probably require these macros to be modified, however 
  18242. they are great as a guide. 
  18243.  
  18244. Generic Macro 
  18245.  
  18246. This macro makes no assumptions about your development environment and causes 
  18247. PPWIZARD to fail with an appropriate error message if the resource does not 
  18248. exist. 
  18249.  
  18250. The macro takes 2 manditory parameters, one identifies the full name of the 
  18251. file on the development machine and the other is used for resource 
  18252. identification purposes (when an error occurs) and is normally how your HTML 
  18253. references it. 
  18254.  
  18255. The macro is as follows: 
  18256.  
  18257.     ;--- Generic check for resource validity routine ---
  18258.     #define    CheckResource                                                     \
  18259.                #if stream('{$LocalName}', 'c', 'query exists') = ''              \
  18260.                    #error ^Resource "{$Name}" appears to be invalid. The file "{$LocalName}" could not be located!^ \
  18261.                #endif
  18262.  
  18263. Of course you may not wish to abort PPWIZARD for what you consider to be a 
  18264. warning situation, in this case you could use #warning instead. 
  18265.  
  18266. Development Environment Specific Macro 
  18267.  
  18268. In HTML, when I refer to an image such as "graphics/fred.gif", the file 
  18269. "fred.gif" should exist in the "graphics" directory when the HTML is "run". The 
  18270. image file could exist anywhere on my development machine, so I will taylor a 
  18271. graphics validation setup as follows: 
  18272.  
  18273.     ;--- Check if Graphic exists ------------------------------------------------
  18274.     #option    PUSH LineContinuation="NULL"      ;;Next line ends with continuation char!
  18275.     #define    MyLocalGraphicsDirectory    C:\PROJECTS\HOMEPAGE\GRAPHICS\
  18276.     #option    POP                               ;;Restore original continuation char
  18277.     #define    MyRemoteGraphicsDirectory   graphics/
  18278.     #define    ValGraphic                                                        \
  18279.                <$CheckResource LocalName=^<$MyLocalGraphicsDirectory>{$SNAME}^   \
  18280.                                     Name=^<$MyRemoteGraphicsDirectory>{$SNAME}^  \
  18281.                >
  18282.  
  18283. The above macros are probably defined in a validation or other common header 
  18284. file. Note that you might wish to use shorter names such as "vlg" for "validate 
  18285. local graphic" etc. To actually test that an image file exists I could use: 
  18286.  
  18287.     <$ValGraphic SNAME="fred.gif">
  18288.     <IMG SRC="graphics/fred.gif">
  18289.  
  18290. Even the above macro and reference make some assumptions about how I personally 
  18291. wish to use them, this is another reason why everyone would probably "roll 
  18292. their own". 
  18293.  
  18294. An Alternative Way - #1 
  18295.  
  18296. The problem with the above set of macros is that you have to do 2 operations, 
  18297. the first is to validate the resource and the second is to use it. 
  18298.  
  18299. A better alternative is for the same routine that does the validation to 
  18300. generate the "remote" resource so that the generic macro (let's also change to 
  18301. only warning if resource is missing) becomes: 
  18302.  
  18303.     ;--- Generic check for resource validity routine ---
  18304.     #define    CheckResource                                                     \
  18305.                #if stream('{$LocalName}', 'c', 'query exists') = ''              \
  18306.                    #Warning ^$MR00^ ^Resource "{$Name}" appears to be invalid. The file "{$LocalName}" could not be located!^ \
  18307.                #endif                                                            \
  18308.                {$Name}             ;;"output" the "runtime" file name
  18309.  
  18310. Now the image-based macros might look like: 
  18311.  
  18312.     ;--- Check if Graphic exists ------------------------------------------------
  18313.     #option    PUSH LineContinuation="NULL"      ;;Next line ends with continuation char!
  18314.     #define    MyLocalGraphicsDirectory    C:\PROJECTS\HOMEPAGE\GRAPHICS\
  18315.     #option    POP                               ;;Restore original continuation char
  18316.     #define    MyRemoteGraphicsDirectory   graphics/
  18317.     #define    UseGraphic                                                        \
  18318.                <$CheckResource LocalName=^<$MyLocalGraphicsDirectory>{$SNAME}^   \
  18319.                                     Name=^<$MyRemoteGraphicsDirectory>{$SNAME}^  \
  18320.                >
  18321.  
  18322. And to use the macro becomes automatic and simple: 
  18323.  
  18324.     <IMG SRC="<$UseGraphic SNAME='fred.gif'>">
  18325.  
  18326. Note that I kept the "UseGraphic" macro simple for demonstration purposes, for 
  18327. my purposes I would create a higher level "img" macro which not only validated 
  18328. the file exists but used GetImageHeightWidth() (by default) to automatically 
  18329. calculate the image size. Other "img" tag parameters could be passed as macro 
  18330. parameters (with suitable defaults). 
  18331.  
  18332. An HTML validation version would be slightly more complex than the above, since 
  18333. you would probably wish to also handle the "#location" suffix. The simplest 
  18334. (and maybe best) way to handle it might be just to have a new optional 
  18335. parameter. Another complication is that you would probably look for a local 
  18336. file with the extension ".IT", again exactly how it looks is really a personal 
  18337. preference. 
  18338.  
  18339. An Alternative Way - #2 
  18340.  
  18341. Under OS/2 there is a free URL checking program which can be given a list of 
  18342. URLs to check. Similar programs will exist for other operating systems. 
  18343.  
  18344. You could create a ".URL" file for each HTML page and have your macros not only 
  18345. check that everything is fine locally, but add each URL in turn to the new file 
  18346. (deleted at start of build). Later, when online and after updating your web 
  18347. site, you could run the lists through the URL checking program. 
  18348.  
  18349. Case Sensitivity 
  18350.  
  18351. None of the code shown actually checks the case of the filename so it's 
  18352. possible that although the code shows that the file exists locally, if copied 
  18353. to a unix server a "browser" will not find the file. There are a number of 
  18354. changes you can make to check the case or, even simpler, to transfer the files 
  18355. to the unix server in lower case and ensure that you refer to the files in 
  18356. lower case. 
  18357.  
  18358. SiteCopy 
  18359.  
  18360. So as to be very sure that you never forget to correctly update your web site 
  18361. you can use an automated tool such as "SiteCopy" to FTP new or modified files 
  18362. and directories. It will also delete obsolete files and directories. 
  18363.  
  18364. This tool is a bit rough around the edges but it is free and if you provide the 
  18365. developers with constructive feedback they will probably listen. I am using 
  18366. this tool for my site updating. 
  18367.  
  18368. There are OS/2, Windows, and other ports of the unix program; the main sitecopy 
  18369. page is at http://www.lyra.org/sitecopy/. 
  18370.  
  18371. I recommend that Windows users download my "SITECPY" download as this has been 
  18372. repackaged so it is a breeze to install and setup and does not require command 
  18373. line access for typical tasks. It is available from 
  18374. http://www.labyrinth.net.au/~dbareis/freew32.htm. 
  18375.  
  18376.  
  18377. ΓòÉΓòÉΓòÉ 16.9. SHARING HEADERS - HTML + REXX CGI ΓòÉΓòÉΓòÉ
  18378.  
  18379. SHARING HEADERS - HTML + REXX CGI 
  18380.  
  18381. Whenever you use the #define command to define something you have already 
  18382. decided (whether or not you realise it) the contexts it can be used in. 
  18383.  
  18384. As an example, you could create a definition which expands to a filename 
  18385. surrounded by double quotes; this can only be used in situations where the 
  18386. double quotes are required (or won't interfere). Your other major choice was 
  18387. not to supply double quotes; this then requires you to supply double quotes 
  18388. when used in situations where the quotes are required. 
  18389.  
  18390. Sometimes you can have a mismatch between "languages" which mean that you will 
  18391. need to get "tricky" when creating definitions when a header file is shared, 
  18392. such as where a common header file is shared between HTML and REXX code (server 
  18393. CGI script for example). 
  18394.  
  18395. You should understand that PPWIZARD has a /CGI mode, this example does not 
  18396. cover this at all. The REXX CGI script discussed in this example is generated 
  18397. by PPWIZARD and placed onto the web server for execution. When the /CGI mode is 
  18398. used, the header sharing issues discussed here, along with the solutions, are 
  18399. not relevant and in a lot of cases using this switch may be the simplest 
  18400. solution. 
  18401.  
  18402. Some REXX CGI / HTML Issues 
  18403.  
  18404.        1. REXX has a limit on the size of a literal. So if you had a standard 
  18405.           HTML footer which successfully expands to 2000 characters in a HTML 
  18406.           document, simply putting quotes around the text for REXX would result 
  18407.           in a 2000 byte literal. The limit is more likely to be around 250 
  18408.           bytes! 
  18409.  
  18410.        2. In a REXX CGI script it may be that some substituted text (macro 
  18411.           parameter) may not be known until runtime whereas with HTML you are 
  18412.           likely to be able to "hard code" it. 
  18413.  
  18414.        3. Some REXX interpreters also have a limit on the maximum length of a 
  18415.           command. 
  18416.  
  18417.        4. There may be a maximum line limit in some REXX interpreters. 
  18418.  
  18419.  EXAMPLE - COMMON HEADER 
  18420.  
  18421.   ;--- We need to get tricky to use some LONG macros in rexx code -------------
  18422.   #if  ['<?ProcessingMode>' = 'REXX']
  18423.        ;--- We are generating REXX code (take care of OS/2 & REGINA restrictions on lengths of literals and clauses) ---
  18424.        #define   RexxAssignTo CgiVar           ;;The user must assign macro to this variable
  18425.        #define   RexxQuote  ' || "'" || '      ;;Used in place of any single quotes
  18426.        #define   RexxConcat ';<?NewLine><$RexxAssignTo> = <$RexxAssignTo> || '                 ;;End old & start new literal
  18427.   #elseif
  18428.        ;--- We are generating HTML --------------------------------------------
  18429.        #define   RexxQuote    '                ;;Simply expand to single quote
  18430.        #define   RexxConcat
  18431.   #endif
  18432.  
  18433.  In the above "RexxConcat" is designed to be used "every so often" (within 
  18434.  REXX's literal limit). When expanding in HTML it does nothing. In REXX code it 
  18435.  finishes off the literal, statement and line then starts another. 
  18436.  
  18437.  The "RexxQuote" is designed to be used in place of any single quotes you might 
  18438.  wish to output in the expanded text. There should be few of these as you will 
  18439.  try to use double quotes everywhere. 
  18440.  
  18441.  The following shows how a large macro might make use of the above definitions 
  18442.  (note that a lot of external macros are referenced which are not shown): 
  18443.  
  18444.   ;--- Define Headings --------------------------------------------------------
  18445.   #define TitleHtml                                                        \
  18446.           ;--- Start Html ------------------------------------------      -\
  18447.           <HTML>                                                          -\
  18448.           <HEAD>                                                          -\
  18449.           <$HtmlDebugNL>                                                  -\
  18450.           <TITLE>{$Title=^{$Text}^}</TITLE>                               -\
  18451.           #if '{$OTHERHEADER_TAGS=^^}' <> ''                              -\
  18452.                <$HtmlDebugNL>                                             -\
  18453.                {$OTHERHEADER_TAGS=^^}                                     -\
  18454.           #endif                                                          -\
  18455.           <$HtmlDebugNL>                                                  -\
  18456.           </HEAD>                                                         -\
  18457.                                                                           -\
  18458.           ;--- Set up Body tag -------------------------------------      -\
  18459.           <$HtmlDebugNL>                                                  -\
  18460.           <$BodyStandardOs2Warp>                                          -\
  18461.           <$RexxConcat>                                                   -\
  18462.                                                                           -\
  18463.           ;--- Now output the standard heading bar -----------------      -\
  18464.           <$BsdHeadingBar TEXT=^{$Text=^Branch Systems Development^}^>
  18465.   #define BsdHeadingBar                                                    \
  18466.           ;--- Put Heading of page into a TABLE --------------------      -\
  18467.           <$HtmlDebugNL>                                                  -\
  18468.           <$HtmlDebugComment TEXT="Start of Heading Bar">                 -\
  18469.           <TABLE WIDTH=100% BORDER=0                                       \
  18470.                  BGCOLOR=<$BsdColorBgTitleAndNavigation>                   \
  18471.                  CELLSPACING=0 CELLPADDING=5                              -\
  18472.           >                                                               -\
  18473.           <$HtmlDebugNL>                                                  -\
  18474.           <$RexxConcat>                                                   -\
  18475.           <TR>                                                            -\
  18476.              ;--- All left hand images in one cell -------                -\
  18477.              <$HtmlDebugComment TEXT="All right hand images into 1 cell"> -\
  18478.              <TD ALIGN=LEFT>                                              -\
  18479.              <TABLE BORDER=0 CELLSPACING=0                                 \
  18480.                     CELLPADDING=1  ;;Set Image spacing                    -\
  18481.              >                                                            -\
  18482.              <TR>                                                         -\
  18483.                  ;--- Link To Intranet home page --------------           -\
  18484.                  <$HtmlDebugComment TEXT="Go to Intranet Homepage">       -\
  18485.                  <TD ALIGN=LEFT>                                          -\
  18486.                      <A HREF="<$IntranetHomePage>" TARGET=_top>           -\
  18487.                      <$IntranetImgHeaderAnz>                              -\
  18488.                      </A>                                                 -\
  18489.                  </TD>                                                    -\
  18490.                  <$RexxConcat>                                            -\
  18491.                                                                           -\
  18492.                  ;--- Link To BSD home page --------------                -\
  18493.                  <$HtmlDebugComment TEXT="Go to BSD Homepage">            -\
  18494.                  <TD ALIGN=LEFT>                                          -\
  18495.                      <A HREF="<$BsdHomePage>" TARGET=_top>                -\
  18496.                      <$BsdImgBsdHome>                                     -\
  18497.                      </A>                                                 -\
  18498.                  </TD>                                                    -\
  18499.                  <$RexxConcat>                                            -\
  18500.                                                                           -\
  18501.              ;--- End of left hand images TABLE ----------                -\
  18502.              <$HtmlDebugNL>                                               -\
  18503.              </TABLE>                                                     -\
  18504.              </TD>                                                        -\
  18505.                                                                           -\
  18506.              ;--- Output title of this page ---------------               -\
  18507.              <$HtmlDebugComment TEXT="Title of this page">                -\
  18508.              <TD ALIGN=MIDDLE><FONT COLOR=<$BsdColorFgTitle>               \
  18509.                  SIZE={$FONTSIZE="+2"}                                    -\
  18510.              >                                                            -\
  18511.                  <B><CENTER><STRONG>                                      -\
  18512.                  {$Text=^Branch Systems Development^}                     -\
  18513.                  </STRONG></CENTER></FONT></B>                            -\
  18514.              </TD>                                                        -\
  18515.              <$RexxConcat>                                                -\
  18516.                                                                           -\
  18517.              ;--- All right hand images in one cell -------               -\
  18518.              <$HtmlDebugComment TEXT="All right hand images into 1 cell"> -\
  18519.              <TD ALIGN=RIGHT>                                             -\
  18520.              <TABLE BORDER=0 CELLSPACING=0                                 \
  18521.                     CELLPADDING=1  ;;Set Image spacing                    -\
  18522.              >                                                            -\
  18523.              <TR>                                                         -\
  18524.                  ;--- Link to search for phone number ---------           -\
  18525.                  <$HtmlDebugComment TEXT="Link to Intranet Phone Search"> -\
  18526.                  <TD>                                                     -\
  18527.                      <A HREF="<$IntranetPhoneSearchPage>" TARGET=_top>    -\
  18528.                         <$IntranetImgHeaderPhone>                         -\
  18529.                      </A>                                                 -\
  18530.                  </TD>                                                    -\
  18531.                  <$RexxConcat>                                            -\
  18532.                                                                           -\
  18533.                  ;--- Link to Site Information ----------------           -\
  18534.                  <$HtmlDebugComment TEXT="Link to Intranet Site Info">    -\
  18535.                  <TD>                                                     -\
  18536.                      <A HREF="<$IntranetSiteInfoPage>" TARGET=_top>       -\
  18537.                      <$IntranetImgHeaderSiteInfo>                         -\
  18538.                      </A>                                                 -\
  18539.                  </TD>                                                    -\
  18540.                  <$RexxConcat>                                            -\
  18541.                                                                           -\
  18542.                  ;--- Link to search Engine -------------------           -\
  18543.                  <$HtmlDebugComment TEXT="Link to Intranet Search">       -\
  18544.                  <TD>                                                     -\
  18545.                      <A HREF="<$IntranetSiteSearchPage>" TARGET=_top>     -\
  18546.                      <$IntranetImgHeaderSiteSearch>                       -\
  18547.                      </A>                                                 -\
  18548.                  </TD>                                                    -\
  18549.                  <$RexxConcat>                                            -\
  18550.                                                                           -\
  18551.              ;--- End of right hand images TABLE ----------               -\
  18552.              <$HtmlDebugNL>                                               -\
  18553.              </TABLE>                                                     -\
  18554.              </TD>                                                        -\
  18555.                                                                           -\
  18556.           ;--- End of Heading Row/Table -------------------               -\
  18557.           </TR>                                                           -\
  18558.           </TABLE>                                                        -\
  18559.           <$HtmlDebugNL>                                                  -\
  18560.           <$HtmlDebugNL>
  18561.   #define Title                                                            \
  18562.           {$Rule="<P><HR>"}                                               -\
  18563.           #if  ['{$ID=''}' <> '']                                         -\
  18564.                <A NAME="{$ID=''}"></A>    ;;User wants to name this posn  -\
  18565.           #endif                                                          -\
  18566.           <CENTER><H2><FONT COLOR=<$BsdColorBgTitleAndNavigation>>        -\
  18567.           {$Text}                                                         -\
  18568.           </FONT></H2></CENTER>
  18569.  
  18570.  The following show how one of the macros could be used to generate a title in 
  18571.  HTML: 
  18572.  
  18573.   <$TitleHtml Text=^The Title of the Page^ FONTSIZE=^+2^>
  18574.  
  18575.  The following shows how one of the macros could be used to generate a title in 
  18576.  a REXX CGI script (needs to be written to stdout): 
  18577.  
  18578.   /*--- Get dummy title (set up at compile - of rexx source - time) ---*/
  18579.   #define+   RexxAssignTo    NewLineVar
  18580.   NewLineVar = '<$TitleHtml Text=^$DUMMY$^ FONTSIZE=^+2^>';
  18581.  
  18582.   /*--- Convert to real title and output (done at CGI runtime) --------*/
  18583.   NewLineVar = ReplaceString(NewLineVar, '$DUMMY$', RealTitle);
  18584.   say NewLineVar;
  18585.  
  18586.  Note that the ReplaceString() used above is not PPWIZARD's, as of course at 
  18587.  runtime it is unavailable. My website contains the source code for this and 
  18588.  many other handy routines. 
  18589.  
  18590.  
  18591. ΓòÉΓòÉΓòÉ 16.10. TEXTEDIT with PPWIZARD ΓòÉΓòÉΓòÉ
  18592.  
  18593. TEXTEDIT with PPWIZARD 
  18594.  
  18595. I have another handy program called TEXTEDIT, it takes a text file as input. 
  18596. PPWIZARD can simplify handling of any text file and this example shows how I 
  18597. have used it to create some "macro" commands that not only simplifies the 
  18598. syntax but checks the return code (TEXTEDIT aborts on error). 
  18599.  
  18600. The code shown here is a small fragment of what I use to completely 
  18601. automatically extract menus, dialogs, etc., out of Netscape and modify or 
  18602. delete controls, then put the modified resources back into Netscape. 
  18603.  
  18604. DLG102.TE - The MAIN Program 
  18605.  
  18606. ;--------------------------------------------------------
  18607. ;--- Edits dialog 102 of Netscape 4.04 "Communicator" ---
  18608. ;--------------------------------------------------------
  18609.  
  18610. ;--- Include header file ----------------------------------------------------
  18611. #include   "DIALOG.H"
  18612.  
  18613. ;--- Disable Choose file button ---------------------------------------------
  18614. <$DisableControlLineGivenMiddle LINE=^<$DLG_CHOOSE_FILE>^>
  18615.  
  18616. ;--- Disable "Composer" radio button ----------------------------------------
  18617. <$DisableControlLineGivenMiddle LINE=^<$DLG_COMPOSER>^>
  18618.  
  18619. ;--- Thats all Folks! -------------------------------------------------------
  18620. <$WriteFile>
  18621.  
  18622. DIALOG.H - Dialog Specific Header 
  18623.  
  18624. ;--- Include generic stuff -------------------------------------------------
  18625. #include "TEXTEDIT.H"
  18626.  
  18627. ;--- Constants -------------------------------------------------------------
  18628. #define DLG_CHOOSE_FILE         Choose ~File
  18629. #define DLG_COMPOSER            ~Composer
  18630.  
  18631. ;--- Disable Control -------------------------------------------------------
  18632. #define DisableControlLineGivenMiddle                                            \
  18633.         ReplaceLines {$COUNT="1"} ^*{$LINE}*^ ^${ReplacedLine}, WS_DISABLED^    %\
  18634.         <?Hash>if  '${Rc}' <> '0'                                               %\
  18635.                @exit 255 'Could not find a control line matching = "*{$LINE}*"' %\
  18636.         <?Hash>endif
  18637.  
  18638. TEXTEDIT.H - Generic Header (for dialogs, menus etc) 
  18639.  
  18640. ;--- Macro to delete a line ------------------------------------------------
  18641. #define DeleteLineGivenMiddle                                            \
  18642.         DeleteBlock ^*{$LINE}*^   ^*{$LINE}*^                           %\
  18643.         <?Hash>if  '${Rc}' <> '0'                                       %\
  18644.                @exit 255 'Could not find a line matching = "*{$LINE}*"' %\
  18645.         <?Hash>endif
  18646.  
  18647. ;--- Write changed data to file --------------------------------------------
  18648. #define WriteFile                                            \
  18649.         ;--- Pretty up the final code (easier to read) ---  %\
  18650.         top                                                 %\
  18651.         ReplaceText 9999 "BEGIN" "{"                        %\
  18652.         ReplaceText 9999 "END"   "}"                        %\
  18653.                                                             -\
  18654.         ;--- Write the file ------------------------------  %\
  18655.         checkpoint
  18656.  
  18657. ;--- Find a line -----------------------------------------------------------
  18658. #define MustFindLineGivenMiddle                                          \
  18659.         Find {$COUNT="1"} ^*{$LINE}*^                                   %\
  18660.         <?Hash>if  '${Rc}' <> '0'                                       %\
  18661.                @exit 255 'Could not find a line matching = "*{$LINE}*"' %\
  18662.         <?Hash>endif
  18663.  
  18664.  
  18665. ΓòÉΓòÉΓòÉ 16.11. Accessing SQL DATABASES Directly ΓòÉΓòÉΓòÉ
  18666.  
  18667. Accessing SQL DATABASES Directly 
  18668.  
  18669. Note that PPWIZARD has an #import command that can probably handle most SQL 
  18670. requirements but the samples shown here are useful if you have more complex 
  18671. requirements or simply as samples for the facilities used. 
  18672.  
  18673. These examples use Mark Hessing's RexxSQL library to access the database 
  18674. program. It's free and is available for multiple operating systems and can 
  18675. access many different database programs. it's available from 
  18676. "http://www.lightlink.com/hessling/REXXSQL/". 
  18677.  
  18678. Note that the routine ErrorSQL() has been provided specifically for your use 
  18679. when accessing SQL databases directly as shown here. 
  18680.  
  18681. Example #1 
  18682.  
  18683. This example was developed and tested under Windows 2000, accessing a Microsoft 
  18684. Access 2000 database. While it shows how to obtain the rows it is a bit 
  18685. simplistic in that all it does is display the description column of each row 
  18686. matching the query. In real life you would probably be creating a HTML table. 
  18687.  
  18688. #NextId
  18689. #DefineRexx ''
  18690.    ;--- Load REXXSQL --------------------------------------------------------
  18691.    call LoadRexxSql
  18692.  
  18693.    /*--- Turn on debug (to maximum) --------------------------------------------*/
  18694.    @@VersionInfo = SqlVariable("VERSION")
  18695.    say @@VersionInfo;
  18696.    say copies('~', length(@@VersionInfo));
  18697.    call SqlVariable "DEBUG", 3
  18698.  
  18699.    /*--- Connect to ACCESS database -----------------------------------------*/
  18700.    @@Id           = "ConnectID";
  18701.    @@UserId       = "";
  18702.    @@Password     = "";
  18703.    @@DataSourceId = "PHASE2";           /* Defined in WIN32 "Data Sources ODBC" */
  18704.    @@Server       = '';
  18705.    if  SQLConnect(@@Id, @@UserId, @@Password, @@DataSourceId, @@Server) < 0 then
  18706.        ErrorSql('Connection failed to "' || @@DataSourceId || '", have you set up an ODBC datasource (control panel)?');
  18707.  
  18708.    /*--- Specify the query --------------------------------------------------*/
  18709.    @@Select = 'SELECT * FROM Department ORDER BY Department.DepartmentDescription';
  18710.  
  18711.    /*--- Prepare query ------------------------------------------------------*/
  18712.    if  SqlPrepare('SQLQUERY', @@Select) < 0 then
  18713.        ErrorSql();
  18714.  
  18715.    ;--- Fetch first record --------------------------------------------------
  18716.    if  SqlOpen('SQLQUERY') < 0 then
  18717.        ErrorSql();
  18718.    @@FetchRc = SqlFetch('SQLQUERY');
  18719.  
  18720.    ;--- Work through all rows -----------------------------------------------
  18721.    do  while @@FetchRc > 0
  18722.        call Say 'Description =' || SqlQuery.DepartmentDescription
  18723.        @@FetchRc = SqlFetch('SQLQUERY');
  18724.    end
  18725.    if  @@FetchRc < 0 then
  18726.        ErrorSql();
  18727.  
  18728.    ;--- Close the query -----------------------------------------------------
  18729.    if  SqlClose('SQLQUERY') < 0 then
  18730.        ErrorSql();
  18731.    if  SqlDispose('SQLQUERY') < 0 then
  18732.        ErrorSql();
  18733.  
  18734.    /*--- Disconnect from the database ------------------------------------------*/
  18735.    if  SQLDisconnect(@@Id) < 0 then
  18736.        ErrorSql('Disconnection from database failed!');
  18737. #DefineRexx
  18738.  
  18739. Example #2 
  18740.  
  18741. This example shows you how to access data using the "mSQL" (free) database 
  18742. program under OS/2. The database we will process is called "supersite" and the 
  18743. table we will access is "link". 
  18744.  
  18745. You may want to have a look at the #evaluate routines AsIs() and AutoTag(). 
  18746.  
  18747. mSQL EXAMPLE 
  18748.  
  18749. ;--- Very simplistic start of HTML ------------------------------------------
  18750. <HTML>
  18751. <BODY>
  18752. <H1>Example - Create Links List from SQL Query</H1>
  18753.  
  18754. ;--- Initialization ---------------------------------------------------------
  18755. #define QueryCategory 3             ;;This query is for this category
  18756. #define LinkTemplate <P><A HREF="{$url}">{$title}</A>: {$description}  ;;HTML for each record (note that it would be more efficient (but less "clean") to just pick up rexx variable names here
  18757.  
  18758. ;--- Enable PPWIZARD to make use of external SQL library --------------------
  18759. #evaluate  ''  "call LoadRexxSql"
  18760.  
  18761. ;--- Connect to the data base ("supersite" on local machine) ----------------
  18762. #evaluate 'ConnectRc' "SQLConnect('PPW',,, 'supersite', 'localhost')"
  18763.  
  18764. ;--- Perform a database query (on the table "link") -------------------------
  18765. #evaluate+ 'QueryRc' ^SQLCommand('RxLink', 'SELECT * FROM link WHERE category = <$QueryCategory>')^
  18766. #info      'QueryRc = <$QueryRc>'
  18767. #info      'Number of records is <??RxLink.url.0>'
  18768.  
  18769. ;--- Generate the html (for simple list) ------------------------------------
  18770. <UL>                            ;;Start of list
  18771. #RexxVar RxCount = 1            ;;Initialize record counter (rexx variable)
  18772. #{                              ;;Start of loop
  18773.    #if ['<??RxCount>' <= '<??RxLink.url.0>']
  18774.        ;--- Use previously defined macro (template) to generate output ------
  18775.        <$LinkTemplate url="<??RxLink.url.RxCount>" title=^<??RxLink.title.RxCount>^ description=^<??RxLink.description.RxCount>^>
  18776.        #RexxVar RxCount + 1     ;;Update record counter
  18777.    #elseif
  18778.        #break
  18779.    #endif
  18780. #}                              ;;End of loop
  18781. </UL>                           ;;End of list
  18782.  
  18783. ;--- Disconnect the data base -----------------------------------------------
  18784. #evaluate 'DisConnectRc' "SQLDisconnect('PPW')"
  18785.  
  18786. ;--- Very simple end of HTML ------------------------------------------------
  18787. <P>
  18788. <HR>
  18789. <CENTER>End of simple SQL IMPORT Example</CENTER>
  18790. </BODY>
  18791. </HTML>
  18792.  
  18793.  
  18794. ΓòÉΓòÉΓòÉ 16.12. Rexx Preprocessing ΓòÉΓòÉΓòÉ
  18795.  
  18796. Rexx Preprocessing 
  18797.  
  18798. This program, while mainly designed for HTML processing, could be used for most 
  18799. languages.  It has specific support built in for the preprocessing of REXX 
  18800. code. 
  18801.  
  18802. REXX code is, by default, packed.  This makes the resultant ".CMD" file much 
  18803. smaller than the original code and in many cases this would be enough of a 
  18804. reason to use it (although the packing is irrelevant if you then compile the 
  18805. ".CMD" into a ".EXE" using my REXX compiler). Also note that the packing will 
  18806. not speed up the execution of your code although it may slightly speed up the 
  18807. initial tokenization. 
  18808.  
  18809. If you examine the small example, you will notice that I used "#ifdef" commands 
  18810. to determine which parts of the header file I wished to include.  You could 
  18811. easily extend this concept to allow debug code to be added only when you wish 
  18812. to debug or have variations on error handling (log the message, ignore it, 
  18813. etc.).  I don't normally define my subroutines as procedures because in my 
  18814. opinion the disadvantages of the way REXX does it outweigh the advantages. My 
  18815. example header file has been written so that the user of the subroutines can 
  18816. determine not only whether they should be procedures but what variables they 
  18817. should expose if they are! 
  18818.  
  18819. MORE ON PACKING 
  18820.  
  18821. The preprocessor packs well written code (by my definition!) and can fail to 
  18822. correctly pack code where strings are appended without the use of the "||" 
  18823. operator (as the excess spaces will be removed).  For example the following 
  18824. statement will not create the string you expect when packed: 
  18825.  
  18826.        BothPartsCombined = 'Value:'   TheValue;
  18827.  
  18828. The following statement is a version of the above that will work: 
  18829.  
  18830.         BothPartsCombined = 'Value:   ' || TheValue;
  18831.  
  18832. You can get very good results by packing but if you have got legacy code or you 
  18833. don't wish to change (your evil ways!) you should use the "/Pack:N" command 
  18834. line switch.  This turns off most packing (rexx comment and trailing ';' 
  18835. removal still occurs). 
  18836.  
  18837. If you have trouble with some parts of your code but the bulk packs well then 
  18838. you may wish to consider leaving packing on and using the AllowPack option to 
  18839. indicate parts of your rexx code that should not be packed. 
  18840.  
  18841. WARNING 
  18842.  
  18843. This has not been tested on object rexx so I don't know if it will work or not 
  18844. (I assume it will). 
  18845.  
  18846.  
  18847. ΓòÉΓòÉΓòÉ 16.12.1. Rexx Example ΓòÉΓòÉΓòÉ
  18848.  
  18849. Rexx Example 
  18850.  
  18851. Note that the REXX source code page contains much better examples. It is best 
  18852. to look at the more recently modified ones as they are more likely to be making 
  18853. use of more recently introduced features or techniques. The "AddComma" and 
  18854. "PPWSORT" are two packages well worth studying. 
  18855.  
  18856. The following batch file was used to generate the REXX code: 
  18857.  
  18858. @echo off
  18859. rem set DEBUG=/debug
  18860. out\ppwizard.rex REXAMPLE.X /output:out\REXAMPLE.REX /rexx
  18861.  
  18862.  
  18863. The source files are: 
  18864.  
  18865.        1. REXAMPLE.X 
  18866.        2. REXAMPLE.XH 
  18867.  
  18868.  The generated REXX code is: 
  18869.  
  18870.        1. REXAMPLE.REX 
  18871.  
  18872.  
  18873. ΓòÉΓòÉΓòÉ 16.12.1.1. REXAMPLE.X ΓòÉΓòÉΓòÉ
  18874.  
  18875. REXAMPLE.X 
  18876.  
  18877. ;----------------------------------------------------------------------------
  18878. ;    MODULE NAME:   REXAMPLE.X
  18879. ;
  18880. ;        $Author:   USER "Dennis"  $
  18881. ;      $Revision:   1.0  $
  18882. ;          $Date:   30 Mar 2001 18:05:34  $
  18883. ;       $Logfile:   C:/DBAREIS/Projects.PVCS/MultiOs/PPWIZARD/rexample.x.pvcs  $
  18884. ;
  18885. ;    DESCRIPTION:   Small example routine.
  18886. ;
  18887. ;----------------------------------------------------------------------------
  18888.  
  18889. /*--- Want the following comment in the generated output --------------------*/
  18890. /*
  18891.  * $Header:   C:/DBAREIS/Projects.PVCS/MultiOs/PPWIZARD/rexample.x.pvcs   1.0   30 Mar 2001 18:05:34   USER "Dennis"  $
  18892.  */
  18893.  
  18894.  
  18895. /*--- I want all my routines to (1) be procedures & (2) Expose some variables ---*/
  18896. #define Procedure  procedure expose Variable1 Variable2
  18897.  
  18898.  
  18899. /*--- Load supporting routines ----------------------------------------------*/
  18900. #define  INCL_StringReplace
  18901. #define  INCL_AddCommas2DecimalNumber
  18902. #include "REXAMPLE.XH"
  18903.  
  18904.  
  18905. /*--- Make a few changes and Generate the output message --------------------*/
  18906. Count  = 0;                                             ;;Initialize Counter (this is a PPWIZARD comment)
  18907. String = StringReplace('AAAA', 'A', 'B', "Count");      /* Make some changes (this is a REXX comment) */
  18908. if Count = 0 then
  18909.    say 'No Changes made';
  18910. else
  18911.    say 'Count = ' || AddCommas2DecimalNumber(Count);
  18912. return(Count);
  18913.  
  18914.  
  18915. ΓòÉΓòÉΓòÉ 16.12.1.2. REXAMPLE.XH ΓòÉΓòÉΓòÉ
  18916.  
  18917. REXAMPLE.XH 
  18918.  
  18919. ;----------------------------------------------------------------------------
  18920. ;    MODULE NAME:   REXAMPLE.XH
  18921. ;
  18922. ;        $Author:   USER "Dennis"  $
  18923. ;      $Revision:   1.0  $
  18924. ;          $Date:   30 Mar 2001 18:05:34  $
  18925. ;       $Logfile:   C:/DBAREIS/Projects.PVCS/MultiOs/PPWIZARD/rexample.xh.pvcs  $
  18926. ;
  18927. ;    DESCRIPTION:   Small example header file.
  18928. ;
  18929. ;----------------------------------------------------------------------------
  18930.  
  18931. /*
  18932.  * $Header:   C:/DBAREIS/Projects.PVCS/MultiOs/PPWIZARD/rexample.xh.pvcs   1.0   30 Mar 2001 18:05:34   USER "Dennis"  $
  18933.  */
  18934.  
  18935. /*--- Something in this header needs a feature introduced in "99.249" -------*/
  18936. #require   99.249
  18937.  
  18938. /*--- Skip past rexx routines -----------------------------------------------*/
  18939. <?RexxSkip>
  18940.  
  18941.  
  18942. #ifdef INCL_AddCommas2DecimalNumber
  18943. /*===========================================================================*/
  18944. AddCommas2DecimalNumber:                                   /* Integers Only! */
  18945.                        #ifdef Procedure
  18946.                               <$Procedure>
  18947.                        #endif
  18948. /*===========================================================================*/
  18949.    /*--- Get number return it it we already have commas ---------------------*/
  18950.    #NextId
  18951.    @@NoComma = strip( arg(1) );
  18952.    if  pos(',', @@NoComma) <> 0 then
  18953.        return(@@NoComma);
  18954.  
  18955.    /*--- split at possible decimal point ------------------------------------*/
  18956.    @@DotPos = pos('.', @@NoComma);
  18957.    if  @@DotPos = 0 then
  18958.        @@AfterDecimal = '';
  18959.    else
  18960.    do
  18961.        /*--- There is a decimal component -----------------------------------*/
  18962.        if  @@DotPos = 1 then
  18963.            return("0" || @@NoComma);
  18964.        @@AfterDecimal = substr(@@NoComma, @@DotPos+1);
  18965.        @@NoComma      = left(@@NoComma, @@DotPos-1);
  18966.    end;
  18967.  
  18968.    /*--- Reverse the integer ------------------------------------------------*/
  18969.    @@NoComma = reverse(@@NoComma);
  18970.  
  18971.    /*--- Grab 3 digits at a time --------------------------------------------*/
  18972.    @@ResultWithCommas = "";
  18973.    do  while length(@@NoComma) > 3
  18974.        @@ResultWithCommas = @@ResultWithCommas || left(@@NoComma, 3) || ',';
  18975.        @@NoComma          = substr(@@NoComma, 4);
  18976.    end;
  18977.    @@ResultWithCommas = @@ResultWithCommas || @@NoComma;
  18978.  
  18979.    /*--- Reverse the string and add decimal component -----------------------*/
  18980.    @@ResultWithCommas = reverse(@@ResultWithCommas)
  18981.    if  @@AfterDecimal <> '' then
  18982.        @@ResultWithCommas = @@ResultWithCommas || '.' || @@AfterDecimal;
  18983.    return(@@ResultWithCommas);
  18984. #endif
  18985.  
  18986.  
  18987.  
  18988. #ifdef INCL_GetAmPmTime
  18989. /*===========================================================================*/
  18990. GetAmPmTime:                         /* Fixed length AM/PM time with seconds */
  18991.                        #ifdef Procedure
  18992.                               <$Procedure>
  18993.                        #endif
  18994. /*===========================================================================*/
  18995.    #NextId
  18996.    @@CivilTime  = time('C');  if length(@@CivilTime)  = 6 then @@CivilTime=' '@@CivilTime;
  18997.    @@NumSeconds = ':'substr(time(), 7, 2);
  18998.    return( insert(@@NumSeconds, @@CivilTime, 5) );       /* Insert # seconds */
  18999. #endif
  19000.  
  19001.  
  19002.  
  19003. #ifdef INCL_StringReplace
  19004. /*===========================================================================*/
  19005. StringReplace:               /* Too tricky & limiting to set up as procedure */
  19006. /*===========================================================================*/
  19007.    /*--- Get the passed parameters ------------------------------------------*/
  19008.    #NextId
  19009.    @@String       = arg(1);
  19010.    @@ChangeFrom   = arg(2);
  19011.    @@ChangeTo     = arg(3);
  19012.    @@ChangeCntVar = arg(4);                          /* Passed by reference! */
  19013.  
  19014.    /*--- Look for the search string -----------------------------------------*/
  19015.    @@ChangeFromLength = length(@@ChangeFrom);
  19016.    @@ChangeToLength   = length(@@ChangeTo);
  19017.    @@FoundPosn        = pos(@@ChangeFrom, @@String);
  19018.    @@ChangesMade      = 0;
  19019.    do  while @@FoundPosn <> 0
  19020.        /*--- Perform the substitution ---------------------------------------*/
  19021.        @@String = left(@@String, @@FoundPosn-1) || @@ChangeTo || substr(@@String, @@FoundPosn+@@ChangeFromLength);
  19022.  
  19023.        /*--- Look for the more occurances of the search string --------------*/
  19024.        @@FoundPosn = pos(@@ChangeFrom, @@String, @@FoundPosn+@@ChangeToLength);
  19025.        @@ChangesMade = @@ChangesMade + 1;
  19026.    end;
  19027.  
  19028.    /*--- Update the change counter and return to the caller -----------------*/
  19029.    if  @@ChangeCntVar <> "" then
  19030.        interpret @@ChangeCntVar || " = @@ChangesMade + " || @@ChangeCntVar;
  19031.    return(@@String);
  19032. #endif
  19033.  
  19034.  
  19035.  
  19036. /*--- End of header file ----------------------------------------------------*/
  19037. <?RexxSkipTo>
  19038.  
  19039.  
  19040. ΓòÉΓòÉΓòÉ 16.12.1.3. REXAMPLE.REX (generated output) ΓòÉΓòÉΓòÉ
  19041.  
  19042. REXAMPLE.REX (generated output) 
  19043.  
  19044. /*
  19045.  * Generator   : PPWIZARD version 01.059
  19046.  *             : FREE tool for Windows, OS/2, DOS and UNIX by Dennis Bareis (dbareis@labyrinth.net.au)
  19047.  *             : http://www.labyrinth.net.au/~dbareis/ppwizard.htm
  19048.  * Time        : Wednesday, 28 Feb 2001 5:45:26pm
  19049.  * Input File  : C:\DBAREIS\Projects\MultiOs\PPWIZARD\rexample.x
  19050.  * Output File : out\REXAMPLE.REX
  19051.  */
  19052.  
  19053. if arg(1)="!CheckSyntax!" then exit(21924)
  19054.  
  19055. /*
  19056. * $Header:   C:/DBAREIS/Projects.PVCS/MultiOs/PPWIZARD/rexample.x.pvcs   1.0   14 Dec 2000 19:45:24   Dennis  $
  19057. */
  19058. /*
  19059. * $Header:   C:/DBAREIS/Projects.PVCS/MultiOs/PPWIZARD/rexample.xh.pvcs   1.0   14 Dec 2000 19:45:24   Dennis  $
  19060. */
  19061. signal REXAMPLE_1
  19062.  
  19063. AddCommas2DecimalNumber:
  19064. procedure expose Variable1 Variable2
  19065. z1_NoComma = strip( arg(1) )
  19066. if  pos(',', z1_NoComma) <> 0 then
  19067. return(z1_NoComma)
  19068. z1_DotPos = pos('.', z1_NoComma)
  19069. if  z1_DotPos = 0 then
  19070. z1_AfterDecimal = ''
  19071. else
  19072. do
  19073. if  z1_DotPos = 1 then
  19074. return("0" || z1_NoComma)
  19075. z1_AfterDecimal = substr(z1_NoComma, z1_DotPos+1)
  19076. z1_NoComma      = left(z1_NoComma, z1_DotPos-1)
  19077. end
  19078. z1_NoComma = reverse(z1_NoComma)
  19079. z1_ResultWithCommas = ""
  19080. do  while length(z1_NoComma) > 3
  19081. z1_ResultWithCommas = z1_ResultWithCommas || left(z1_NoComma, 3) || ','
  19082. z1_NoComma          = substr(z1_NoComma, 4)
  19083. end
  19084. z1_ResultWithCommas = z1_ResultWithCommas || z1_NoComma
  19085. z1_ResultWithCommas = reverse(z1_ResultWithCommas)
  19086. if  z1_AfterDecimal <> '' then
  19087. z1_ResultWithCommas = z1_ResultWithCommas || '.' || z1_AfterDecimal
  19088. return(z1_ResultWithCommas)
  19089.  
  19090. StringReplace:
  19091. z2_String       = arg(1)
  19092. z2_ChangeFrom   = arg(2)
  19093. z2_ChangeTo     = arg(3)
  19094. z2_ChangeCntVar = arg(4)
  19095. z2_ChangeFromLength = length(z2_ChangeFrom)
  19096. z2_ChangeToLength   = length(z2_ChangeTo)
  19097. z2_FoundPosn        = pos(z2_ChangeFrom, z2_String)
  19098. z2_ChangesMade      = 0
  19099. do  while z2_FoundPosn <> 0
  19100. z2_String = left(z2_String, z2_FoundPosn-1) || z2_ChangeTo || substr(z2_String, z2_FoundPosn+z2_ChangeFromLength)
  19101. z2_FoundPosn = pos(z2_ChangeFrom, z2_String, z2_FoundPosn+z2_ChangeToLength)
  19102. z2_ChangesMade = z2_ChangesMade + 1
  19103. end
  19104. if  z2_ChangeCntVar <> "" then
  19105. interpret z2_ChangeCntVar || " = z2_ChangesMade + " || z2_ChangeCntVar
  19106. return(z2_String)
  19107.  
  19108. REXAMPLE_1:
  19109. Count  = 0
  19110. String = StringReplace('AAAA', 'A', 'B', "Count")
  19111. if Count = 0 then
  19112. say 'No Changes made'
  19113. else
  19114. say 'Count = ' || AddCommas2DecimalNumber(Count)
  19115. return(Count)
  19116.