home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / ppwidoco.zip / ppwizard.inf (.txt)
OS/2 Help File  |  1999-11-25  |  426KB  |  15,550 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 works under: 
  8.  
  9.        1. OS/2 
  10.        2. Windows NT 
  11.        3. Windows 95 
  12.        4. Windows 3.1 (use DOS) 
  13.        5. DOS 
  14.        6. UNIX (tested on Linux) 
  15.  
  16.  PPWIZARD is more powerful than virtually any other preprocessor available and 
  17.  unlike many others remains simple to use (no complicated syntax), its 
  18.  replacement syntax is HTML like. 
  19.  
  20.  The free "Regina" interpreter is required for operating systems other than 
  21.  OS/2. 
  22.  
  23.  This preprocessor is commonly used as a HTML preprocessor as well as a rexx 
  24.  preprocessor however there is no reason why this one preprocessor can't handle 
  25.  almost any file you have around (example you can change preprocessor to use 
  26.  "!if" etc and leave "#if" commands alone if you wish.  You may wish to have a 
  27.  look at my HTML/IPF document creation example. This method was used to create 
  28.  both the HTML and IPF versions of the documentation you are now viewing. 
  29.  
  30.  Most people would probably find the #include and #define commands the most 
  31.  useful as they could be used to ensure that you need never specify something 
  32.  more than once.  For example you might refer to a specific link (or image) in 
  33.  tens of places in different html pages but you can define it in one place. 
  34.  When you need to change it you make the one change and regenerate the html. 
  35.  Its not just easier and fast, it eliminates mistakes. You could set up your 
  36.  source and have automatic checking of the existance of any resources on your 
  37.  web page (no incorrect links). 
  38.  
  39.  The "#if" support is much more powerful than that of any other preprocessor 
  40.  due to the fact that what it executes is rexx code, what this means is that 
  41.  any rexx expression can be called including your own rexx procedures.  The 
  42.  "#evaluate" command allows you to parse files or do whatever you need to to 
  43.  obtain the text you wish to use in your HTML. 
  44.  
  45.  You can use this program to produce different versions of your html pages for 
  46.  different locations.  For example for an offline copy you may not want to have 
  47.  links to internet sites or have different links.  The preprocessor could be 
  48.  used in conjunction with a HTML editor however it is most useful for power 
  49.  users.  You may wish to check out "http://www.yoursite.co.uk/os/2/webwriter/" 
  50.  as this beta tool has specific support for this preprocessor. 
  51.  
  52.  This tool can be used to automatically calculate image widths and heights, 
  53.  file sizes or file dates and times and basically do all the drudge work (the 
  54.  stuff most likely to otherwise quickly become out of date). 
  55.  
  56.  By default excess leading spaces are removed from the output file so that you 
  57.  can format the input as much as you like without impacting download speed. 
  58.  
  59.  If you can't explain why an error message is being displayed or your code is 
  60.  not generated as you'd expect then I highly recommend you try the "/debug" 
  61.  command line switch.  I'd also like the debug output if you report problems. 
  62.  
  63.  If you have used a previous version of the preprocessor then I'd recommended 
  64.  you examine the change history section to determine what changes might effect 
  65.  you. 
  66.  
  67.  Please see my web page at http://www.labyrinth.net.au/~dbareis/ppwizard.htm 
  68.  for the latest copy of this program or contact me (Dennis Bareis) via email 
  69.  (dbareis@labyrinth.net.au). I value feedback from users. 
  70.  
  71.  If the examples in this INF version of the documentation don't look correct 
  72.  (fonts overlap etc) then you have removed "Courier 8' font from your operating 
  73.  system.  Please restore it... 
  74.  
  75.  Note that I would have loved to have written this in Java, however as a 
  76.  compiled language it does not have an "interpret" instruction. Apparently 
  77.  something is being added to version 1.2 which might allow something similar, 
  78.  I'll have a look then.  The "interpret" instruction is important as it allows 
  79.  the preprocessor to be extended as well as doing a lot of work I'd otherwise 
  80.  need to do myself (and I wouldn't do it as well).  I will not be rewriting the 
  81.  preprocessor in Java (as it wouldn't be compatible with the rexx version), but 
  82.  with any luck I'd be able to write any similar future stuff in Java.... 
  83.  
  84.  
  85. ΓòÉΓòÉΓòÉ 1.1. Operating System Status ΓòÉΓòÉΓòÉ
  86.  
  87. Operating System Status 
  88.  
  89. I have ported this program to work with the free Regina interpreter (available 
  90. at "http://www.lightlink.com/hessling"). Do not try to use versions prior to 
  91. 0.08f. 
  92.  
  93. This program was originally written for native OS/2 rexx and this is where most 
  94. of my testing occurs.  My release procedure ensures that when I package up 
  95. PPWIZARD, it passes the more stingent regina syntax checking and that a small 
  96. test run generates the same code under OS/2 and Regina. 
  97.  
  98. Every so often I test the generation of my web pages under NT and do some other 
  99. testing under Linux. 
  100.  
  101. If you use this program under other operating systems and it fails (or works) 
  102. then please let me know.  If it fails then I will try to resolve it if you are 
  103. prepared to help (supply info & test). When reporting problems please run the 
  104. preprocessor with the "/debug" flag and give the the command line used, the 
  105. redirected output and the source file(s). 
  106.  
  107. Your Source 
  108.  
  109. I have made the preprocessor cross platform.  This does not mean that your 
  110. source will correctly build the output on another platform.  There are issues 
  111. that you will need to take care of to ensure that your code is cross platform 
  112. also! 
  113.  
  114. As an example of a mistake you could easily have made, you could have used the 
  115. OS/2 "filespec()" routine instead of the PPWIZARD "_filespec" call. 
  116.  
  117. Status Under OS/2 
  118.  
  119. Works like a champ! 
  120.  
  121. Regina - All Operating Systems 
  122.  
  123. Some things that are currently disabled are: 
  124.  
  125.          /FILTERINPUT 
  126.          /FILTEROUTPUT 
  127.          #MacroSpace 
  128.  
  129.  Some other situations not fully supported yet: 
  130.  
  131.          No colors used by default (except under OS/2).  You could try 
  132.           "/Color" but it may not work. 
  133.  
  134.          You should not use #UnDef on versions of regina prior to "0.08f". 
  135.  
  136.  Status Under Windows NT 
  137.  
  138.  No known issues. 
  139.  
  140.  Status Under Windows 98 
  141.  
  142.  People are happily using it under Windows 98. 
  143.  
  144.  I believe the Windows 98 has the same 3 or 4 year old bug with its command 
  145.  processor as Windows 95. 
  146.  
  147.  Status Under Windows 95 
  148.  
  149.  PPWIZARD under Windows 95 works exactly like the DOS version. 
  150.  
  151.  It appears that a bug in Windows 95 (thanks Microsoft!) might prevent you 
  152.  getting the return code and so automatically determining if everything worked 
  153.  or not. 
  154.  
  155.  Status Under Windows 3.1 
  156.  
  157.  Use DOS version. 
  158.  
  159.  Status Under DOS 
  160.  
  161.  My own web site is reasonably complex and the DOS (DPMI) version has 
  162.  successfully compiled it. 
  163.  
  164.  Had to increase DMPI memory to do my whole site in one hit (*.IT), if you have 
  165.  a similar problem just call PPWIZARD many times (maybe processing " A*.IT 
  166.  B*.IT ... K*.IT" in one go and the rest the next. You get the idea!  An even 
  167.  simpler method would be to use dependancies (/DependsOn), this way if you run 
  168.  out of memory, you simply restart the build and it will pick up from where it 
  169.  left off. 
  170.  
  171.  Status Under Unix 
  172.  
  173.  All command line switches should be specified using '-' and not '/'. 
  174.  
  175.  All my testing has been performed on Red Hat Linux 5.1 and 5.2 (using it's 
  176.  default "bash" shell as well as "csh"). 
  177.  
  178.  You will need to obtain the Regina source code and compile it.  All testing 
  179.  used the generated "rexx" program.  The source can be obtained from my 
  180.  http://www.labyrinth.net.au/~dbareis/regina.htm. 
  181.  
  182.  Note that temporary files are put into the directory identified by the "TMP" 
  183.  environment variable, you must have write access to this.  If the environment 
  184.  variable does not exist then files are placed into the "/tmp" directory. 
  185.  
  186.  As with all operating systems I am keen to fix any problems, unix is a bigger 
  187.  unknown to me with all it's different shells etc. If you have a problem, 
  188.  please use the "-debug" command line switch and redirect the commands output, 
  189.  along with the name of the shell you are using and any other relevant details. 
  190.  I will typically have a fix for you in a few days and maybe a workaround even 
  191.  faster. 
  192.  
  193.  Other Operating Systems 
  194.  
  195.  If regina works on your operating system but your operating system is not 
  196.  listed above then contact me.  If you are prepared to help (test changes etc) 
  197.  then I will try to get it to work for you. 
  198.  
  199.  
  200. ΓòÉΓòÉΓòÉ 1.2. Change History ΓòÉΓòÉΓòÉ
  201.  
  202. Change History 
  203.  
  204. I'm getting quite a bit of feedback now but most simply tells me how happy you 
  205. all are. While I do lap it all up, I would like more suggestions or bug 
  206. reports. I don't care how small a bug is (incorrect spelling, incorrectly 
  207. formatted or difficult to understand error messages). 
  208.  
  209. My aim for PPWIZARD to to be very flexible and to work the way you do. If you 
  210. have to work hard to get PPWIZARD to do what you want then I'd like to know. 
  211. Most of the changes I have made are due to the fact that as a heavy user of 
  212. PPWIZARD myself I find situations where PPWIZARD could be modified to make my 
  213. life easier. Other changes have come about because people have asked me how to 
  214. do something and I've decided I can make life simpler for everyone! I have a 
  215. very long list of possible enhancements, your feedback can ensure that 
  216. something you would like goes to the top of the list! 
  217.  
  218. In some cases people have told me what they were doing, this allows me to think 
  219. about a specific set of circumstances (rather than all possible theoretical 
  220. ones). After thinking about things a bit I have frequently enhanced PPWIZARD 
  221. before I was asked (that is I have anticipated my user's requirements). 
  222. Sometimes I also know something I've done is not perfect, but am waiting for 
  223. users to indicate a problem area before 'correcting'. 
  224.  
  225.        1. Version "Next Release" 
  226.  
  227.               You tell me, feedback please! 
  228.                Have you ever looked at a product and said "Wouldn't it be nice 
  229.                if ...", well get on your backside and send an email, make it 
  230.                so! 
  231.               Note that if you require any of the changes mentioned here for 
  232.                the next release then email me and I will either send you a copy 
  233.                or speed up its release. Also if you disagree with a change then 
  234.                tell me why, I can then think about implementing a feature which 
  235.                will do what you want in a better manner (or in worst case 
  236.                senario say "oops" and reverse the change). 
  237.               Your idea here :-). 
  238.              
  239.  
  240.        2. Version 99.329 
  241.  
  242.               PPWIZARD now supports Positional Parameters, these remove the 
  243.                need to "name" parameters. 
  244.               I have worked out a workaround to regina's annoying "clause 
  245.                length" feature. This has also prompted me to work out a better 
  246.                way of handling rexx code generation (when used as a rexx code 
  247.                preprocessor). If you define your rexx code with #DefineRexx you 
  248.                will never get the clause length message unless an individual 
  249.                line is greater than the "maximum clause length" (1,024 
  250.                characters in regina interpreters ppwizard supports). Not only 
  251.                that but any rexx code you generate will also not cause clause 
  252.                length problems. Note that regina incorrectly calls a line a 
  253.                clause. 
  254.               New line continuation code for separate with newline, new 
  255.                default code is "%\" (I should never have used the down 
  256.                arrow...). Using the old code will work for now but generate a 
  257.                warning. At some future stage this support will be removed. 
  258.               PPWCURL.CMD improved to handle "SSL" links ("https://"). 
  259.               The "{$Parm-}" format no longer exists, it is probably rarely 
  260.                used, if required however (extremely unlikely) you can use the 
  261.                new "$$IGNORE" parameter command. 
  262.               Some debug mode changes which hopefully make it easier to work 
  263.                through. 
  264.  
  265.        3. Version 99.324 
  266.  
  267.               Updated '{$?}', can now specify '$$' commands in which case they 
  268.                are applied to each parameter (and they are not in pass through 
  269.                format). 
  270.               When defining your own '$$' commands you can now determine the 
  271.                source of the value (macro or parameter name). 
  272.               Updated directory creation code, under regina we can tell if a 
  273.                directory exists, so now only create when required. 
  274.               New ProcessNext() routine. 
  275.               New ReplaceMacros() routine. 
  276.               New /DebugTime switch. 
  277.               The "BIN2PPW.CMD" updated to work within regina's tight 
  278.                restrictions. 
  279.               Updated HtmlPre.IH & OL_DOC.DH so that the right angle bracket 
  280.                is now converted to the html code. 
  281.               Updated error messages when a macro expansion fails, the macro 
  282.                being expanded is now reported. Try to show macro expanded lines 
  283.                where possible. 
  284.               If compound rexx variable unknown then known "components" are 
  285.                now always dumped. 
  286.               Some lists and other items would not show up correctly under 
  287.                Internet Explorer, hopefully all occurances have now been fixed. 
  288.  
  289.                There could be some glitches in the documentation, if you notice 
  290.                problems please report them... 
  291.  
  292.        4. Version 99.317 
  293.  
  294.               New '$$' command of '$$SPCPLUS'. Adds space before item if its 
  295.                non empty. 
  296.               If executing #DefineRexx code immediately then macro parameters 
  297.                are always replaced. 
  298.               New MacroSet() & MacroGet() routines, the later replaces any 
  299.                "GetMacro()" calls which will be removed in a later release. 
  300.               Updated OL_DOC.DH so that it should now work under regina. 
  301.               Updated NestChk.H to perform more validation of IDs and created 
  302.                new macro for easy definition of HTML tags you want to verify 
  303.                the nesting of. 
  304.  
  305.        5. Version 99.313 
  306.  
  307.               Fixed bug in '{$?}', would not always work unless in debug mode! 
  308.               New "#option" of CsReplacement. By default ppwizard Macros and 
  309.                their parameters are case insensitive. 
  310.               Updated OL_DOC.DH so that headings can contain single quotes. 
  311.                Also added new as yet undocumented "SimpleList" list type to 
  312.                match IPF "sl" and "esl" tags. 
  313.               New BulkChangePrepare() routine. 
  314.               New "<?DebugOn>" variable which simply tells you if debug is on 
  315.                or off. The new IsDebugOn() call tells you similar information. 
  316.                New "user" DebugLevel states that you can use for your own 
  317.                purposes. 
  318.               New Debug() and DebugIndent() calls. 
  319.  
  320.        6. Version 99.310 
  321.  
  322.               The '$$' commands introduced last release now also apply to 
  323.                Standard Definitions, allowing standard variables as well as 
  324.                rexx variables to be easily handled. 
  325.               The #{ loops can now be used in a macro. Prior to this it would 
  326.                only work if read from file. 
  327.               The #DefineRexx command can now immediately execute rexx code 
  328.                (no need to save as macro contents). 
  329.               Document that AddInputFileToDependancyList() and 
  330.                AddOutputFileToDependancyList() can now be used. 
  331.               Updated OL_DOC.DH so that it no longer generates java navigation 
  332.                (wasn't reliable). 
  333.               Removed a number of files from main download, now available 
  334.                separately. 
  335.  
  336.        7. Version 99.304 
  337.  
  338.               New macro and macro parameter replacement options, you can 
  339.                perform translations on whole macro values or on individual 
  340.                parameter values. Tell me if you can think of any other common 
  341.                transformations you would like to be able to do. 
  342.               New macro replacement option, you can now use '{$?}' to generate 
  343.                "unused" parameters. This will be a very handy feature and 
  344.                allows you to create better macros as replacements to existing 
  345.                HTML tags. 
  346.               Some rare very early errors were not being correctly reported as 
  347.                they would cause ppwizard to trap. 
  348.  
  349.        8. Version 99.299 
  350.  
  351.               Updated the #RexxVar command to create better "PUSH" and "POP" 
  352.                commands (old format still supported). 
  353.               Updated FTPLIKE.IH header so that it can handle filenames and 
  354.                directories that contain single quotes. 
  355.  
  356.        9. Version 99.289 
  357.  
  358.               There are now some special alternatives to the normal method of 
  359.                macro replacement. Valueless parameters starting with '$$' are 
  360.                now special cases and represent instructions to PPWIZARD. 
  361.               Updated OL_DOC.DH header, main change is validation of links to 
  362.                ensure that the destination heading exists. Updated it's 
  363.                documentation and fixed some faulty links. 
  364.               Modified GetImageHeightWidth() so that it now dies on failure 
  365.                instead of generating warnings. 
  366.               The FTPLIKE.IH header was updated. Added new WPS URL to HTML 
  367.                example. 
  368.               Input (only) dependencies are now converted to upper case on 
  369.                case insensitive operating systems so that we don't store 
  370.                information for the same file more than once. 
  371.               Dependency file has a new format. The #DependsOn command has 
  372.                been enhanced so that you can "stamp" commands or files matching 
  373.                masks. 
  374.               Regina 08h allows better reporting on syntax traps, improved 
  375.                trap handler to take advantage of this change. 
  376.  
  377.       10. Version 99.281 
  378.  
  379.               New Summary() routine to allow you to add (or remove) details on 
  380.                the displayed summaries. 
  381.               Updated VALRURL.H to remove "name expected" trap when used under 
  382.                regina. 
  383.               Updated default whitespace to include EOF (26 decimal) as 
  384.                different versions of regina seem to handle it correctly, then 
  385.                not! 
  386.               Work around to stream('STATE') & stream('DESCRIPTION') bug in 
  387.                regina 08h beta. 
  388.               Improved text of some error messages. 
  389.  
  390.       11. Version 99.276 
  391.  
  392.               Fixed bug in handling of macro parameters which did not have a 
  393.                value (new feature in 99.225). PPWIZARD would fail if the 
  394.                parameter was the last supplied (and there was no spaces after 
  395.                it). 
  396.               The SortArray() routine has been updated so you can decide 
  397.                whether or not compares are strict. The default is that they are 
  398.                not, strict compares are best for text, numbers however will not 
  399.                correctly sort this way. 
  400.               Spelling dictionaries are now put into dependency file if 
  401.                required. 
  402.               Improved way ppwizard fails if user makes certain mistakes with 
  403.                the name of an included file (such as empty name), rexx used to 
  404.                spit the dummy. 
  405.               New FAQ section in doco. 
  406.               The HTML generator tags now go in no matter the case of the user 
  407.                html tags. It now also handles a body tag with parameters. 
  408.               Finally managed to generate a very small test case to 
  409.                demonstrate the 08g "stream('query exists')" bug and sent it to 
  410.                Mark Hessling, he has fixed the problem for the next release. We 
  411.                have also confirmed that this bug has been around for a while. 
  412.                While ppwizard (in my setup) would only fail on 08g, my testcase 
  413.                fails on all regina versions I have access to. For this reason I 
  414.                have decided to support 08g and remove the warning. 
  415.  
  416.       12. Version 99.269 
  417.  
  418.               Had to restore an old workaround to a regina bug (removed in 
  419.                99.225). I'd thought it had been fixed (looks like only 
  420.                partially fixed). Quite a few header files updated to correct 
  421.                this. If you had trouble retrieving variables after you'd 
  422.                created them (ppwizard would trap - variable not found) then you 
  423.                were probably bitten by this bug. 
  424.               The default is now to see each spelling error (for a word) once 
  425.                per build, you can use the new /SpellShowAll switch to indicate 
  426.                that you'd like to see each error. 
  427.               You can now modify the spelling delimiters from within a 
  428.                dictionary. 
  429.  
  430.       13. Version 99.268 
  431.  
  432.               Updated #import command so that closing column tags are now 
  433.                generated by default. These are optional but some browsers such 
  434.                as Netscape may not work correctly in all circumstances when 
  435.                they are missing. There are now options which allow the easy 
  436.                definition of text which goes before and after record data (say 
  437.                to change fonts within a cell). 
  438.               When generating rexx code (/Rexx used) the syntax of the 
  439.                generated code is now checked in all cases. With regina the 
  440.                generated code had previously not been checked. 
  441.               We now have a basic spell checker, its not perfect and will 
  442.                probably change in future (maybe based on user feedback), but 
  443.                its a good start. It tries to avoid HTML tags and so does not 
  444.                yet handle "ALT" text etc. There are 2 basic modes (you can use 
  445.                both together) as follows: 
  446.                  -  You can indicate words that you frequently get wrong and 
  447.                     ppwizard will tell you when you use the word. 
  448.                  -  You can supply a list of "good" words (dictionaries) and 
  449.                     ppwizard will tell you if you use a word which is not in a 
  450.                     dictionary. 
  451.               There are new switches of /SpellCheck and /SpellAddWord. A new 
  452.                option of AllowSpell gives you control over which parts of the 
  453.                output you wish to spell check. 
  454.               Note that currently ppwizard only reports a spelling related 
  455.                error for a word once per ppwizard invocation not once (or many) 
  456.                per individual build (as it probably should). 
  457.               HtmlPre.IH & OL_DOC.DH updated so spell checking on examples is 
  458.                optional (default state controlled by user). 
  459.               The "/DependsOnPpw" switch no longer exists, see the new 
  460.                "/DependsOnComplete" switch. 
  461.               PPWCURL.CMD improved. New switches allow timed out URLs to be 
  462.                retried and for you to specify if moved URLs are OK or not (for 
  463.                each one). Memory file can be backed up to 'x' levels. 
  464.               The default handling of the FTPLIKE.IH header should now handle 
  465.                spaces in filenames better. If you have any problems please let 
  466.                me know! 
  467.               Updated "PPWSORT.H" so default method of sorting is not strict 
  468.                (">>") as this incorrectly sorts numeric values. 
  469.               Better debug output. 
  470.               You may need to modify your source, see following issues: 
  471.                  a. Updated #import command so that the option 
  472.                     "?_BLANK_COLUMN#" now has a underscore before the field 
  473.                     number to be consistant with all other options which refer 
  474.                     to column #. 
  475.                  b. If you use "DecodeUrl()" or "EncodeUrl()" see doco for 
  476.                     UrlDecode() & UrlEncode(). 
  477.  
  478.       14. Version 99.261 
  479.  
  480.               Windows (at least NT) appears to have a bug/feature in its 
  481.                handling of the "dir" command which caused ppwizard to report 
  482.                that no files were found when /ScanSubDir used and maybe other 
  483.                times. I've worked around this bug. This would probably have 
  484.                affected the use of the FTPLIKE.IH header and maybe others. 
  485.               The way PPWCURL.CMD is invoked has changed, most environment 
  486.                variables have disappeared, replaced by command line switches. 
  487.                Can now test URLs extracted straight from HTML pages. The 
  488.                program is much improved in many other ways. 
  489.               PPWCURL.CMD will now run under Windows using the windows version 
  490.                of RxSock (although there is no support for FTP checking under 
  491.                windows). Apparently there is a linux version of RxSock with 
  492.                object rexx this may or may not work with regina, please tell me 
  493.                if you try it! 
  494.  
  495.       15. Version 99.252 
  496.  
  497.               The /Output and /DependsOn switches can now generate their 
  498.                output in a completely separate directory tree (when /ScanSubDir 
  499.                used). 
  500.               New "<?RexxSkip>" and "<?RexxSkipTo>" variables. 
  501.               Updated OL_DOC.DH, main change allows you to specify "targets" 
  502.                on links (section within a html page). Can also save/restore 
  503.                heading levels. 
  504.               Documented fact that PPWCURL.CMD can be used to check WPS URL 
  505.                objects (created by Netscape etc). Also minor improvements to 
  506.                program. 
  507.               Assorted performance enhancements. 
  508.               Started documenting the tags and options of OL_DOC.DH. A few 
  509.                names modified. 
  510.  
  511.       16. Version 99.234 
  512.  
  513.               Updated #OneLine command so it will correctly handle ppwizard 
  514.                commands embedded within a #define (a macro which executes 
  515.                ppwizard commands). 
  516.               Updated VALRURL.H and PPWCURL.CMD so that it will now tell you 
  517.                in which html file(s) the failing URL occurs. Assorted other 
  518.                improvements. 
  519.               New InputComponentLevel() and InputComponentLineLevel() 
  520.                routines. 
  521.  
  522.       17. Version 99.230 
  523.  
  524.               I've set up an email based PPWIZARD discussion group (using 
  525.                "list bot"). 
  526.                Join up at http://www.labyrinth.net.au/~dbareis/ppwizard.htm. 
  527.               Please read the changes to the "Bugs or Suggestions" section. 
  528.               New #OneLine command, hopefully this will please a lot of people 
  529.                (judging by past feedback). 
  530.               The "PPWCURL.CMD" (URL validator) batch file has had some major 
  531.                improvements, the biggest one being able to specify a period of 
  532.                time (in days) after a successful check before another is 
  533.                required (this is major performance improvement). 
  534.               Must have forgotten to document the /HtmlGenerator switch. 
  535.                Wasn't working 100% anyway! 
  536.               Minor change to #import to allow the specification of particular 
  537.                values for each column to replace empty fields (not just 
  538.                "?_BLANK_FIELD" - which still exists). 
  539.  
  540.       18. Version 99.225 
  541.  
  542.               Can now have macro parameters without you having to specify a 
  543.                value (it will be given the value of the parameter name in upper 
  544.                case). Thanks to feedback from "Mads Orbesen Troest" for this 
  545.                one. 
  546.               Removed work around to regina value() bug (to speed up 
  547.                PPWIZARD). This bug is fixed in regina 0.08f onwards (the only 
  548.                version that PPWIZARD now supports - see next item!). 
  549.               Found bug in regina 0.08g (latest available), do NOT use this 
  550.                version, I have reported the problem and am providing as much 
  551.                detail as possible so hopefully the next version will be OK. 
  552.               A debug message and warning message will be generated if 
  553.                PPWIZARD does not "approve" of the version of regina you are 
  554.                using. 
  555.               Updated "VALRURL.H" to not do http/ftp support checking if URL 
  556.                checking is not immediate. 
  557.  
  558.       19. Version "99.220 
  559.  
  560.               The #DefineRexx command now honours the AllowPack setting. 
  561.               The SortArray() routine is now much faster. Note that the 
  562.                routine now "correctly" uses strict compares, this may have 
  563.                caused "funny" sorts if you had leading/trailing whitespace. 
  564.               You may need to modify your source, see following issues: 
  565.                  a. Updated "PPWSORT.H". Added some easy to use macros for 1 
  566.                     and 2 array sorts. New much faster code is generated, see 
  567.                     doco about changes to variable names. 
  568.  
  569.       20. Version "99.215 
  570.  
  571.               New #DefineRexx command which simplifies the definition of rexx 
  572.                code (for example line continuation characters are no longer 
  573.                required). 
  574.  
  575.       21. Version 99.150 
  576.  
  577.               New "PPWSORT.H" header. This allows you to define how the 
  578.                sorting is done as well as sort more than one array (keep 
  579.                associated info together). 
  580.               Updated "VALRURL.H" support. 
  581.  
  582.       22. Version 99.148 
  583.  
  584.               New Info() routine to match #info command. 
  585.               Updated "VALRURL.H" header file. Now performs immediate checking 
  586.                of URLs at end of each successful build or can batch URL's for 
  587.                later validation, or you can define your own URL handler. 
  588.               You may need to modify your source, see following issues: 
  589.                  a. "BubbleSort()" renamed to "SortArray()". 
  590.                  b. "ReverseIt()" renamed to "ReverseArray()". 
  591.  
  592.       23. Version 99.145 
  593.  
  594.               New "VALRURL.H" header file which allows validation of remote 
  595.                http and ftp URLs. I am very interested in feedback on this 
  596.                feature. 
  597.               Updated FTPLIKE.IH. 
  598.               New "DieIfIoErrorOccurred()" routine which can be called any 
  599.                time prior to the closing of a stream to see if any input or 
  600.                output errors have occurred. 
  601.               Updated "GetEnv()", it now takes an optional parameter telling 
  602.                it to die if the env var does not exist. 
  603.               Removed "/CheckImage" & "/CheckHref" validation switches as they 
  604.                did not handle all cases, did not do a really good job of 
  605.                checking, there are better ways of doing it anyway (see the 
  606.                Resource Validation - Local section for more details) and user 
  607.                feedback seems to imply its a rarely used feature. I will 
  608.                probably come up with a new header file and framework for the 
  609.                validation of local files (and maybe remote as well) in a future 
  610.                release. 
  611.               New "GenerateFileName()" routine which allows you to create 
  612.                filenames from masks exactly like switches such as /Output do. 
  613.  
  614.       24. Version 99.135 
  615.  
  616.               Assorted linux improvements. 
  617.               Updated FTPLIKE.IH so it can handle directories in operating 
  618.                systems other than OS/2. It now works well under linux. 
  619.               Updated NestChk.H to work around bug in regina. Note that under 
  620.                regina 0.08e you will get a "clause" error, please change to 
  621.                "0.08f". 
  622.               Updated _SysFileTree() to handle directories. Basically also 
  623.                clean up some other "strange" stuff. 
  624.               #import would fail if you used some import types such as ",,," 
  625.                and your "TMP" or "TEMP" environment variable pointed to a drive 
  626.                without long filename support (PPWIZARD would trap). 
  627.               If "TMP" or "TEMP" pointed to a root directory (such as in 
  628.                "E:\") then PPWIZARD would trap. A terminating slash on other 
  629.                directories was OK! 
  630.               Now when a trap occurs variables from nearby lines are dumped to 
  631.                help in problem diagnosis. 
  632.  
  633.       25. Version 99.131 
  634.  
  635.               In some unusual situations where a file that ppwizard had to 
  636.                locate is read directly from file it could get confused. Under 
  637.                OS/2 this would correctly trap, due to a regina bug/feature it 
  638.                will cause an infinite loop. 
  639.               Summary information improved. 
  640.  
  641.       26. Version 99.120 
  642.  
  643.               The way a file is included has been rewritten. A file may now 
  644.                either be read directly from the file or via a memory cache. 
  645.                Reading from cache will improve performance if the file resides 
  646.                on slow media (if it needs to be re-read). If a recursive 
  647.                #include is detected (this is now allowed) then read from cache 
  648.                is forced, there is no more need for a file copy workaround. 
  649.               A /Inc2Cache switch allows you to override the default read 
  650.                method (file/cache) chosen by PPWIZARD. 
  651.               Improved CompareReplaceFixed() routine so that it can also be 
  652.                used as a compare function. 
  653.               No bugs reported or seen however I think in some situations 
  654.                #import could have caused some weird looping or other bugs. 
  655.  
  656.       27. Version 99.115 
  657.  
  658.               New "#OnExit" command. 
  659.               Added new _filespec types. 
  660.               New parameter on GetIdPrepare() call improves functionality in 
  661.                some circumstances. 
  662.               New ExpandXCodes() call. 
  663.               New "PUSHPOPM.H" header file which allows you to easily 
  664.                save/restore macro values. 
  665.               Updated "FTPLIKE.IH" as well as NestChk.H and OL_DOC.DH headers. 
  666.               Better validation on "#include" and "#output" commands. 
  667.               Now only generate warning if no lines generated. 
  668.  
  669.       28. Version 99.110 
  670.  
  671.               New "FTPLIKE.IH" header file which allows you to create simple 
  672.                FTP like listings with ".DIZ" file support. The DIZ file can 
  673.                contain HTML tags. 
  674.               Fixed bug in "#{" type loops where #if nesting level could get 
  675.                confused if loops were "nested". Possibly other effects. 
  676.  
  677.       29. Version 99.106 
  678.  
  679.               Improved CompareReplaceFixed() routine. 
  680.               Now added infinite loop detection (can be turned off) for 
  681.                expansion of macros. 
  682.  
  683.       30. Version 99.100 
  684.  
  685.               New "#option" of AtChangeType to allow variations on the 
  686.                "normal" case sensitive #AutoTag or #AsIs changes. 
  687.                If you have some fantastic free PURE REXX search and replace 
  688.                code then I can include it as a new PPWIZARD extension if you 
  689.                send me the code! 
  690.               New "#option" of ExpandX to provide more control over when 
  691.                <?xXX> codes get expanded. 
  692.               New ReplaceStringCI() routine to perform case insensitive search 
  693.                and replaces. 
  694.               New CompareReplaceFixed() routine to perform complex "fixed" 
  695.                type compare and replace operations. 
  696.               New "<?ProcessingMode>" variable. 
  697.               New TEXTEDIT with PPWIZARD and SHARING HEADERS - HTML + REXX CGI 
  698.                examples. 
  699.  
  700.       31. Version 99.092 
  701.  
  702.               More of a feature (as code functioned...), however the 
  703.                "StartsMacroParm" and similar stuff was not what I was aiming 
  704.                for! You would only have seen this while debugging T2H imports. 
  705.               So problems such as the one above can never reoccur, rather than 
  706.                delay trap handling I now use a "simple" trap handler until 
  707.                PPWIZARD has initialized itself enough to use the normal (much 
  708.                more complex) one. 
  709.               New GetInputFileNameAndLine(), GetFileLineBeingProcessed() & 
  710.                GetLineBeingProcessed() calls so rexx code can keep track of 
  711.                debugging/diagnostic type information. 
  712.               New "NestChk.H" header file which contains macros for generic 
  713.                handling of nesting validation. You could use this to ensure 
  714.                numbers of "TABLE" tags match numbers of "/TABLE" tags etc 
  715.                (rather than hope testing shows this up). 
  716.               Now validate #AutoTagState nesting level. 
  717.               Much more complex import example put into doco. The example 
  718.                reads a comma delimited file (could have been fixed field etc) 
  719.                and generates 3 html files based on the first letter of the 
  720.                surname. 
  721.  
  722.       32. Version 99.083 
  723.  
  724.               New /WarningsIgnore switch. This allows you to specify one or 
  725.                more individual (expected) messages to ignore. 
  726.               A parameter on the command line can now be surrounded by double 
  727.                quotes if it needs to contain spaces. 
  728.               Updated documentation, particularly the #Import command (more 
  729.                details on internal processing etc). 
  730.               New "Resource Validation - Local" section in documentation. 
  731.               Documented WriteLineToTmpImportFile() routine, must have 
  732.                forgotten to do so in an earlier release. 
  733.               New Error() & Warning() routines (useful in filters etc). 
  734.               Fixed bug which may occur if you had used the ReplacementTags 
  735.                option (rare bug to do with 'x' codes). 
  736.               Summary now includes warning count (if any). 
  737.               You may need to modify your source, see following issues: 
  738.                  a. The '\\' line continuation form no longer exists (it was an 
  739.                     alias for '-\'). You can use the modified (but backwards 
  740.                     compatible) LineContinuation option to allow '\\' if you 
  741.                     wish. 
  742.                  b. Syntax of #Warning slightly modified. To quickly get 
  743.                     yourself going simply add "USER " before your warning text. 
  744.                  c. If the defined line continuation character ends a line but 
  745.                     it otherwise does not look like a line continuation then 
  746.                     the line is no longer treated as continued. In practical 
  747.                     terms you now need a space before the '\' character! 
  748.  
  749.       33. Version 99.074 
  750.  
  751.               Enhanced the #Output command so that the new file does not need 
  752.                to be processed in the same mode as the "current" file. For 
  753.                example while generating rexx code you may wish to generate data 
  754.                files (such as TEXTEDIT scripts) which the rexx program will use 
  755.                as input at runtime. This allows #define variables to be easily 
  756.                shared and gives you the option of wrapping everything up in a 
  757.                single source file. 
  758.               Fixed error message when invalid parameter used on #Output 
  759.                command. 
  760.               Better temporary file name calculation (and handling) under 
  761.                regina. 
  762.               Handling of "stderr" redirection changed so should work on "csh" 
  763.                and similar shells under unix and not just the "bash" shell (not 
  764.                100% sure this was required as regina seems to use "bash" shell 
  765.                for operating system commands). 
  766.               The "#Import" command can now take "EOF:" in the "Remove" 
  767.                variable to remove to EOF. 
  768.               Updated "#Import" command so that you can now always specify a 
  769.                number of lines to drop and not just if "CMA-" etc used. Whether 
  770.                or not the '-' is used now just determines the default state. 
  771.               New /beep switch for people who don't like beeps on errors 
  772.                (grumpy bunch!). 
  773.               On all operating systems now do "set" command (and capture 
  774.                output) when /debug used.  No real reason except may help me in 
  775.                future debugging (help me identify unix shell, version etc). 
  776.               Other minor debug and doco improvements. 
  777.  
  778.       34. Version 99.067 
  779.  
  780.               When environment variables containing paths are searched the 
  781.                character separating paths is now ':' for unix, for all other 
  782.                operating systems it remains ';'.  Similar change for processing 
  783.                of /#Include switch. 
  784.               Minor debug and doco improvements. 
  785.  
  786.       35. Version 99.056 
  787.  
  788.               In unix now default to lines terminating with a newline (no 
  789.                carriage return). Other operating systems now default to CR + LF 
  790.                even for HTML, to 'pack' this more use the /CRLF switch to turn 
  791.                off carriage returns (HTML browsers don't require them). No 
  792.                switches apart from /CRLF modify the line termination state. 
  793.               New /Exclude switch to allow you to exclude certain files.  Now 
  794.                only process a file once even if specified in multiple masks on 
  795.                the same command line. 
  796.               Improved syntax/novalue trap information on user errors in #if, 
  797.                #evaluate commands etc. 
  798.               More debug parameters for AddressCmd(), lots of other little 
  799.                debug changes. 
  800.  
  801.       36. Version 99.051 
  802.  
  803.               New "#option" of WhiteSpace, under unix this defaults to the EOF 
  804.                (decimal 27) and CR (decimal 13) characters.  This allows unix 
  805.                to read PC files without problems. 
  806.               Whitespace after line continuation characters no longer prevents 
  807.                line continuation. 
  808.               Temporary files under unix will no longer go into the root 
  809.                directory if the "TMP" environment variable is not set up, they 
  810.                will go into the "/tmp" directory (I assume this will always be 
  811.                there). 
  812.               The /output and /DependsOn switches now have non-wildcard 
  813.                alternatives as placeholders. 
  814.               Unix has case sensitive filenames, the documentation should now 
  815.                match the correct case of the files. 
  816.               Other minor changes. 
  817.  
  818.       37. Version 99.049 
  819.  
  820.               Unix fix for directory search bug. 
  821.  
  822.       38. Version 99.048 
  823.  
  824.               Improved "TRYME.IT" example to demonstrate more features (while 
  825.                hopefully still being fairly easy to understand). 
  826.               If all input files end in ".X" and "/Rexx" (or other mode 
  827.                switch) was not specified then /rexx is invoked anyway. Now have 
  828.                a /html switch. 
  829.               After looking everywhere else for a file PPWIZARD now also 
  830.                checks the directory it is executing from. 
  831.               Removed "OL_DOC.DH" from document and now bundle together with 
  832.                PPWIZARD. 
  833.               Minor change to generated rexx header. 
  834.  
  835.       39. Version 99.044 
  836.  
  837.               New "HtmlPre.IH" header file to make it easier for people to 
  838.                start using PPWIZARD to include example code into a html page. 
  839.               Many enhancements to ML importing, other import types have also 
  840.                had relatively small changes. 
  841.               New "Dropped" array during import so you can access fields that 
  842.                are not directly displayed.  This would allow you to create 
  843.                combined fields etc. 
  844.               Fix to /DependsOn when /Template also used. 
  845.               Minor change to way REXXTRACE define is accessed for tracing 
  846.                rexx code.  Improved use of "interactive mode" rexx debugging. 
  847.  
  848.       40. Version 99.038 
  849.  
  850.               Fixed "#Import" bug where fields could not be reordered with 
  851.                '{2}' etc. 
  852.               New "#Import" type ML, this allows you to create a text database 
  853.                in an easy to manage format. Some people are already using WRAP 
  854.                imports to handle similar formatted text databases. 
  855.  
  856.       41. Version 99.034 
  857.  
  858.               Optimised #AsIs text changes so that it will work much better 
  859.                for large numbers of single character replacements such as would 
  860.                be required to convert international characters for correct 
  861.                display in a html browser. New BulkChar2String() routine. 
  862.               The /output and /DependsOn switches now have a new special 
  863.                character of '?' (allows specification of paths relative to the 
  864.                input file). 
  865.               Worked out a faster workaround to a regina bug, this should 
  866.                speed up PPWIZARD when the regina interpreter is used. 
  867.               Major update to the "rexx" section of the manual. 
  868.               Minor improvement to rexx packing. Minor change to generator 
  869.                header. 
  870.               Minor cleanups for rexx tracing. 
  871.  
  872.       42. Version 99.030 
  873.  
  874.               Oops, wildcards were not expanding correctly under regina. 
  875.               New SortArray() and ReverseArray() "array" routines. 
  876.               If you were having trouble with the /DependsOn switch then you 
  877.                are probably using regina version 0.08e.  It has a bug in the 
  878.                "parse" command which can generate spaces.  I have added a 
  879.                workaround but it would be safer to move to a newer version. 
  880.  
  881.       43. Version 99.027 
  882.  
  883.               Document fact that delimited and fixed imports can be setup so 
  884.                that the format for each record (row of table) can vary 
  885.                depending on the data.  This documents a new variable that can 
  886.                be used in a filter. 
  887.               Enhanced looping so that it can contain "#include" or "#import" 
  888.                commands. 
  889.               New DebugLevel option of REXXTRACE for debugging any rexx that 
  890.                you might be executing. 
  891.               Removed "RestrictKey" routine, this functionality can be 
  892.                achieved through the new "GetId" routine.  Also see the new 
  893.                "SetId" routine.  This is a much more powerful mechanism which 
  894.                "OL_DOC.DH" now uses. 
  895.               New "<?RestartLine>" variable. 
  896.               Minor debug improvements. 
  897.  
  898.       44. Version 99.023 
  899.  
  900.               New AsIs() and AsIsPrepare() routines. 
  901.               New AutoTag() routine. 
  902.               New QuoteIt() routine. 
  903.  
  904.       45. Version 99.020 
  905.  
  906.               Changed syntax and way "#AsIs" command works so that it is now 
  907.                much more flexible.  If you have used the "#AsIs" command you 
  908.                will need to make minor changes.  Sorry but I never liked the 
  909.                way it was before... Too limiting. 
  910.               Changed "#AsIs" mode so that when turned off it restores the 
  911.                state of the options to the state that existed just before the 
  912.                "as is" mode was turned on. 
  913.               More "#Import" changes/options.  You can now filter records in 
  914.                the T2H mode.  Largish changes to WRAP import.  You can now 
  915.                easily disable or extend on the "standard" #AsIs replacements 
  916.                that occur during import (chars like '<' and the box chars). 
  917.               New "<?ProtectFromPpwStart>" & <?ProtectFromPpwEnd> definitions. 
  918.               New "ToLowerCase" routine. 
  919.               New "rexx" section in the manual. 
  920.               Improved summary information. 
  921.  
  922.       46. Version 99.014 
  923.  
  924.               More "#Import" changes.  Default is now to "PROTECT" delimited 
  925.                and fixed imported data.  More configurable parameters in T2H 
  926.                import.  "T2H" import now finds and by default tags email 
  927.                addresses. 
  928.               Parm 2 of #AutoTag command now can now include "{$AT}" to refer 
  929.                to the before (automatically tagged) text.  This can save a lot 
  930.                of retyping. 
  931.  
  932.       47. Version 99.009 
  933.  
  934.               Fix looping problem on loops other than the first. 
  935.               Improved "#Import" type T2H, this affects you if you used 
  936.                "_LINK" definitions. 
  937.               Modified "#Import" type WRAP, to work better under regina (OS/2 
  938.                seems to have better garbage collection). 
  939.               No longer delete temporary files during #Import command if debug 
  940.                mode is on. 
  941.               Modified "#option" command so push and pop commands can be 
  942.                combined with setting options. 
  943.               Added an example of importing using SQL. 
  944.               I correct some code which may not have correctly handled a line 
  945.                with all blanks (when writing to output file). 
  946.               Note that you can now tell PPWIZARD exactly what characters to 
  947.                translate during the #Import command.  For example if your text 
  948.                includes internation characters such as umlauts you could 
  949.                convert them to the html symbols so that they display correctly. 
  950.  
  951.       48. Version 99.006 
  952.  
  953.               Improved documentation. 
  954.               Fixed major problems with "#Import" type T2H. 
  955.  
  956.       49. Version 99.005 
  957.  
  958.               PPWIZARD looping is now possible. Requested by Chris Wenham. 
  959.                Note that you have always been able to do loops in rexx 
  960.                (#evaluate). 
  961.               New "#Import" type T2H.  This is basically a TEXT to HTML 
  962.                conversion mode.  It is reasonably configurable (and will get 
  963.                more so).  You can determine look and feel and whether "http:" 
  964.                links are made links or not, plus more. Use /Debug to make up 
  965.                for lack of doco for now - everything can be turn off or changed 
  966.                for example you can turn off creation of links and can change 
  967.                mode from "PRE" to blank line indicates end of paragraph.  If 
  968.                you know of common examples of text then maybe we can get much 
  969.                smarter.  Basically feedback required. 
  970.               Now when in HTML mode (the default), if no input files were 
  971.                specified PPWIZARD will look for "DEFAULT.IT". Requested by 
  972.                Chris Wenham. 
  973.               New "<?CgiStart>" variable. Feedback from Chris Wenham. 
  974.               New "<?PpwizardAuthor>", "<?PpwizardAuthorEmail>", 
  975.                "<?PpwizardAuthorHomePage>", "<?PpwizardGeneratorMetaTags>" and 
  976.                "<?PpwizardHomePage>" variables. 
  977.  
  978.       50. Version 99.001 
  979.  
  980.               Fix some minor documentation issues. 
  981.               Generator meta tagging added when generating html. 
  982.  
  983.  I have still kept the history for previous releases (as far back as 98.044), 
  984.  so if you wish I could send it to you, however if you are interested in stuff 
  985.  this far back take my word for it you are better off with the current release! 
  986.  
  987.  
  988. ΓòÉΓòÉΓòÉ 1.3. FAQ ΓòÉΓòÉΓòÉ
  989.  
  990. PPWIZARD FAQ 
  991.  
  992. The following (currently short list) of questions are answered: 
  993.  
  994.        1. Can ppwizard accept options from a configuration file? Currently I 
  995.           have some very long command lines and its hard to swap between 
  996.           frequently used configurations. 
  997.        2. I have a perfectly working series of lines that I wish to place into 
  998.           a macro. The macro takes one or more parameters so that I can 
  999.           generate many versions of the output. I use the example tags, #AsIs" 
  1000.           or #AutoTag" commands but these don't seem to be working correctly. 
  1001.           What am I doing wrong? 
  1002.  
  1003.  
  1004. ΓòÉΓòÉΓòÉ 1.3.1. QUESTION #1 - Does PPWIZARD support config files? ΓòÉΓòÉΓòÉ
  1005.  
  1006. QUESTION #1 
  1007.  
  1008. Can ppwizard accept options from a configuration file? Currently I have some 
  1009. very long command lines and its hard to swap between frequently used 
  1010. configurations. 
  1011.  
  1012. ANSWER 
  1013.  
  1014. There is no need for a separate file as ppwizard can accept anything the 
  1015. command line can accept from environment variables. In most operating systems 
  1016. you can either put your options in "config.sys" or in a batch file that you run 
  1017. for your project. That is, the facility is there, it is just supplied in a 
  1018. different way. 
  1019.  
  1020. You can create a whole range of different common options and select from them 
  1021. as you wish, hopefully the following example demonstates the method: 
  1022.  
  1023.     @echo off
  1024.  
  1025.     REM *** YOU MIGHT WISH TO SET THIS IN CONFIG.SYS ETC *******
  1026.     SET PPWIZARD_OPTIONS=/beep /color:n
  1027.  
  1028.  
  1029.  
  1030.     REM *** NOW SET SOME OTHER STUFF ****
  1031.     SET PPWDEBUG=/debug /option:DebugLevel{x3D}"-ALL"
  1032.     SET   STUPID=/DependsOn:out\*.DEP
  1033.     SET   OTHERS=/GetEnv:Stupid
  1034.  
  1035.     REM *** START PPWIZARD ***
  1036.     if     "%1" == "" ppwizard *.IT  /GetEnv:OTHERS
  1037.     if not "%1" == "" ppwizard %1.IT /GetEnv:OTHERS
  1038.  
  1039.     REM *** IF I'd wanted debug ***
  1040.     goto Endbatch
  1041.     if     "%1" == "" ppwizard *.IT  /GetEnv:PPWDEBUG /GetEnv:OTHERS
  1042.     if not "%1" == "" ppwizard %1.IT /GetEnv:PPWDEBUG /GetEnv:OTHERS
  1043.     :Endbatch
  1044.  
  1045.  
  1046. ΓòÉΓòÉΓòÉ 1.3.2. QUESTION #2 - My macros are not generating output correctly? ΓòÉΓòÉΓòÉ
  1047.  
  1048. QUESTION #2 
  1049.  
  1050. I have a perfectly working series of lines that I wish to place into a macro. 
  1051. The macro takes one or more parameters so that I can generate many versions of 
  1052. the output. I use the example tags, #AsIs" or #AutoTag" commands but these 
  1053. don't seem to be working correctly. What am I doing wrong? 
  1054.  
  1055. ANSWER 
  1056.  
  1057. The #AsIs and #AutoTag commands only work on data read directly from the a 
  1058. file. This means that you may need to use a bit of trial and error (maybe 
  1059. swearing a bit) and you can get it to work. 
  1060.  
  1061. What is probably easier is rather than creating a macro, put the information 
  1062. into its own header file, then instead of macro parameters you simply #define+ 
  1063. each "parameter" prior to each #include command. 
  1064.  
  1065.  
  1066. ΓòÉΓòÉΓòÉ 1.4. Bugs, Problems or Suggestions ΓòÉΓòÉΓòÉ
  1067.  
  1068. Before asking questions, I would appreciate it if you'd ensure that your answer 
  1069. was not in the FAQ or the this manual! 
  1070.  
  1071. Requested Information - Bugs or Problems 
  1072.  
  1073. If reporting bugs/problems please supply: 
  1074.  
  1075.        1. A detailed description of the problem. Please don't bother wasting 
  1076.           your and my time by telling me "it did not work". 
  1077.  
  1078.        2. All files involved (input, output and any batch files used to run the 
  1079.           preprocessor). You have hopefully trimmed out everything which is not 
  1080.           required by me to recreate the problem. 
  1081.  
  1082.        3. When supplying the redirected output from PPWIZARD please ensure that 
  1083.           you had used /DEBUG on the command line to turn on debug mode. 
  1084.  
  1085.  The easier you make it for me the faster I will be able to come up with a fix 
  1086.  or tell you what your doing wrong etc. 
  1087.  
  1088.  Reporting Bugs/Problems or Suggestions 
  1089.  
  1090.  There are two main ways to report PPWIZARD issues or ask questions, they are: 
  1091.  
  1092.        1. PPWIZARD Discussion List 
  1093.           People who are very interested in PPWIZARD can now join an email 
  1094.           based discussion group, any email sent to ppwizard@listbot.com will 
  1095.           be seen by all subscribers. Hopefully I won't have to answer them 
  1096.           all, but if one person answers, everyone gets the benefit of the 
  1097.           response. All messages are archived so you can always go back and see 
  1098.           previous messages. I will also make announcements on this list. 
  1099.  
  1100.           If you think the problem might be a ppwizard or regina bug (which you 
  1101.           think others probably haven't encountered) you may wish to contact me 
  1102.           directly as others may not be interested (we don't want too many 
  1103.           messages). 
  1104.  
  1105.           Please don't attach large files to emails sent to this address (there 
  1106.           is a 100K limit as well anyway). 
  1107.  
  1108.           We'll have to see how it goes, hopefully it does not need to become 
  1109.           moderated (I probably haven't got time for that!). 
  1110.  
  1111.        2. Authors Email Address 
  1112.           I will take feedback in this manner but in general prefer the email 
  1113.           list mentioned above. Exceptions might be where you have large 
  1114.           attachments, you don't think anyone else would be interested, you 
  1115.           don't want to join the group (why not?) or you really want to hammer 
  1116.           me! 
  1117.  
  1118.           If you must email me directly then send it to 
  1119.           dbareis@labyrinth.net.au. If I think its appropriate I will "CC" the 
  1120.           above discussion group with my response. 
  1121.  
  1122.  Please zip attachments, this reduces the size of the email and ensures that 
  1123.  the information gets here uncorrupted. 
  1124.  
  1125.  Known Bugs or Problems 
  1126.  
  1127.  The following bugs are ppwizard bugs: 
  1128.  
  1129.        1. None Known 
  1130.  
  1131.  The following bugs may occur when using the native interpreters under OS/2: 
  1132.  
  1133.        1. None Known 
  1134.  
  1135.  The following bugs may occur under any operating system using regina (I will 
  1136.  assume on "one of my recommended versions only"): 
  1137.  
  1138.        1. The debug time will be plus or minus a second (this can produce 
  1139.           negative times etc). 
  1140.  
  1141.        2. Regina has a number of 'query exists' bugs, the one that might affect 
  1142.           you is if you specify an input file such as "C:\CONFIG.SYS" and 
  1143.           PPWIZARD tells you it can't open the "CONFIG.SYS" file in a 
  1144.           completely different directory! Another one is where "garbage" might 
  1145.           appear after a filename. 
  1146.  
  1147.  
  1148. ΓòÉΓòÉΓòÉ 1.5. Disclaimer ΓòÉΓòÉΓòÉ
  1149.  
  1150. Disclaimer 
  1151.  
  1152. I believe it is very unlikely that ppwizard or regina will cause damage to your 
  1153. system however I feel that it is wise to advise you of steps you can take if 
  1154. your data is highly critical. 
  1155.  
  1156. I wish to stress that you take full responsibility for ensuring that PPWIZARD 
  1157. (or any other software related to PPWIZARD) is suitable for use in your 
  1158. intended environment. 
  1159.  
  1160. PPWIZARD is supplied "as is" and may contain bugs. It is just impossible to 
  1161. test software (or even information) in all environments as there are just too 
  1162. many possibilities. For this reason you should test any software/information 
  1163. yourself for suitability before using in production or placing onto machines 
  1164. containing important information. By doing this you will have helped ensure 
  1165. that there are no unintended drastic side effects. Prior to testing it is 
  1166. recommended that a full backup of your hard disk be performed. 
  1167.  
  1168. Updating from Older Versions 
  1169.  
  1170. While I will try to keep PPWIZARD backwards compatible with older versions, I 
  1171. will at times (intentionally or not) change it in such a way as to require you 
  1172. to make changes to your source (batch files, code etc) if you wish to upgrade 
  1173. to the newer version of PPWIZARD. 
  1174.  
  1175. It is recommended that you backup your source AND the older versions of my 
  1176. programs before trying a newer version. 
  1177.  
  1178. LINKS 
  1179.  
  1180. Any links I mention are provided "as is", it is up to you to determine the 
  1181. quality of any site I link to or any software I mention... 
  1182.  
  1183.  
  1184. ΓòÉΓòÉΓòÉ 2. PPWIZARD.CMD Command Line ΓòÉΓòÉΓòÉ
  1185.  
  1186. PPWIZARD.CMD Command Line 
  1187.  
  1188.     PPWIZARD[.CMD]  InputMask1 [Options[:parms]]
  1189.  
  1190. The "InputMask1" can be the name of a single file or a filemask containing the 
  1191. normal wildcard characters "?" & "*". You may specify more than one file or 
  1192. mask and they may appear anywhere on the line however none are processed until 
  1193. after all options). Each source file may include other files such as common 
  1194. header files with your standard definitions. If all input files end in the 
  1195. extension ".X" then the default processing mode is /rexx (normally /html). 
  1196.  
  1197. Options 
  1198.  
  1199. All Options begin with '/' unless running under UNIX where '-' is used instead. 
  1200. Options in the optional environment variable "PPWIZARD_OPTIONS" are processed 
  1201. before any specified on the command line. 
  1202.  
  1203. Normally files or options are separated by spaces, if the file or option needs 
  1204. to contain spaces then you can surround it by double quotes. If you use double 
  1205. quotes the quoted value must not contain double quotes (encode with "{x22}" - 
  1206. see below). 
  1207.  
  1208. Commonly used options: 
  1209.  
  1210.        1. /CrLf 
  1211.        2. /Debug 
  1212.        3. /DependsOn 
  1213.        4. /Rexx 
  1214.        5. /Pack 
  1215.        6. /Output 
  1216.  
  1217.  Validation options: 
  1218.  
  1219.        1. /WarningsIgnore 
  1220.        2. /WarningsOk 
  1221.        3. /SpellCheck 
  1222.        4. /SpellAddWord 
  1223.        5. /SpellShowAll 
  1224.  
  1225.  Less commonly used options: 
  1226.  
  1227.        1. /Option 
  1228.        2. /Define 
  1229.        3. /DebugTime 
  1230.        4. /Template 
  1231.        5. /GetEnv 
  1232.        6. /Exclude 
  1233.        7. /Inc2Cache 
  1234.        8. /CGI 
  1235.        9. /DependsOnComplete 
  1236.       10. /FileNames 
  1237.       11. /#Include 
  1238.       12. /Other 
  1239.       13. /Tabs 
  1240.       14. /**/ 
  1241.       15. /FilterInput 
  1242.       16. /FilterOutput 
  1243.       17. /ScanSubDir 
  1244.       18. /Color 
  1245.       19. /Beep 
  1246.       20. /Info 
  1247.       21. /Sleep 
  1248.       22. /Html 
  1249.       23. /HtmlGenerator 
  1250.  
  1251.  Note that if you know the ASCII code of a character (in hex) you can encode 
  1252.  it, for example "{x20}" represents a space. If a code looks invalid then it is 
  1253.  ignored. The following are codes for some of the more difficult command line 
  1254.  characters you are likely to need: 
  1255.  
  1256.          {x20} - Space 
  1257.          {x22} - " 
  1258.          {x3C} - < 
  1259.          {x3D} - = 
  1260.          {x3E} - > 
  1261.          {x7C} - | 
  1262.          {x26} - & 
  1263.          {x5B} - [ 
  1264.          {x5D} - ] 
  1265.          {x7B} - { 
  1266.          {x7D} - } 
  1267.  
  1268.  LONG COMMAND LINES / CONFIGURATION FILES 
  1269.  
  1270.  Note that PPWIZARD does not support a separate configuration file. It does not 
  1271.  need one, you can use the /GetEnv switch to obtain the same effect. 
  1272.  
  1273.  RETURN CODES 
  1274.  
  1275.          A return code of 0 indicates success. 
  1276.  
  1277.          A return code of 1 indicates success (with warnings) and /WarningsOk 
  1278.           was not used to turn them off. 
  1279.  
  1280.          Any other value indicates an error occurred. 
  1281.  
  1282.  EXAMPLE 
  1283.  
  1284.  This example has the following attributes: 
  1285.  
  1286.        1. Make file functionality without the hassle. 
  1287.  
  1288.        2. All source files have an extension of ".IT" (headers use ".IH"). 
  1289.  
  1290.        3. All output to have the extension ".html" and go into the "OUT" 
  1291.           directory. 
  1292.  
  1293.       +-[ MAKEIT.CMD ]----------------------------------------------------+
  1294.       | @echo off                                                         |
  1295.       | md OUT        >nul 2>&1                                           |
  1296.       | md OUT\DEPEND >nul 2>&1                                           |
  1297.       | ppwizard.cmd %1.IT /Output:OUT\*.html /DependsOn:OUT\DEPEND\*.DEP |
  1298.       | if errorlevel 1 echo ERROR: Command failed!                       |
  1299.       +-------------------------------------------------------------------+
  1300.  
  1301.  Example - Redirection 
  1302.  
  1303.  Ppwizard (or any other program) can at times generate quite a lot of output. 
  1304.  When /Debug is used you will definitely wish to "redirect" the output into a 
  1305.  file, the following is an example which would work in virtually all operating 
  1306.  systems (including linux bash shell - change switch characters to '-'!): 
  1307.  
  1308.       ppwizard.cmd index.it /Output:OUT\*.htm /Debug   > OUT\output.TXT 2>&1
  1309.  
  1310.  If the redirection example does not work you will need to read the 
  1311.  documentation for the operating system you are using to determine the correct 
  1312.  method. 
  1313.  
  1314.  
  1315. ΓòÉΓòÉΓòÉ 2.1. /Beep ΓòÉΓòÉΓòÉ
  1316.  
  1317. Switch /Beep[:YesOrNo] 
  1318.  
  1319. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  1320. switches in the "PPWIZARD_OPTIONS" environment variable. 
  1321.  
  1322. You can determine if beeps occur in some situations such as ppwizard detecting 
  1323. errors. 
  1324.  
  1325. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  1326. one of the following values is expected: 
  1327.  
  1328.          Y 
  1329.          N 
  1330.          YES 
  1331.          NO 
  1332.  
  1333.  
  1334. ΓòÉΓòÉΓòÉ 2.2. /CGI ΓòÉΓòÉΓòÉ
  1335.  
  1336. Switch /CGI:LogFile 
  1337.  
  1338. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  1339. switches in the "PPWIZARD_OPTIONS" environment variable. 
  1340.  
  1341. This command changes the way PPWIZARD works to allow it to be used as a web 
  1342. server based CGI program (or part of a bigger CGI process). 
  1343.  
  1344. The output goes to stdout and what would normally go to stdout is prevented 
  1345. from going there. 
  1346.  
  1347. If the optional "LogFile" is not specified then all status, debug and error 
  1348. output is dropped.  If you need to see this you would specify the name of a 
  1349. file.  If the filename includes "?" then a "random" 8.3 filename (no path) is 
  1350. chosen and replaces the "?". 
  1351.  
  1352. If the ppwizard output is not part of a larger process then you may want to 
  1353. make use of the "<?CgiStart>" variable. 
  1354.  
  1355. Being a CGI script (or part of one) you would want your code to be as fast as 
  1356. possible, I highly recommend you read the "performance" documentation. 
  1357.  
  1358. CGI OPTIONS 
  1359.  
  1360. You may /define, #define or #evaluate the following variables to control the 
  1361. output which occurs in the case of a fatal error (the default is to display the 
  1362. information): 
  1363.  
  1364.          CGI_FATAL_MY_MESSAGE_ONLY 
  1365.           Define this variable if you don't want any details of the message to 
  1366.           be displayed in the HTML output.  Leave this variable empty so as not 
  1367.           to indicate an error (other than truncated output!) or supply the 
  1368.           HTML codes and text you wish displayed. 
  1369.  
  1370.          CGI_FATAL_HEADER 
  1371.           This variable controls the HTML codes that are sent to stdout before 
  1372.           the lines that contain the details of the error.  It is recommended 
  1373.           that these codes include "<PRE>" or similar to retain the line 
  1374.           formatting on error lines. 
  1375.  
  1376.          CGI_FATAL_TRAILER 
  1377.           This variable controls the HTML codes that are sent to stdout after 
  1378.           the lines that contain the details of the error.  The codes will 
  1379.           usually reverse those you specified for use before the error details. 
  1380.  
  1381.  Example 
  1382.  
  1383.  The following examples show the options being specified on the command line, 
  1384.  it is probably better to have any common options specified in CONFIG.SYS on 
  1385.  the web server. 
  1386.  
  1387.       ppwizard.cmd EmailForm.TEM /CrLf /CGI
  1388.       ppwizard.cmd EmailForm.TEM /CrLf /CGI:LOGS\LAST.LOG
  1389.       ppwizard.cmd EmailForm.TEM /CrLf /CGI:LOGS\?
  1390.  
  1391.  
  1392. ΓòÉΓòÉΓòÉ 2.3. /Color ΓòÉΓòÉΓòÉ
  1393.  
  1394. Switch /Color[:YesOrNo] 
  1395.  
  1396. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  1397. switches in the "PPWIZARD_OPTIONS" environment variable. 
  1398.  
  1399. You can determine if colors are used in displayed output.  Useful if 
  1400. redirecting output to log files (or you just hate colors!). 
  1401.  
  1402. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  1403. one of the following values is expected: 
  1404.  
  1405.          Y 
  1406.          N 
  1407.          YES 
  1408.          NO 
  1409.  
  1410.  For colors to work the session must support ANSI color strings. OS/2 does this 
  1411.  by default.  NT does not seem to. 
  1412.  
  1413.  
  1414. ΓòÉΓòÉΓòÉ 2.4. /CrLf ΓòÉΓòÉΓòÉ
  1415.  
  1416. Switch /CrLf[:YesOrNo] 
  1417.  
  1418. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  1419. switches in the "PPWIZARD_OPTIONS" environment variable. 
  1420.  
  1421. This switch can be used to vary the line termination characters. These are 
  1422. initialized to newline on unix and carriage return plus linefeed elsewhere. 
  1423.  
  1424. You can "compress" html on OS/2 and Windows systems a bit more by removing the 
  1425. carriage return as html browsers don't need them, this way you'd save one byte 
  1426. per line. 
  1427.  
  1428. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  1429. one of the following values is expected: 
  1430.  
  1431.          Y 
  1432.          N 
  1433.          YES 
  1434.          NO 
  1435.  
  1436.  
  1437. ΓòÉΓòÉΓòÉ 2.5. /Debug ΓòÉΓòÉΓòÉ
  1438.  
  1439. Switch /Debug 
  1440.  
  1441. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  1442. switches in the "PPWIZARD_OPTIONS" environment variable. 
  1443.  
  1444. This option can be useful in determining what is going wrong when you don't get 
  1445. the output you expected. 
  1446.  
  1447. The output is fairly easy to understand and aims to actually teach (or help you 
  1448. to understand) certain commands (such as #import). 
  1449.  
  1450. To get the maximum output use the switch as early as possible on the command 
  1451. line, if you are getting too much output, there are many filtering options (see 
  1452. the DebugLevel option). 
  1453.  
  1454. If you wish to report a problem with ppwizard then please use this switch and 
  1455. send the output along with any other details. 
  1456.  
  1457. Note that if this command line switch is used you can no longer turn debug mode 
  1458. on and off with the #debug command. 
  1459.  
  1460. The following switches are also simulated: 
  1461.  
  1462.          /INFO 
  1463.  
  1464.  
  1465. ΓòÉΓòÉΓòÉ 2.6. /DebugTime ΓòÉΓòÉΓòÉ
  1466.  
  1467. Switch /DebugTime[:NoOrFormat] 
  1468.  
  1469. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  1470. switches in the "PPWIZARD_OPTIONS" environment variable. 
  1471.  
  1472. By default ppwizard outputs the elapsed time (short display format) at the 
  1473. start of any debug line it outputs. This option allows you to select a longer 
  1474. format (HH:MM:SS.99) or turn off time generation altogether. 
  1475.  
  1476. Outputting the time can help you identify areas of code that may be taking 
  1477. longer than you'd expect to execute. 
  1478.  
  1479. The parameter should be one of the following values: 
  1480.  
  1481.          N or NO 
  1482.  
  1483.          L or LONG 
  1484.  
  1485.          S or SHORT 
  1486.  
  1487.  Note that ppwizard is optimised for fast execution with debug turned off, and 
  1488.  in fact may perform extra work when debug is on (on the assumption that 
  1489.  execution time is not an issue). For these reasons you should use the timings 
  1490.  you obtain as a guide only. 
  1491.  
  1492.  Note that a regina bug prevents this from working correctly at this time. 
  1493.  
  1494.  
  1495. ΓòÉΓòÉΓòÉ 2.7. /Define ΓòÉΓòÉΓòÉ
  1496.  
  1497. Switch /Define:Variable=Contents 
  1498.  
  1499. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  1500. switches in the "PPWIZARD_OPTIONS" environment variable. 
  1501.  
  1502. This command sets variables (like #define), but from the command line.  You can 
  1503. set as many variables as you wish. 
  1504.  
  1505. If the contents needs to include a space you should use "<?Space>" instead. 
  1506.  
  1507. EXAMPLE 
  1508.  
  1509. Define 2 variables 
  1510.  
  1511.     ppwizard.cmd 1.in /output:out\*.out /CrLf /Define:OpSys=OS/2
  1512.  
  1513. In your code you could do: 
  1514.  
  1515.     #if '<$OpSys>' = 'OS/2'
  1516.         ...
  1517.     #elseif
  1518.         ...
  1519.     #endif
  1520.  
  1521.  
  1522. ΓòÉΓòÉΓòÉ 2.8. /DependsOn ΓòÉΓòÉΓòÉ
  1523.  
  1524. Switch /DependsOn:[-]EditMask 
  1525.  
  1526. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  1527. switches in the "PPWIZARD_OPTIONS" environment variable. 
  1528.  
  1529. This option requires a parameter which controls how the "InputFile" parameter 
  1530. is transformed into the name of a dependancy file.  The default is that there 
  1531. is no dependancy file (therefore dependancies are not checked).  If you use 
  1532. dependancy files then the output is only built if required (a source file has 
  1533. changed). 
  1534.  
  1535. Unless you preceeded the EditMask parameter with a '-' the dependancy checking 
  1536. progress is displayed. 
  1537.  
  1538. You can not build a system that can not be reliably tracked however you may 
  1539. need to use the #DependsOn command if you directly access files yourself via 
  1540. macros. on 
  1541.  
  1542. An edit mask is basically much like a file (with path if required) and will 
  1543. contain zero or one special characters as follows: 
  1544.  
  1545.        1. * or {$BASE} 
  1546.           This gets replaced with the short filename (less extension) of the 
  1547.           current input file.
  1548.  
  1549.        2. ? or {$PATH} 
  1550.           This gets replaced with the path (including terminating slash) of the 
  1551.           current input file. This is most likely to be of use if you want to 
  1552.           position generated files relative to the input file and you use the 
  1553.           "/ScanSubDir" switch. For example "?OUT\*.HTM".
  1554.  
  1555.        3. {$path} 
  1556.           This allows you to set up a separate tree for generated filenames, 
  1557.           the input mask and file are examined and the relative path extracted, 
  1558.           the result is either blank ('') or a relative path that ends with a 
  1559.           path separator. Note for this to work the input mask must either use 
  1560.           an absolute path, begin with '.' or '..' followed by slash or not 
  1561.           have a path attached at all otherwise ppwizard will abort. It would 
  1562.           be pointless to use this sort of path unless the "/ScanSubDir" switch 
  1563.           was also used.
  1564.  
  1565.  The "EditMask" can be absolute or relative (your exact circumstances will 
  1566.  determine your choice). 
  1567.  
  1568.  Note that resultant relative filenames are always relative to the current 
  1569.  directory. 
  1570.  
  1571.  While you control the case of the mask you can't control the case of the part 
  1572.  that replaces the '*'.  What you can do is ensure the whole name is either in 
  1573.  upper or lower case with the /FileNames switch. 
  1574.  
  1575.  EXAMPLE 
  1576.  
  1577.  In the following example the command will check/create a file called 
  1578.  "OUT\DEPEND\IN.DEP": 
  1579.  
  1580.       +-[ MAKEIT.CMD ]----------------------------------------------------+
  1581.       | @echo off                                                         |
  1582.       | ppwizard.cmd IN.IT /Output:OUT\*.html /DependsOn:OUT\DEPEND\*.DEP |
  1583.       | if errorlevel 1 echo ERROR: Command failed!                       |
  1584.       +-------------------------------------------------------------------+
  1585.  
  1586.  
  1587. ΓòÉΓòÉΓòÉ 2.9. /DependsOnComplete ΓòÉΓòÉΓòÉ
  1588.  
  1589. Switch /DependsOnComplete[:YesOrNo] 
  1590.  
  1591. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  1592. switches in the "PPWIZARD_OPTIONS" environment variable. 
  1593.  
  1594. This switch alters the way "/DependsOn" works. 
  1595.  
  1596. Normally ppwizard is very strict in its input dependancy checking in that it 
  1597. puts itself and any spelling dictionaries used in the list. This means that 
  1598. when one of these items changes everything gets remade. While the safest option 
  1599. is to leave it on you may wish to turn it off. 
  1600.  
  1601. Note that this switch controls the building of the dependancy file.  Existing 
  1602. dependancy files will need to rebuild at least once under the new setting for 
  1603. everything to work as you wish, for this reason you may wish to delete any 
  1604. existing dependancy files when you change the setting. 
  1605.  
  1606. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  1607. one of the following values is expected: 
  1608.  
  1609.          Y 
  1610.          N 
  1611.          YES 
  1612.          NO 
  1613.  
  1614.  
  1615. ΓòÉΓòÉΓòÉ 2.10. /Exclude ΓòÉΓòÉΓòÉ
  1616.  
  1617. Switch /Exclude:FileMask 
  1618.  
  1619. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  1620. switches in the "PPWIZARD_OPTIONS" environment variable. 
  1621.  
  1622. Sometimes you may wish to process most files with a few exceptions, this switch 
  1623. allows you to specify those exceptions.  The switch may be used as many times 
  1624. as required. 
  1625.  
  1626.     ppwizard.cmd *.IT /Exclude:TEST*.IT /Exclude:TRY?.IT /Output:OUT\*.html
  1627.  
  1628.  
  1629. ΓòÉΓòÉΓòÉ 2.11. /FileNames ΓòÉΓòÉΓòÉ
  1630.  
  1631. Switch /FileNames:TranslateType 
  1632.  
  1633. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  1634. switches in the "PPWIZARD_OPTIONS" environment variable. 
  1635.  
  1636. Normally the case of output filenames are not modified, you can override this 
  1637. behaviour with this command line switch.  It requires either "Upper" or "Lower" 
  1638. as a parameter. 
  1639.  
  1640.  
  1641. ΓòÉΓòÉΓòÉ 2.12. /FilterInput ΓòÉΓòÉΓòÉ
  1642.  
  1643. Switch /FilterInput:RexxCmdFile 
  1644.  
  1645. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  1646. switches in the "PPWIZARD_OPTIONS" environment variable. 
  1647.  
  1648. This will probably be a rarely used option.  This switch allows you to 
  1649. translate file input a line at a time.  The mechanism provides the filter 
  1650. enough information to perform complex processing (in case required).  Your 
  1651. filter routine will return the possibly changed line or lines. 
  1652.  
  1653. In most cases it would probably be easier to write a translation procedure as a 
  1654. separate step before PPWIZARD is invoked (however sometimes this may not be 
  1655. practical). 
  1656.  
  1657. The rexx filter code you identify will be passed the following arguments: 
  1658.  
  1659.        1. The literal 'I' indicates that input is being filtered. 
  1660.  
  1661.        2. The line as read by rexx (still has comments and all whitespace). 
  1662.  
  1663.        3. The name of the file where the line came from. 
  1664.  
  1665.        4. The line number of the source file being processed (first line is 1). 
  1666.  
  1667.        5. The overall input line number (counter). 
  1668.  
  1669.        6. The newline character you should use if returning more than one line. 
  1670.  
  1671.  The following environment variables are also available for use: 
  1672.  
  1673.        1. PPWIZARD_VER_II 
  1674.           This variable contains the version number of the interface used by 
  1675.           this program.  This version number will only change when PPWIZARD has 
  1676.           been modified in such a way that existing input filters could break. 
  1677.           Its is recommended that you validate the interface in your filter. 
  1678.  
  1679.        2. PPWIZARD_DEBUG 
  1680.           This variable tells you the current debug state ('Y' means on).  This 
  1681.           can be modified by the #debug command or the "/debug" command line 
  1682.           switch. 
  1683.  
  1684.        3. Your Own Variables 
  1685.           You can create your own state variables in the environment. 
  1686.  
  1687.  I have a need where each input line is encrypted to prevent tampering by 
  1688.  users, the source is divided over many header files. For a number of reasons I 
  1689.  do not wish to perform a separate step to get the files in the clear.  This 
  1690.  switch is my generic solution. 
  1691.  
  1692.  WHAT YOU RETURN 
  1693.  
  1694.        1. You may modify the passed line in any way you wish and return the 
  1695.           result. 
  1696.  
  1697.        2. You may pass back more than one line by separating the lines with the 
  1698.           passed newline character.  This allows you to insert macros or 
  1699.           #include instructions. 
  1700.  
  1701.        3. You may drop a line altogether by returning the string value 
  1702.           "d2c(0)". 
  1703.  
  1704.        4. You may indicate an error by returning "d2c(0)" followed the error 
  1705.           message, processing will stop. 
  1706.  
  1707.  EXAMPLE OF INPUT FILTER 
  1708.  
  1709.   /************************************************/
  1710.   /* Stupid non-useful example of an input filter */
  1711.   /************************************************/
  1712.  
  1713.   /*--- Get ALL parameters ----------------------------------------------------*/
  1714.   FilterType   = arg(1);
  1715.   TheLine      = arg(2);
  1716.   FromFile     = arg(3);
  1717.   FromFileLine = arg(4);
  1718.   TotalLine    = arg(5);
  1719.   NewLine      = arg(6);
  1720.  
  1721.   /*--- Check ONCE if on correct interface ------------------------------------*/
  1722.   if  TotalLine = 1 then
  1723.   do
  1724.      /*--- Filter written to interface version "98.131" --------------------------*/
  1725.      WrittenToFilterVer = "98.131";
  1726.      CallersVer         = GetEnv("PPWIZARD_VER_II");
  1727.      if  CallersVer <> WrittenToFilterVer then
  1728.          return(d2c(0) || 'FILTERIN: Interface written to version ' || WrittenToFilterVer || ' (found ' || CallersVer || ')' );
  1729.   end;
  1730.  
  1731.   /*--- Get current debug state (output input line if debug is on) ------------*/
  1732.   DebugOn = GetEnv("PPWIZARD_DEBUG");
  1733.   if DebugOn = 'Y' then
  1734.      say 'FILTERIN: #' || TotalLine || ' -> ' || TheLine;
  1735.  
  1736.   /*--- Process the input -----------------------------------------------------*/
  1737.   if  TotalLine = 1 then
  1738.   do
  1739.      /*--- We wish to drop the 1st line ---------------------------------------*/
  1740.      if  DebugOn = 'Y' then
  1741.          say '          We are dropping this line';
  1742.       return(d2c(0));
  1743.   end;
  1744.   else
  1745.   do
  1746.      /*--- Now either insert a line (if 4th) or return line unchanged ---------*/
  1747.      if  TotalLine = 4 then
  1748.          return(TheLine || NewLine || 'This line was inserted after the 4th line input line!');
  1749.      else
  1750.          return(TheLine);
  1751.   end;
  1752.  
  1753.  
  1754.   /*===========================================================================*/
  1755.   GetEnv:
  1756.   /*                                                                           */
  1757.   /* arg(1) : Name of environment variable.                                    */
  1758.   /*===========================================================================*/
  1759.      return( value(arg(1),,'OS2ENVIRONMENT') );
  1760.  
  1761.  
  1762. ΓòÉΓòÉΓòÉ 2.13. /FilterOutput ΓòÉΓòÉΓòÉ
  1763.  
  1764. Switch /FilterOutput:RexxCmdFile 
  1765.  
  1766. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  1767. switches in the "PPWIZARD_OPTIONS" environment variable. 
  1768.  
  1769. This will probably be a rarely used option.  This switch allows you to 
  1770. translate all generated lines a line at a time.  The mechanism provides the 
  1771. filter enough information to perform complex processing (in case required). 
  1772. Your filter program actually writes all output lines. 
  1773.  
  1774. In most cases it would probably be easier to write a translation procedure as a 
  1775. separate step after PPWIZARD has completed (however sometimes this may not be 
  1776. practical). 
  1777.  
  1778. The rexx filter code you identify will be passed the following arguments: 
  1779.  
  1780.        1. The literal 'O' indicates that output is being filtered. 
  1781.  
  1782.        2. The generated line without terminating newline. 
  1783.  
  1784.        3. The name of the output file. 
  1785.  
  1786.        4. The number of lines already generated to the file (starts at 0). 
  1787.  
  1788.        5. The overall number of lines generated. 
  1789.  
  1790.        6. The newline character(s) that need to terminate each line that you 
  1791.           write.  The value of the newline may change if /CrLf is used. 
  1792.  
  1793.  The following environment variables are also available for use: 
  1794.  
  1795.        1. PPWIZARD_VER_OI 
  1796.           This variable contains the version number of the interface used by 
  1797.           this program.  This version number will only change when PPWIZARD has 
  1798.           been modified in such a way that existing output filters could break. 
  1799.           Its is recommended that you validate the interface in your filter. 
  1800.  
  1801.        2. PPWIZARD_DEBUG 
  1802.           This variable tells you the current debug state ('Y' means on).  This 
  1803.           can be modified by the #debug command or the "/debug" command line 
  1804.           switch. 
  1805.  
  1806.        3. Your Own Variables 
  1807.           The filter program can create its own state variables in the 
  1808.           environment, this is demonstrated in the example further on.  You can 
  1809.           also set environment variables with the built in SetEnv routine. 
  1810.  
  1811.  WHAT YOU RETURN 
  1812.  
  1813.        1. If successful you should return the string "OK:" followed by the 
  1814.           number of lines you wrote to the output file.  For example you would 
  1815.           return "OK:0" if you dropped the passed line. 
  1816.  
  1817.        2. Any string that does not begin with "OK:" indicates an error. The 
  1818.           message will be displayed and processing will stop. 
  1819.  
  1820.  EXAMPLE OF OUTPUT FILTER 
  1821.  
  1822.   /*************************************************/
  1823.   /* Stupid non-useful example of an output filter */
  1824.   /*************************************************/
  1825.  
  1826.   /*--- Get ALL parameters ----------------------------------------------------*/
  1827.   FilterType   = arg(1);
  1828.   TheLine      = arg(2);
  1829.   ToFile       = arg(3);
  1830.   ToFileLine   = arg(4);                                     /* Written so far */
  1831.   TotalLine    = arg(5);                                     /* Written so far */
  1832.   NewLine      = arg(6);
  1833.  
  1834.   /*--- Check "ONCE" if on correct interface (Actually checked twice) ---------*/
  1835.   if  TotalLine = 0 then
  1836.   do
  1837.      /*--- Filter written to interface version "98.132" -----------------------*/
  1838.      WrittenToFilterVer = "98.132";
  1839.      CallersVer         = GetEnv("PPWIZARD_VER_OI");
  1840.      if  CallersVer <> WrittenToFilterVer then
  1841.          return( 'FILTEROUT: Interface written to version ' || WrittenToFilterVer || ' (found ' || CallersVer || ')' );
  1842.   end;
  1843.  
  1844.   /*--- Get current debug state (output input line if debug is on) ------------*/
  1845.   DebugOn = GetEnv("PPWIZARD_DEBUG");
  1846.   if DebugOn = 'Y' then
  1847.      say 'FILTEROUT: #' || TotalLine+1 || ' -> ' || TheLine;
  1848.  
  1849.   /*--- If first line drop (this is complicated by line counters not changing!)*/
  1850.   if  TotalLine = 0 then
  1851.   do
  1852.      /*--- Only drop the first "first" file! ----------------------------------*/
  1853.      if  GetEnv('FiltOut_0') = '' then
  1854.      do
  1855.          /*--- We wish to drop the 1st line -----------------------------------*/
  1856.          if  DebugOn = 'Y' then
  1857.              say '          We are dropping the first line of output';
  1858.          call SetEnv 'FiltOut_0', 'Line 0 dropped';
  1859.          return("OK:0");
  1860.      end;
  1861.   end;
  1862.  
  1863.   /*--- All lines reversed (except inserted 5th) ------------------------------*/
  1864.   NumberOfLines = 1;
  1865.   ToWrite       = reverse(TheLine);
  1866.   if  TotalLine = 3 then
  1867.   do
  1868.      /*--- We are inserting a line (generating 2) -----------------------------*/
  1869.      NumberOfLines = 2;
  1870.      ToWrite       = ToWrite || NewLine || 'This line was inserted after the 4th output line line!';
  1871.   end;
  1872.  
  1873.   /*--- Output the data -------------------------------------------------------*/
  1874.   if  0 <> charout(ToFile, ToWrite || NewLine) then
  1875.      return('Write to "' || ToFile || '" failed!');
  1876.   else
  1877.      return("OK:" || NumberOfLines);
  1878.  
  1879.  
  1880.  
  1881.  
  1882.   /*===========================================================================*/
  1883.   GetEnv:
  1884.   /*                                                                           */
  1885.   /* arg(1) : Name of environment variable.                                    */
  1886.   /*===========================================================================*/
  1887.      return( value(arg(1),,'OS2ENVIRONMENT') );
  1888.  
  1889.  
  1890.  
  1891.  
  1892.   /*===========================================================================*/
  1893.   SetEnv:
  1894.   /*                                                                           */
  1895.   /* arg(1) : Name of environment variable.                                    */
  1896.   /* arg(2) : New Value.                                                       */
  1897.   /*                                                                           */
  1898.   /* Returns original value of the environment variable.                       */
  1899.   /*===========================================================================*/
  1900.      return( value(arg(1),arg(2),'OS2ENVIRONMENT') );
  1901.  
  1902.  
  1903. ΓòÉΓòÉΓòÉ 2.14. /GetEnv ΓòÉΓòÉΓòÉ
  1904.  
  1905. Switch /GetEnv:EnvVarName 
  1906.  
  1907. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  1908. switches in the "PPWIZARD_OPTIONS" environment variable. 
  1909.  
  1910. This allows you to specify an environment variable which must exist and whose 
  1911. value is more PPWIZARD command line parameters. 
  1912.  
  1913. This switch could be used to handle long command line, it effectively allows 
  1914. you to have an infinitely long command line since the included contents can 
  1915. itself refer to other environment variables. 
  1916.  
  1917.  
  1918. ΓòÉΓòÉΓòÉ 2.15. /HTML ΓòÉΓòÉΓòÉ
  1919.  
  1920. Switch /HTML 
  1921.  
  1922. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  1923. switches in the "PPWIZARD_OPTIONS" environment variable. 
  1924.  
  1925. This switch should rarely be required as html mode is the default mode unless 
  1926. all input files end in the extension ".X" (its use is recommended for rexx 
  1927. source code). 
  1928.  
  1929. On non unix operating systems lines end with carriage return followed by 
  1930. linefeed, with the internet unix has finally won (it only requires lines to 
  1931. terminate with a linefeed).  Web servers and browsers do not require the 
  1932. carriage return (which they ignore).  You can save an extra one character per 
  1933. line with use of the /CRLF switch. 
  1934.  
  1935. This switch sets the processing mode for the output file as well as the default 
  1936. processing mode for other output files specified with the #Output command. 
  1937.  
  1938.  
  1939. ΓòÉΓòÉΓòÉ 2.16. /HtmlGenerator ΓòÉΓòÉΓòÉ
  1940.  
  1941. Switch /HtmlGenerator:Contents 
  1942.  
  1943. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  1944. switches in the "PPWIZARD_OPTIONS" environment variable. 
  1945.  
  1946. By default when generating HTML, ppwizard will try to insert a meta tag similar 
  1947. to the following in the "HEAD" section: 
  1948.  
  1949.     <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)">
  1950.  
  1951. You can turn off the generation of the tags altogether by specifying an empty 
  1952. value or you can supply alternative line(s). 
  1953.  
  1954. PPWIZARD is supplied as freeware and I would appreciate it if you at least 
  1955. mention PPWIZARD and its homepage in the pages that you generate (either in 
  1956. meta tags or comments). The switch is mainly supplied so that you can add your 
  1957. own details if you wish. 
  1958.  
  1959. If you wish to specify your own generator contents (or refer to ppwizard 
  1960. details in HTML comments) you can make use of these variables (on the command 
  1961. line replace '<' with '{x3C}' and '>' with '{x3E}') : 
  1962.  
  1963.        1. <?PpwizardAuthor> 
  1964.        2. <?PpwizardAuthorEmail> 
  1965.        3. <?PpwizardAuthorHomePage> 
  1966.        4. <?PpwizardHomePage> 
  1967.  
  1968.  The value you wish to give this switch is probably so large that you would 
  1969.  normally need to use the /GetEnv switch to get the information out of an 
  1970.  environment variable. 
  1971.  
  1972.  
  1973. ΓòÉΓòÉΓòÉ 2.17. /Inc2Cache ΓòÉΓòÉΓòÉ
  1974.  
  1975. Switch /Inc2Cache[:YesOrNo] 
  1976.  
  1977. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  1978. switches in the "PPWIZARD_OPTIONS" environment variable. 
  1979.  
  1980. This switch can be used to override the way PPWIZARD includes files. This would 
  1981. not normally be required as PPWIZARD is likely to choose a good way. 
  1982.  
  1983. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  1984. one of the following values is expected: 
  1985.  
  1986.          Y 
  1987.          N 
  1988.          YES 
  1989.          NO 
  1990.  
  1991.  Warning 
  1992.  
  1993.  Loading the files to cache will of course require more memory than you'd 
  1994.  otherwise require. From what I gather Windows (95/98 and NT!) do not have very 
  1995.  good memory management. 
  1996.  
  1997.  
  1998. ΓòÉΓòÉΓòÉ 2.18. /Info ΓòÉΓòÉΓòÉ
  1999.  
  2000. Switch /Info[:YesOrNo] 
  2001.  
  2002. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  2003. switches in the "PPWIZARD_OPTIONS" environment variable. 
  2004.  
  2005. By default important informational messages may be output, these could be 
  2006. considered as similar to a warning but no as severe.  They inform you of 
  2007. situations that are unusual but may be perfectly OK in your environment.  This 
  2008. switch allows you to turn these messages off. 
  2009.  
  2010. It is recommended that you do not turn them off. 
  2011.  
  2012. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  2013. one of the following values is expected: 
  2014.  
  2015.          Y 
  2016.          N 
  2017.          YES 
  2018.          NO 
  2019.  
  2020.  
  2021. ΓòÉΓòÉΓòÉ 2.19. /Other ΓòÉΓòÉΓòÉ
  2022.  
  2023. Switch /Other 
  2024.  
  2025. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  2026. switches in the "PPWIZARD_OPTIONS" environment variable. 
  2027.  
  2028. This switch indicates that the input is not one of the types specifically 
  2029. supported such as HTML or REXX.  It turns of any funny stuff while in #AsIs 
  2030. Mode. 
  2031.  
  2032. This switch sets the processing mode for the output file as well as the default 
  2033. processing mode for other output files specified with the #Output command. 
  2034.  
  2035.  
  2036. ΓòÉΓòÉΓòÉ 2.20. /Option ΓòÉΓòÉΓòÉ
  2037.  
  2038. Switch /Option:OptionParameters 
  2039.  
  2040. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  2041. switches in the "PPWIZARD_OPTIONS" environment variable. 
  2042.  
  2043. The "OptionParameters" is basically anything that is acceptable on the #option 
  2044. command. 
  2045.  
  2046. When PPWIZARD starts it sets up a default value for each option. This switch 
  2047. allows you to modify the value to suit your needs. 
  2048.  
  2049. Warning 
  2050.  
  2051. You may need to be careful about some of the characters used on a command line 
  2052. or when setting an environment variable.  For example from an OS/2 command 
  2053. prompt you can not set an environment variable to a value that contains an 
  2054. equal sign, you would need to use '{x3D}' (it's ASCII code in hexadecimal) 
  2055. instead. 
  2056.  
  2057.  
  2058. ΓòÉΓòÉΓòÉ 2.21. /Output ΓòÉΓòÉΓòÉ
  2059.  
  2060. Switch /Output:EditMask 
  2061.  
  2062. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  2063. switches in the "PPWIZARD_OPTIONS" environment variable. 
  2064.  
  2065. This parameter controls how the "InputFile" parameter is transformed to 
  2066. generate the correct name for the generated output file. on 
  2067.  
  2068. An edit mask is basically much like a file (with path if required) and will 
  2069. contain zero or one special characters as follows: 
  2070.  
  2071.        1. * or {$BASE} 
  2072.           This gets replaced with the short filename (less extension) of the 
  2073.           current input file.
  2074.  
  2075.        2. ? or {$PATH} 
  2076.           This gets replaced with the path (including terminating slash) of the 
  2077.           current input file. This is most likely to be of use if you want to 
  2078.           position generated files relative to the input file and you use the 
  2079.           "/ScanSubDir" switch. For example "?OUT\*.HTM".
  2080.  
  2081.        3. {$path} 
  2082.           This allows you to set up a separate tree for generated filenames, 
  2083.           the input mask and file are examined and the relative path extracted, 
  2084.           the result is either blank ('') or a relative path that ends with a 
  2085.           path separator. Note for this to work the input mask must either use 
  2086.           an absolute path, begin with '.' or '..' followed by slash or not 
  2087.           have a path attached at all otherwise ppwizard will abort. It would 
  2088.           be pointless to use this sort of path unless the "/ScanSubDir" switch 
  2089.           was also used.
  2090.  
  2091.  The "EditMask" can be absolute or relative (your exact circumstances will 
  2092.  determine your choice). 
  2093.  
  2094.  Note that resultant relative filenames are always relative to the current 
  2095.  directory. 
  2096.  
  2097.  While you control the case of the mask you can't control the case of the part 
  2098.  that replaces the '*'.  What you can do is ensure the whole name is either in 
  2099.  upper or lower case with the /FileNames switch. 
  2100.  
  2101.  The default mask is "*.htm".  I place all my output into a separate "OUT" 
  2102.  directory and use "/Output:OUT\*.HTM". 
  2103.  
  2104.  
  2105. ΓòÉΓòÉΓòÉ 2.22. /Pack ΓòÉΓòÉΓòÉ
  2106.  
  2107. Switch /Pack[:YesOrNo] 
  2108.  
  2109. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  2110. switches in the "PPWIZARD_OPTIONS" environment variable. 
  2111.  
  2112. This switch is only useful if "/rexx" is also specified.  You can get a much 
  2113. smaller generated rexx program by packing (off by default).  Packing does not 
  2114. significantly slow down processing. 
  2115.  
  2116. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  2117. one of the following values is expected: 
  2118.  
  2119.          Y 
  2120.          N 
  2121.          YES 
  2122.          NO 
  2123.  
  2124.  MORE ON PACKING 
  2125.  
  2126.  The preprocessor packs well written code (by my definition!) and can fail to 
  2127.  correctly pack code where strings are appended without the use of the "||" 
  2128.  operator (as the excess spaces will be removed).  For example the following 
  2129.  statement will not create the string you expect when packed: 
  2130.  
  2131.          BothPartsCombined = 'Value:'   TheValue;
  2132.  
  2133.  The following statement is a version of the above that will work: 
  2134.  
  2135.           BothPartsCombined = 'Value:   ' || TheValue;
  2136.  
  2137.  You can get very good results by packing but if you have got legacy code or 
  2138.  you don't wish to change (your evil ways!) you should use the "/Pack:N" 
  2139.  command line switch.  This turns off most packing (rexx comment and trailing 
  2140.  ';' removal still occurs). 
  2141.  
  2142.  If you have trouble with some parts of your code but the bulk packs well then 
  2143.  you may wish to consider leaving packing on and using the AllowPack option to 
  2144.  indicate parts of your rexx code that should not be packed. 
  2145.  
  2146.  WARNING 
  2147.  
  2148.  This has not been tested on object rexx so I don't know if it will work or not 
  2149.  (I assume it will). 
  2150.  
  2151.  
  2152. ΓòÉΓòÉΓòÉ 2.23. /Rexx ΓòÉΓòÉΓòÉ
  2153.  
  2154. Switch /Rexx 
  2155.  
  2156. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  2157. switches in the "PPWIZARD_OPTIONS" environment variable. 
  2158.  
  2159. The input is treated as rexx source.  Rexx comments are removed from the 
  2160. source. 
  2161.  
  2162. This switch sets the processing mode for the output file as well as the default 
  2163. processing mode for other output files specified with the #Output command. 
  2164.  
  2165. Packing of the resultant rexx code (within one generated line) occurs by 
  2166. default.  You can specify "/Pack" if you don't want this done.  Turning off 
  2167. packing will speed up the generation of rexx code but in my mind the 
  2168. compression gain from leaving it on is worth it. 
  2169.  
  2170. Other options you may wish to use are "LeaveBlankLines" & "KeepIndent". 
  2171.  
  2172. WARNING 
  2173.  
  2174. Note that if you are taking unknown code and passing it through the 
  2175. preprocessor to reduce its size you should use the "/Pack;N" option as there 
  2176. are situations where the operation of the code will be affected.  Some good and 
  2177. safe reduction in code size will still occur. 
  2178.  
  2179.  
  2180. ΓòÉΓòÉΓòÉ 2.24. /SpellAddWord ΓòÉΓòÉΓòÉ
  2181.  
  2182. Switch /SpellAddWord:[-]NameOfAddFile 
  2183.  
  2184. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  2185. switches in the "PPWIZARD_OPTIONS" environment variable. 
  2186.  
  2187. This option can be specified if you have used /SpellCheck (use empty dictionary 
  2188. if required) to enable spell checking. 
  2189.  
  2190. What it allows you to do is indicate which incorrect words should be added to a 
  2191. dictionary file. All words you wish to add are added to the file sorted in 
  2192. order of the number of occurances of this word so that the most frequently used 
  2193. (therefore most important) are first. 
  2194.  
  2195. You would typically manually cut and paste words from the generated file to one 
  2196. of your dictionary files. 
  2197.  
  2198. To automatically add all words to the file preceed the filename with "-". 
  2199.  
  2200.  
  2201. ΓòÉΓòÉΓòÉ 2.25. /SpellCheck ΓòÉΓòÉΓòÉ
  2202.  
  2203. Switch /SpellCheck:NameOfDictionary 
  2204.  
  2205. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  2206. switches in the "PPWIZARD_OPTIONS" environment variable. 
  2207.  
  2208. This option loads a dictionary and turns on spell checking. The switch can be 
  2209. used any number of times to load as many dictionaries as you wish. As an 
  2210. example you might wish to set up "GLOBAL.DIC", "PROJECT.DIC" and "JUNK.DIC". 
  2211.  
  2212. You may need to set up "JUNK.DIC" to hold junk words that are not really valid 
  2213. but get picked up as words during the spell check. In interactive spell 
  2214. checking such as in Microsoft word, these junk words are the annoying ones you 
  2215. keep replying "Ignore All" to! 
  2216.  
  2217. Note that ppwizard ignores the case of words and should work for international 
  2218. languages such as German. 
  2219.  
  2220. The /SpellAddWord will help you update or create dictionaries. 
  2221.  
  2222. A dictionary file must exist and it can be empty. 
  2223.  
  2224. There are large dictionaries available (such as in isspell40.zip on hobbes) 
  2225. however this take too long to load if you are impatient like me. The extra time 
  2226. will be required to load the extra words into memory, once loaded I do not 
  2227. think it will take longer to process your files. 
  2228.  
  2229. Spell checking has 2 basic modes (you can use both together) as follows:, 
  2230.  
  2231.          You can indicate words that you frequently get wrong and ppwizard 
  2232.           will tell you when you use the word. 
  2233.  
  2234.          You can supply a list of "good" words (dictionaries) and ppwizard 
  2235.           will tell you if you use a word which is not in a dictionary. 
  2236.  
  2237.  Dictionaries 
  2238.  
  2239.  All leading whitespace on all lines is ignored as are any blank lines or lines 
  2240.  that begin with ';' (a comment). 
  2241.  
  2242.  There are two types of dictionary entries as follows: 
  2243.  
  2244.        1. A valid word. Each word occurs on its own line. The fact that we have 
  2245.           loaded at least one dictionary word (you are not required to do so) 
  2246.           means that ppwizard will try to validate (spell check) all words. 
  2247.           Note that a "word" can contain any characters and so if required 
  2248.           could be "ASD%^". 
  2249.  
  2250.        2. A '$command' as follows: 
  2251.  
  2252.               $MISTAKE 
  2253.                This command allows you to specify a word that you frequently 
  2254.                get wrong. Ppwizard will tell you if you use this word. The 
  2255.                command takes one or two parameters the first parameter is the 
  2256.                incorrectly spelt word while the second (if passed) is the word 
  2257.                correctly spelt. 
  2258.  
  2259.               $DELIMITERS 
  2260.                If you don't like the default delimiters that ppwizard uses then 
  2261.                you can specify a rexx expression which represents the 
  2262.                delimiters you wish to use. Each character you specify is 
  2263.                converted to a space and is therefore ignored. A warning is 
  2264.                generated if this command is used more than once. 
  2265.  
  2266.  Example of Dictionary 
  2267.  
  2268.       ;--- Add common mistakes ----
  2269.       $mistake seperate
  2270.  
  2271.       ;--- Specify alternate delimiters ----
  2272.       $Delimiters d2c(9) || ',.=:;<>&-%()!/~?#${}[]"'
  2273.  
  2274.       ;--- A few words ----
  2275.       THE
  2276.       CAT
  2277.       DOG
  2278.       computer.
  2279.  
  2280.  
  2281. ΓòÉΓòÉΓòÉ 2.26. /SpellShowAll ΓòÉΓòÉΓòÉ
  2282.  
  2283. Switch /SpellShowAll[:YesOrNo] 
  2284.  
  2285. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  2286. switches in the "PPWIZARD_OPTIONS" environment variable. 
  2287.  
  2288. By default you only see a warning for the first time a word error occurs in 
  2289. each build. This switch allows you to indicate that you would like to see every 
  2290. error. 
  2291.  
  2292. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  2293. one of the following values is expected: 
  2294.  
  2295.          Y 
  2296.          N 
  2297.          YES 
  2298.          NO 
  2299.  
  2300.  
  2301. ΓòÉΓòÉΓòÉ 2.27. /ScanSubDir ΓòÉΓòÉΓòÉ
  2302.  
  2303. Switch /ScanSubDir 
  2304.  
  2305. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  2306. switches in the "PPWIZARD_OPTIONS" environment variable. 
  2307.  
  2308. By default this program only checks the directory specified in the "InputMask", 
  2309. specify this option if you wish to process subdirectories as well. 
  2310.  
  2311.  
  2312. ΓòÉΓòÉΓòÉ 2.28. /Sleep ΓòÉΓòÉΓòÉ
  2313.  
  2314. Switch /Sleep:NumberOfSeconds 
  2315.  
  2316. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  2317. switches in the "PPWIZARD_OPTIONS" environment variable. 
  2318.  
  2319. This option can be used to pause execution for a period of time after PPWIZARD 
  2320. completes processing normally (no trap etc).  Used with the "/DependsOn" switch 
  2321. could be used in place of a CRON step to poll for data file changes. 
  2322.  
  2323. If you like the sound of this be sure to also check out the "/Template" switch. 
  2324.  
  2325.  
  2326. ΓòÉΓòÉΓòÉ 2.29. /Tabs ΓòÉΓòÉΓòÉ
  2327.  
  2328. Switch /Tabs:TabOption 
  2329.  
  2330. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  2331. switches in the "PPWIZARD_OPTIONS" environment variable. 
  2332.  
  2333. The "TabOption" parameter controls how tabs if found are handled. Valid options 
  2334. are: 
  2335.  
  2336.          Ignore 
  2337.           Don't do anything, just ignore, this may cause preprocessor to fail 
  2338.           (depending on where tabs are located). 
  2339.  
  2340.          ToSpaces 
  2341.           Each tab is converted to one only space. 
  2342.  
  2343.          Warnings 
  2344.           Each tab is converted to one only space and a warning is generated. 
  2345.           This is the default condition. 
  2346.  
  2347.  
  2348. ΓòÉΓòÉΓòÉ 2.30. /Template ΓòÉΓòÉΓòÉ
  2349.  
  2350. Switch /Template:TemplateFile 
  2351.  
  2352. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  2353. switches in the "PPWIZARD_OPTIONS" environment variable. 
  2354.  
  2355. Normally PPWIZARD begins by reading from the input file. This switch modifies 
  2356. this behavior.  The name of the "input file" is stored in the variable 
  2357. "<?TemplateDataFile>" and the file named on this switch is loaded instead. 
  2358.  
  2359. The template file would generally #include or #import the data file. 
  2360.  
  2361.  
  2362. ΓòÉΓòÉΓòÉ 2.31. /WarningsIgnore ΓòÉΓòÉΓòÉ
  2363.  
  2364. Switch /WarningsIgnore[:IgnoreWhich] 
  2365.  
  2366. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  2367. switches in the "PPWIZARD_OPTIONS" environment variable. 
  2368.  
  2369. This switch allows you to have individual control of which warning messages you 
  2370. wish to see. If this switch is used more than once the last used invocation is 
  2371. what is used. Warnings can come from PPWIZARD or from the #warning command. 
  2372.  
  2373. To turn off ignoring of warning messages you would not pass a parameter. This 
  2374. would be useful if you have set up a default where some messages are ignored. 
  2375.  
  2376. If you supply a parameter then you can specify one or more strings (each 
  2377. separated by ';', or ':' under unix). If the text of a warning message contains 
  2378. any of the strings (case insensitive check) then the message will not display 
  2379. and the warning return code will not be generated. If a message is dropped then 
  2380. you can still see the message in debug mode as well as the reason it normally 
  2381. gets dropped. 
  2382.  
  2383. The warning message text which is searched includes the line number as well as 
  2384. the warning ID, basically the exact text that you would normally see so you 
  2385. could prevent warnings down to a particular line number if you wish (although 
  2386. this is not recommended). 
  2387.  
  2388. Warning IDs and text are not documented so you need to wait for one to occur 
  2389. before deciding how to drop it. 
  2390.  
  2391. If you wish to see warning messages but still want a zero return code you 
  2392. should check out the /WarningsOk switch. 
  2393.  
  2394.  
  2395. ΓòÉΓòÉΓòÉ 2.32. /WarningsOk ΓòÉΓòÉΓòÉ
  2396.  
  2397. Switch /WarningsOk[:YesOrNo] 
  2398.  
  2399. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  2400. switches in the "PPWIZARD_OPTIONS" environment variable. 
  2401.  
  2402. By default when one or more warnings are displayed a return code of 1 will be 
  2403. returned, when this switch is used to indicate that Warnings are OK then a 
  2404. "good" return code of zero will be returned instead. 
  2405.  
  2406. This switch simply indicates that you don't care what warnings were displayed, 
  2407. you do not consider a warning to be an error.  You can get more fine tuning 
  2408. with the /WarningsIgnore switch. 
  2409.  
  2410. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  2411. one of the following values is expected: 
  2412.  
  2413.          Y 
  2414.          N 
  2415.          YES 
  2416.          NO 
  2417.  
  2418.  
  2419. ΓòÉΓòÉΓòÉ 2.33. /**/ ΓòÉΓòÉΓòÉ
  2420.  
  2421. Switch /**/[:YesOrNo] 
  2422.  
  2423. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  2424. switches in the "PPWIZARD_OPTIONS" environment variable. 
  2425.  
  2426. This switch only has affect when /rexx also used to turn on rexx processing. 
  2427. Normally rexx comments on ends of lines are removed.  Use this switch to leave 
  2428. them in.  Normally there would be no need to leave them in however you might 
  2429. choose to do so to aid runtime debugging. 
  2430.  
  2431. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise 
  2432. one of the following values is expected: 
  2433.  
  2434.          Y 
  2435.          N 
  2436.          YES 
  2437.          NO 
  2438.  
  2439.  
  2440. ΓòÉΓòÉΓòÉ 2.34. /#Include ΓòÉΓòÉΓòÉ
  2441.  
  2442. Switch /#INCLUDE:FileList] 
  2443.  
  2444. This is a PPWIZARD.CMD command line switch.  You can set up your own default 
  2445. switches in the "PPWIZARD_OPTIONS" environment variable. 
  2446.  
  2447. This switch allows you to specify one or more files which should automatically 
  2448. be included before any other file processing takes place.  To specify more than 
  2449. one they should be separated by a ';' character (or ':' under unix). 
  2450.  
  2451. You could use this if you supply a set of macros in header file and supply a 
  2452. batch file to run the preprocessor.  You would then not have to require (or 
  2453. request) a user of your header to '#include' it themselves. 
  2454.  
  2455. Example 
  2456.  
  2457.     ppwizard.cmd  *.it  /output:out\*.htm /CrLf /#Include:Header1.H;Header2.H
  2458.  
  2459.  
  2460. ΓòÉΓòÉΓòÉ 3. The Source Code ΓòÉΓòÉΓòÉ
  2461.  
  2462. The Source Code 
  2463.  
  2464.        1. There is no limit to how long a line may be so the only practical 
  2465.           limit will be whatever your editor or other tools impose. 
  2466.  
  2467.           You will wish to also check out the following extra details: 
  2468.  
  2469.               White Space 
  2470.               Commenting 
  2471.               Line Continuation 
  2472.               Quoted Text - qTextq 
  2473.               Quoted Text - qRestq 
  2474.               Dependancies 
  2475.  
  2476.        2. There is a range of "Standard Definitions" available for use in your 
  2477.           source.  You can create your own as well (for example a formatted 
  2478.           date/time of your document). 
  2479.  
  2480.        3. You can selectively include or exclude portions of the source code 
  2481.           using the "#if" command. 
  2482.  
  2483.        4. Large portions of text (with or without HTML tagging) that you place 
  2484.           in multiple places which you feel must be kept in sync can be defined 
  2485.           once with "#define" and referenced many times. 
  2486.  
  2487.  
  2488. ΓòÉΓòÉΓòÉ 3.1. White Space ΓòÉΓòÉΓòÉ
  2489.  
  2490. White Space 
  2491.  
  2492. By default leading whitespace is ignored.  You can use the "KeepIndent" to 
  2493. alter this. Even when not ignored all PPWIZARD commands may be indented from 
  2494. the left if you wish. 
  2495.  
  2496. Trailing whitespace is always removed from a line.  If you must have trailing 
  2497. whitespace you could specify one or more "<?Space>" codes. 
  2498.  
  2499. By default blank lines (after comment removal) are ignored. You can use the 
  2500. "LeaveBlankLines" option to alter this. 
  2501.  
  2502.  
  2503. ΓòÉΓòÉΓòÉ 3.2. Commenting ΓòÉΓòÉΓòÉ
  2504.  
  2505. Line Comments 
  2506.  
  2507. By default the commenting character is ';' if a line begins with this character 
  2508. then it is ignored. If the line contains the character doubled up (as in ;;) 
  2509. then everything after the last occurance of this string is considered to be an 
  2510. inline comment and is removed. 
  2511.  
  2512. The line comment character can be modified with the LineComment option.  You 
  2513. could add ';;' to the end of a line so that an earlier occurance and everything 
  2514. following does not get removed.  You can also use the "<?SemiColon>" code if 
  2515. required. 
  2516.  
  2517. Note that if the line being dropped is in the middle of a set of continued 
  2518. lines then the the line continuation characters at the end (or not at the end) 
  2519. of the dropped line are not ignored. 
  2520.  
  2521. Commenting Blocks of Lines 
  2522.  
  2523. The easiest way to comment out multiple lines at one time is to use the 
  2524. "#ifdef" command to check for a name that you will ensure never exists such as 
  2525. in the following example: 
  2526.  
  2527.     ;--- This is a line comment ---
  2528.     #define Highlight <B>{$Text}</B>   ;;Comment here
  2529.  
  2530.     #ifdef xxxx
  2531.     1st line commented out
  2532.     2nd line commented out
  2533.     3rd line commented out
  2534.     #endif
  2535.  
  2536.  
  2537. ΓòÉΓòÉΓòÉ 3.3. Line Continuation ΓòÉΓòÉΓòÉ
  2538.  
  2539. Line Continuation 
  2540.  
  2541. PPWIZARD can handle any length line (subject to any rexx interpreter 
  2542. limitations), however the editor you are using may have limitations or you just 
  2543. might want to format it better, PPWIZARD allows you to specify that a line 
  2544. continues onto the next line. The two or more lines will be merged together. 
  2545.  
  2546. You can continue long lines by placing the line continuation characters (' \' 
  2547. by default) at the end of a line that continues onto the next. 
  2548.  
  2549. The #OneLine command provides an alternative to the use of the line 
  2550. continuation characters and the #DefineRexx command provides a simpler way of 
  2551. formatting rexx code. 
  2552.  
  2553. It is not valid for the last line of a file to contain the line continuation 
  2554. characters, all combined lines must come from the one input file. 
  2555.  
  2556. This capability would be most useful for #define commands. 
  2557.  
  2558. The "LineContinuation" option can be used to disable line continuation or to 
  2559. change the continuation character. 
  2560.  
  2561. When you have a long #define statement that spans lines you can have any 
  2562. commands (such as #if, #elseif and #endif) within a continue block, however 
  2563. these commands themselves NEVER continue on following lines. 
  2564.  
  2565. While line continuation is taking place blank or comment lines are treated no 
  2566. differently from any other lines (that is they are not completely ignored as 
  2567. would normally be the case). If a comment line is found while collecting 
  2568. continued lines it must contain line continuation characters if the 
  2569. continuation is to continue. 
  2570.  
  2571. There are actually a number of line continuation types which make for an easier 
  2572. to read shorthand for other variations. All valid variations are listed below: 
  2573.  
  2574.        1. -\ 
  2575.           All trailing whitespace is removed from this line before the next 
  2576.           line is added. 
  2577.  
  2578.        2. +\ 
  2579.           All trailing whitespace is removed from this line before a space and 
  2580.           then the next line is added. 
  2581.  
  2582.        3. \ (space + slash) 
  2583.           All trailing whitespace is removed from this line before a single 
  2584.           space and the next line is added. 
  2585.  
  2586.        4. %\ 
  2587.           All trailing whitespace is removed from this line before a newline 
  2588.           code and the next line is added. 
  2589.  
  2590.  If the line does not end in one of the above 2 character codes then the 
  2591.  continuation character is ignored.  Note that '+\' and ' \' currently serve 
  2592.  the same purpose, in a future release you will probably be able to set the 
  2593.  default continuation type for ' \'. 
  2594.  
  2595.  Note that line continuation does not occur when the #AsIs "ON" is used. 
  2596.  
  2597.  Example of #if Use Within Line Continuation 
  2598.  
  2599.       #define TheSame                                      \
  2600.               <P>Hi, my name is Dennis Bareis and I have   \
  2601.                  been using OS/2 and developing for        \
  2602.               #if '<$AtWork>' = 'Y'                        \
  2603.                  ANZ                                       \
  2604.               #elseif                                      \
  2605.                  *WRONG INC*                               \
  2606.               #endif                                       \
  2607.               on and off since the original 1.0 version.
  2608.  
  2609.  The above shows the creation of a multi-line macro. It is recommended (and in 
  2610.  some cases required) that the definition be formatted as above, that is the 
  2611.  line is continued by '\' after the macro name. All other line continuation can 
  2612.  be as per your requirements (the above is simple but not ideal...). 
  2613.  
  2614.  Example - Good Formatting, Macro Use 
  2615.  
  2616.       <$MyMacro                         \
  2617.                  Parm1=^a parameter^    \
  2618.                  Parm2=^a parameter^    \
  2619.                  Parm3=^a parameter^    \
  2620.       >
  2621.  
  2622.  
  2623. ΓòÉΓòÉΓòÉ 3.4. Quoted Text - qTextq ΓòÉΓòÉΓòÉ
  2624.  
  2625. Quoted Text - qTextq 
  2626.  
  2627. Many commands require quoted text, the only thing special about the quotes in 
  2628. this program are that they can be almost any character (anything 
  2629. non-alphanumeric), the only restriction are as follows: 
  2630.  
  2631.        1. The same quote character must appear at the start and end of the 
  2632.           text. 
  2633.        2. If another parameter follows then there must be at least one space 
  2634.           after the end quote character. 
  2635.        3. You can omit the quote characters if the first character is 
  2636.           alphanumeric and the the text does not contain spaces. 
  2637.  
  2638.  EXAMPLES 
  2639.  
  2640.  The following are examples of valid quoted strings: 
  2641.  
  2642.          "A string" 
  2643.          'Another string' 
  2644.          ^A 'string' which contains "quotes"^ 
  2645.          ΓûêABCΓûê 
  2646.          NoQuotesRequired 
  2647.  
  2648.  
  2649. ΓòÉΓòÉΓòÉ 3.5. Quoted Text - qRestq ΓòÉΓòÉΓòÉ
  2650.  
  2651. Quoted Text - qRestq 
  2652.  
  2653. Many commands require quoted text, this format of quoted text is only ever used 
  2654. for the last parameter of some commands. 
  2655.  
  2656. This is very similar in function to the "Quoted Text - qTextq" method except 
  2657. that no more parameters are expected after the current one.  All "Quoted Text - 
  2658. qTextq" examples are valid. 
  2659.  
  2660. Everything is the same as for "Quoted Text - qTextq" except: 
  2661.  
  2662.        1. The quote character can actually appear within the quoted text. 
  2663.        2. If the value is unquoted the rest of the line (stripped of leading & 
  2664.           trailing whitespace) is used. 
  2665.        3. Nothing follows the text. 
  2666.  
  2667.  EXAMPLES 
  2668.  
  2669.  The following are examples of valid quoted strings: 
  2670.  
  2671.          ^A 'string' which contains "quotes"^ 
  2672.          "A string with "imbedded" double quotes" 
  2673.  
  2674.  
  2675. ΓòÉΓòÉΓòÉ 4. Macros ΓòÉΓòÉΓòÉ
  2676.  
  2677. Macros 
  2678.  
  2679. Macros are collections of text and/or commands and would have to be one of the 
  2680. most important and most used features of this preprocessor. 
  2681.  
  2682. Macros can be created using one of the following methods: 
  2683.  
  2684.        1. #define[+] 
  2685.        2. #evaluate[+] 
  2686.        3. MacroSet() 
  2687.        4. /define 
  2688.  
  2689.  The simplest types of macro simply allows you to define text which you will 
  2690.  use over and over again. You will want to specify it in one place so that if 
  2691.  it ever changes you won't need to hunt up all occurances. The following 
  2692.  example shows an email address being defined (this would normally be done in a 
  2693.  central place and be accessed with #include): 
  2694.  
  2695.       #define MyEmailAddress           dbareis@labyrinth.net.au
  2696.  
  2697.  Now that we have defined the email address (once as per example above), in all 
  2698.  the html pages that required it we could refer to it as in: 
  2699.  
  2700.       <P>If you have any questions or suggestions for improvements please feel free to
  2701.       <A HREF="mailto:<$MyEmailAddress>">email me</A>.
  2702.  
  2703.  There are also a number of "Standard Macros" which always exist, including the 
  2704.  following specialised forms: 
  2705.  
  2706.        1. <?xXX> 
  2707.        2. <??RexxVariable> 
  2708.  
  2709.  All normal macros are replaced before standard macros.  The "<?xXX>" form is 
  2710.  never replaced until just before the line is to be written to the output file. 
  2711.  
  2712.  The following sections provide more details about macros (please read in 
  2713.  order): 
  2714.  
  2715.        1. Simplest Macros 
  2716.        2. Using Standard Definitions + Using REXX Logic 
  2717.        3. Multi Line Macros 
  2718.        4. Macros With Mandatory Parameters 
  2719.        5. Macros With Optional Parameters 
  2720.        6. Macro Parameters without values 
  2721.        7. Positional Parameters (not named) 
  2722.        8. Expand All Unused Parameters 
  2723.        9. Special MACRO Replacement "$$" Commands 
  2724.       10. Special MACRO PARAMETER Replacement "$$" Commands 
  2725.       11. Multi Line Macros With Logic 
  2726.  
  2727.  A macro's name (or parameter) can be very long and can contain nearly any 
  2728.  character (space and end of macro replacement character are the main 
  2729.  exceptions). You will be told if a macro name is invalid when you try to 
  2730.  define it. The maximum length of a macro will be approximately 100 characters 
  2731.  in OS/2 rexx and unlimited with the regina interpreter. 
  2732.  
  2733.  The name of a macro (and it's parameters) are normally case insensitive, 
  2734.  however you can make them case sensitive by using the CsReplacement option. 
  2735.  When this option is not used all macros and parameters are converted to upper 
  2736.  case. 
  2737.  
  2738.  
  2739. ΓòÉΓòÉΓòÉ 4.1. Simplest Macros ΓòÉΓòÉΓòÉ
  2740.  
  2741. Simplest Macros 
  2742.  
  2743. The subject of macros is reasonably complex (but well worth learning) please 
  2744. ensure you have at least read the macro introduction before reading this 
  2745. section. 
  2746.  
  2747. The simplest macros don't contain any logic (just text) and are used where 
  2748. there are many places where you wish the same information used.  For example 
  2749. you might have an email address which you will refer to from 10 different HTML 
  2750. pages.  If this email address changes you do not wish to look for and then 
  2751. change all of these occurrances.  Not only would this be a real pain but you 
  2752. could miss one or get the new email address wrong on one (which you might never 
  2753. realise). 
  2754.  
  2755. You have probably got more than one macro you wish to define (others might be 
  2756. web addresses for external links), it is suggested that in general the best 
  2757. place to keep all of them is together in one place.  You could add all the 
  2758. macro definitions in one place in a file you create called "MACROS.IH". For 
  2759. example the contents of this file might be: 
  2760.  
  2761.     ;--- MY EMAIL Information ---------------------------------------------------
  2762.     #define MyEmailAddress           db0@anz.com
  2763.     #define EmailMeGraphic           <img src="graphics/email.jpg" border=0 width=28 height=19>
  2764.  
  2765.     ;--- Standard Graphics ------------------------------------------------------
  2766.     #define ImgUpdated               <IMG SRC="graphics/updated1.gif" HSPACE=10 ALIGN=middle BORDER=0 WIDTH=52 HEIGHT=12 ALT="updated">
  2767.     #define ImgNew                   <IMG SRC="graphics/new.gif"      HSPACE=10 ALIGN=middle BORDER=0 WIDTH=35 HEIGHT=20 ALT="new">
  2768.     #define ImgBarbedWire            <P><CENTER><IMG SRC="graphics/barbwire.gif"></CENTER>
  2769.  
  2770.     ;--- External WEB Addresses -------------------------------------------------
  2771.     #define HttpNetLabsMainPage      www.netlabs.org
  2772.     #define HttpNetLabsGimpPage      www.netlabs.org/gimp/
  2773.     #define HttpOs2WarpGuruMainPage  www.geocities.com/SiliconValley/Pines/7885/
  2774.     #define HttpOs2WarpGuruApmPage   <$HttpOs2WarpGuruMainPage>DownloadAPM2.html
  2775.  
  2776. At or near the start of the source for the html page (lets call it "Intro.IT") 
  2777. you would add the following statement to load the macros: 
  2778.  
  2779.     ;--- Load all required definitions ------------------------------------------
  2780.     #include "MACROS.IH"
  2781.  
  2782. Later on in "INTRO.IT" you could have the following: 
  2783.  
  2784.     <P>If you have any questions or suggestions for improvements please feel free to
  2785.     <A HREF="mailto:<$MyEmailAddress>">email me</A>.
  2786.  
  2787. As you may guess from the above example to refer to the macro you place '<$' at 
  2788. the start and '>' at the end of the macro (variables) name.  There is now only 
  2789. one place to change if your email address changes.  Not only that but if you 
  2790. get the new address wrong it should be immediately apparent as it will be wrong 
  2791. in all locations!  So not only have you simplified the process but you have 
  2792. probably improved the quality of your output as well! 
  2793.  
  2794. There are better ways to handle what was demonstrated above but hopefully the 
  2795. example was a simple enough starting point. If you are still confused I suggest 
  2796. that you read the e-Zine! articles written by Chris Wenham (the Senior Editor 
  2797. of OS/2 e-Zine! chris@os2ezine.com). 
  2798.  
  2799.  
  2800. ΓòÉΓòÉΓòÉ 4.2. Using Standard Definitions + Using REXX Logic ΓòÉΓòÉΓòÉ
  2801.  
  2802. Using Standard Definitions + Using REXX Logic 
  2803.  
  2804. The subject of macros is reasonably complex (but well worth learning) please 
  2805. ensure you have at least read the macro introduction before reading this 
  2806. section. 
  2807.  
  2808. The following example uses the "#evaluate" command and the "Standard 
  2809. Definition" of "<?OutputFile>" as well as demonstrating the use of using rexx 
  2810. code to include logic. 
  2811.  
  2812.     ;--- Capture some HTML information ------------------------------------------
  2813.     #evaluate ShortNameHtml            "_filespec('name', '<?OutputFile>')"
  2814.     #evaluate ShortNameHtmlLowerCase   "ToLowerCase('<$ShortNameHtml>')"
  2815.  
  2816. The above defined two macros, the first is the short name of the output file 
  2817. (no path or drive attached) and the second is the same short name but all lower 
  2818. case. 
  2819.  
  2820. A "Problem" Notice that the first parameter to the rexx translate function 
  2821. above is surrounded by single quotes, we could safely do this only because we 
  2822. know that a filename can't contain single quotes!  You need to be careful with 
  2823. your use of quotes etc as the macro replacement simply places the correct text 
  2824. where requested.  We could have used the PPWIZARD "MacroGet" function if we 
  2825. were not sure about the quote situation as demonstrated below: 
  2826.  
  2827.     ;--- Capture some HTML information ------------------------------------------
  2828.     #evaluate ShortNameHtmlLowerCase   "ToLowerCase(MacroGet('ShortNameHtml'))"
  2829.  
  2830. There is another (probably better way) of handling the quote 'problem' as in: 
  2831.  
  2832.     ;--- Capture some HTML information ------------------------------------------
  2833.     #evaluate ShortNameHtmlLowerCase   "ToLowerCase('<$ShortNameHtml $$SQX2>')"
  2834.  
  2835.  
  2836. ΓòÉΓòÉΓòÉ 4.3. Multi Line Macros ΓòÉΓòÉΓòÉ
  2837.  
  2838. Multi Line Macros 
  2839.  
  2840. The subject of macros is reasonably complex (but well worth learning) please 
  2841. ensure you have at least read the macro introduction before reading this 
  2842. section. 
  2843.  
  2844. Sometimes a macro contains quite a bit of text and to make it easier you might 
  2845. wish to spread the definition over a number of lines. This will also allow you 
  2846. to add comments and spacing to allow it to be easy to read. 
  2847.  
  2848. When PPWIZARD sees a multi line macro (formatted in a similar manner to the 
  2849. example below) it breaks it up into multiple lines so that any imbedded 
  2850. PPWIZARD Commands will get executed. 
  2851.  
  2852.     ;--- Define the macro -------------------------------------
  2853.     #define FeedBackParagraphs                                        \
  2854.             ;---- First paragraph -----------------------------       \
  2855.             <P>I have put a lot of work into this produce and         \
  2856.                believe it to be of a very high standard.  I           \
  2857.                always appreciate feedback which indicates which       \
  2858.                features you use and like and which you don't          \
  2859.                like.                                                  \
  2860.                                                                       \
  2861.             ;---- Second paragraph ----------------------------       \
  2862.             <P>Please <A HREF="mailto:<$MyEmailAddress>">email me</A> \
  2863.                with tour comments.
  2864.  
  2865.     ;--- Use the macro ----------------------------------------
  2866.     <$FeedBackParagraphs>
  2867.  
  2868. Notice that the expanded "<$FeedBackParagraphs>" will refer to our previously 
  2869. defined "MyEmailAddress" macro.  It is perfectly legal for a macro definition 
  2870. to refer to any number of other definitions. 
  2871.  
  2872.  
  2873. ΓòÉΓòÉΓòÉ 4.4. Macros With Mandatory Parameters ΓòÉΓòÉΓòÉ
  2874.  
  2875. Macros With Mandatory Parameters 
  2876.  
  2877. The subject of macros is reasonably complex (but well worth learning) please 
  2878. ensure you have at least read the macro introduction before reading this 
  2879. section. 
  2880.  
  2881. Back to my previously defined email macro, whenever I use it I still have to 
  2882. duplicate a lot of HTML tagging. What we could do is create an email macro 
  2883. which accepts the text or graphic that the user would click to email me, as 
  2884. below: 
  2885.  
  2886.     #define EmailMeLink  <A HREF="mailto:db0@anz.com">{$VISIBLE}</A>
  2887.  
  2888. The above macro accepts a single parameter which must be supplied when the 
  2889. macro is used.  The parameter's name is "VISIBLE".  The macro refers to a 
  2890. parameter by placing '{$' at the start and '}' at the end of the macro 
  2891. parameters name.  To use this macro we could say: 
  2892.  
  2893.     <P>If you have any questions or suggestions for improvements please feel free to
  2894.     <$EmailMeLink VISIBLE="email me">.
  2895.  
  2896. Note that when you supply the value for a macros parameter you can use 
  2897. virtually any character as a quote not just single or double quotes, for 
  2898. example you could say: 
  2899.  
  2900.     <P>If you have any questions or suggestions for improvements please feel free to
  2901.     <$EmailMeLink VISIBLE=@email me@>.
  2902.  
  2903.  
  2904. ΓòÉΓòÉΓòÉ 4.5. Macros With Optional Parameters ΓòÉΓòÉΓòÉ
  2905.  
  2906. Macros With Optional Parameters 
  2907.  
  2908. The subject of macros is reasonably complex (but well worth learning) please 
  2909. ensure you have at least read the macro introduction before reading this 
  2910. section. 
  2911.  
  2912. Also note that you can create a macro which accepts optional parameters.  The 
  2913. "VISIBLE" parameter we have been using up to now is manditory (required), if 
  2914. not supplied the preprocessor will inform you of this fact and stop.  To make a 
  2915. parameter optional you assign at least the first occurance of the parameter a 
  2916. default value.  You can give each occurance a default value (which may be 
  2917. different), and the last specified default value is remembered for subsequent 
  2918. occurances where a default value is required but not specified. For example to 
  2919. change the email macro to use my email address as the default but allow the 
  2920. specification of alternative addresses I could do the following: 
  2921.  
  2922.     #define EmailMeLink  <A HREF="mailto:{$EMAIL='db0@anz.com'}">{$VISIBLE}</A>
  2923.  
  2924. You could then say: 
  2925.  
  2926.     <P>If you have any questions or suggestions for improvements please feel free to
  2927.     <$EmailMeLink VISIBLE=@email me@>, I have another
  2928.     <$EmailMeLink VISIBLE=@email address@ EMAIL=$db1@anz.com$> which
  2929.     you might like to try.
  2930.  
  2931.  
  2932. ΓòÉΓòÉΓòÉ 4.6. Macro Parameters without values ΓòÉΓòÉΓòÉ
  2933.  
  2934. Macro Parameters without values 
  2935.  
  2936. The subject of macros is reasonably complex (but well worth learning) please 
  2937. ensure you have at least read the macro introduction before reading this 
  2938. section. 
  2939.  
  2940. A macro reference would normally specify values for all parameters it uses, 
  2941. however there are times when this is not required. PPWIZARD does not require 
  2942. you to set a value, if you don't supply one then the name of the parameter in 
  2943. upper case is used. 
  2944.  
  2945. The definition of the macro would supply a default value in case the parameter 
  2946. (keyword) was not used and would normally do some conditional generation (using 
  2947. #if etc). 
  2948.  
  2949. The following example shows a simple macro with very little validation that 
  2950. simply assumes if the "keyword" "start" was not supplied that the "end" 
  2951. condition is required: 
  2952.  
  2953.     ;--- Define the macro ---
  2954.     #define StupidMacro                 \
  2955.             #if '{$START=""}' = 'START' \
  2956.                 start stuff             \
  2957.             #elseif                     \
  2958.                 end stuff               \
  2959.             #endif
  2960.  
  2961.     ;--- Use the macro ---
  2962.     <$StupidMacro start>   ;;Start
  2963.        stuff
  2964.     <$StupidMacro>         ;;End
  2965.  
  2966.  
  2967. ΓòÉΓòÉΓòÉ 4.7. Positional Parameters (not named) ΓòÉΓòÉΓòÉ
  2968.  
  2969. Positional Parameters (not named) 
  2970.  
  2971. The subject of macros is reasonably complex (but well worth learning) please 
  2972. ensure you have at least read the macro introduction before reading this 
  2973. section. 
  2974.  
  2975. In some cases (especially with simple one parameter macros) you may simply wish 
  2976. to supply a value without bothering to name it. For example one way to 
  2977. implement a HTML comment might be: 
  2978.  
  2979.        ;--- Define a macro (takes a parameter called "Text") ----
  2980.        #define COMMENT <!-- {$Text} -->
  2981.  
  2982.  
  2983.        ;--- Use the above macro ---
  2984.        <$COMMENT Text="This will become a html comment">
  2985.  
  2986. As you can see from the above we had to use "Text=" even though that is all the 
  2987. parameter could be (at least correctly), lets do this again but this time using 
  2988. a positional parameter: 
  2989.  
  2990.        ;--- Define a macro (takes a single positional parameter) ----
  2991.        #define COMMENT <!-- {$#1} -->
  2992.  
  2993.  
  2994.        ;--- Use the above macro ---
  2995.        <$COMMENT "This will become a html comment">
  2996.  
  2997. Now the rules are that positional comments must start with a double quote (as 
  2998. demonstrated above), a single quote or an equal sign. The macro contents refers 
  2999. to the parameters as a '#' followed by a decimal number which indicates it's 
  3000. position (there can be any number of positional parameters). 
  3001.  
  3002. The reason for the equal sign is that it allows you to quote a string with any 
  3003. quote character (otherwise you wouldn't bother). As an example the above 
  3004. "COMMENT" macro could be called as follows: 
  3005.  
  3006.        ;--- Use the above macro ---
  3007.        <$COMMENT  "Using double quotes">
  3008.        <$COMMENT  'Using single quotes'>
  3009.        <$COMMENT =@Using any    quotes (can then include '" <-- single and double quotes)@>
  3010.  
  3011.  
  3012. ΓòÉΓòÉΓòÉ 4.8. Expand All Unused Parameters ΓòÉΓòÉΓòÉ
  3013.  
  3014. Expand All Unused Parameters 
  3015.  
  3016. The subject of macros is reasonably complex (but well worth learning) please 
  3017. ensure you have at least read the macro introduction before reading this 
  3018. section. 
  3019.  
  3020. This option allows you to create a ppwizard macro for a html tag and process 
  3021. any parameters you wish while expanding any you don't specifically make use of. 
  3022. For example the following is a simplistic "IMG" tag front end: 
  3023.  
  3024.     #define  IMG   <IMG SRC="graphics/{$FILE}" ALT="{$ALT='{$FILE}'}"{$?}>
  3025.  
  3026. Notice the "{$?}" tag above, it will expand all keywords used on a reference 
  3027. except "FILE" and "ALT". If there are specific keywords you don't want included 
  3028. then you should preceed this command with the parameter using '$$IGNORE'. If 
  3029. there were no keywords then nothing is expanded else a space preceeds the 
  3030. resultant keywords. 
  3031.  
  3032. There are actually 2 modes of replacement, the above shows one mode where no 
  3033. "$$" Commands were used, if they were used then the commands are applied to 
  3034. each unused parameter in turn. In general one of the $$ commands would be a 
  3035. "pass" command. 
  3036.  
  3037. Using the $$ commands gives you much more quoting flexability and gives you the 
  3038. option of not passing on the parameters, you may wish to simply memorise them 
  3039. for later use. 
  3040.  
  3041.  
  3042. ΓòÉΓòÉΓòÉ 4.9. Special MACRO Replacement "$$" Commands ΓòÉΓòÉΓòÉ
  3043.  
  3044. Special MACRO Replacement "$$" Commands 
  3045.  
  3046. The subject of macros is reasonably complex (but well worth learning) please 
  3047. ensure you have at least read the macro introduction before reading this 
  3048. section. 
  3049.  
  3050. Macros parameter where they were supplied on a reference without a value that 
  3051. and begin with '$$' have special meaning, they are commands to PPWIZARD. The 
  3052. command applies to the complete contents of a macro before and replacement of 
  3053. parameters has occurred. 
  3054.  
  3055. As well as all '$$' commands shown earlier (except the $$PASS ones) these 
  3056. commands are also available: 
  3057.  
  3058.          $$ASIS 
  3059.           The value of the macro is substituted EXACTLY as it is, there is no 
  3060.           substitution of macro parameters etc. Note that this will not prevent 
  3061.           any macros the contents refers to from being expanded. 
  3062.  
  3063.          $$DSQ 
  3064.           You use this command to surround your parameters data with quotes. 
  3065.           The quotes used are double or single quotes, if neither can be used 
  3066.           ppwizard will terminate.
  3067.  
  3068.          $$SDQ 
  3069.           You use this command to surround your parameters data with quotes. 
  3070.           The quotes used are single or double quotes, if neither can be used 
  3071.           ppwizard will terminate.
  3072.  
  3073.          $$AQ 
  3074.           You use this command to surround your parameters data with quotes. 
  3075.           The quotes used are double or single quotes, if neither can be used 
  3076.           ppwizard will go through a whole list of alternative 'quote' 
  3077.           characters, if none of these can be used then ppwizard will terminate.
  3078.  
  3079.          $$HTMLQ 
  3080.           The parameter is all or part of a string surrounded by double quotes, 
  3081.           any double quotes that exist in the data should be converted to ""e;".
  3082.  
  3083.          $$SQX2 
  3084.           The value is modified such that all single quote characters are 
  3085.           doubled up. This can be very useful if you wish to use the value in a 
  3086.           rexx string which is surrounded by single quotes as rexx will in this 
  3087.           situation treat the two single quotes as a single single quote that 
  3088.           does not terminate the string.
  3089.  
  3090.          $$UPPER 
  3091.           The parameter will be converted to upper case.
  3092.  
  3093.          $$LOWER 
  3094.           The parameter will be converted to lower case.
  3095.  
  3096.          $$ADDCOMMA 
  3097.           The parameter will be formatted using AddCommasToDecimalNumber().
  3098.  
  3099.          $$? 
  3100.           If the '$$' command is otherwise unknown you can create your own 
  3101.           formatting (ie you can not redefine an existing format). 
  3102.  
  3103.           To define a format you need to define a macro which contains the rexx 
  3104.           formatting code. The macro must have the name of "REXX_$$" followed 
  3105.           by the name of your command, for example to use the command 
  3106.           "$$TO_C_STRING" you would create "REXX_$$TO_C_STRING". The value to 
  3107.           be formatted is in the "TheValue" variable. 
  3108.  
  3109.           If required you can also determine the source of the value (macro or 
  3110.           parameter name) as it is stored in "TheName" (for case insensitive 
  3111.           items it is in upper case). For macro parameters only the name of the 
  3112.           macro being expanded is in the "TheMacro" variable. 
  3113.  
  3114.  A simple example where if the "$$SQX2" command were not used that ppwizard 
  3115.  would fail (in this case with variable "A" unknown trap): 
  3116.  
  3117.       #define TheMacro   The value 'A' is in quotes
  3118.       #evaluate "" "call Summary 'VALUE', '<$TheMacro $$SQx2>'"
  3119.  
  3120.  Another example where we wish to add commas to a rexx variable: 
  3121.  
  3122.       Value = <??ARexxVariable $$ADDCOMMA>
  3123.  
  3124.  Here is another example which may be useful if you were creating 'C' code and 
  3125.  maybe other situations: 
  3126.  
  3127.       ;--- Define directory (non 'C' format as used elsewhere) ---
  3128.       #define DIR_NAME     C:\DB\PROJECTS\FRED
  3129.  
  3130.       ;--- Define a macro to transform a string into 'C' format ---
  3131.       #DefineRexx REXX_$$TO_C_STRING
  3132.                   TheValue = ReplaceString(TheValue, '\',     '\\');
  3133.                   TheValue = ReplaceString(TheValue, '"',     '\"');
  3134.                   TheValue = ReplaceString(TheValue, d2c(10), '\n');
  3135.                   TheValue = ReplaceString(TheValue, d2c(13), '\r');
  3136.                   TheValue = ReplaceString(TheValue, d2c(7),  '\b');
  3137.       #DefineRexx
  3138.  
  3139.       ;--- Use our defined transformation ---
  3140.       StringC = "<$DIR_NAME $$TO_C_STRING>";
  3141.  
  3142.  
  3143. ΓòÉΓòÉΓòÉ 4.10. Special MACRO PARAMETER Replacement "$$" Commands ΓòÉΓòÉΓòÉ
  3144.  
  3145. Special MACRO PARAMETER Replacement "$$" Commands 
  3146.  
  3147. The subject of macros is reasonably complex (but well worth learning) please 
  3148. ensure you have at least read the macro introduction before reading this 
  3149. section. 
  3150.  
  3151. Within a macro's data, when referring to a parameter you can specify certain 
  3152. special commands (all begin with '$$'). These commands (there can be more than 
  3153. one) occur immediately preceeding the '}' character, available commands are: 
  3154.  
  3155.          $$PASSDSQ 
  3156.           The parameter will be quoted as per the $$DSQ command and the 
  3157.           parameter name followed by the equal sign will be added to the start. 
  3158.           This is handy when one macro uses another and a parameter needs to be 
  3159.           passed to the inner macro (parameter has same name in both macros).
  3160.  
  3161.          $$PASSAQ 
  3162.           The parameter will be quoted as per the $$AQ command and the 
  3163.           parameter name followed by the equal sign will be added to the start. 
  3164.           This is handy when one macro uses another and a parameter needs to be 
  3165.           passed to the inner macro (parameter has same name in both macros).
  3166.  
  3167.          $$IGNORE 
  3168.           The parameter will be "dropped" (a empty string will be substituted). 
  3169.           The main reason you might want to do this is to prevent a '"{$?}"' 
  3170.           type parameter from including this parameter. 
  3171.  
  3172.          $$DSQ 
  3173.           You use this command to surround your parameters data with quotes. 
  3174.           The quotes used are double or single quotes, if neither can be used 
  3175.           ppwizard will terminate.
  3176.  
  3177.          $$SDQ 
  3178.           You use this command to surround your parameters data with quotes. 
  3179.           The quotes used are single or double quotes, if neither can be used 
  3180.           ppwizard will terminate.
  3181.  
  3182.          $$AQ 
  3183.           You use this command to surround your parameters data with quotes. 
  3184.           The quotes used are double or single quotes, if neither can be used 
  3185.           ppwizard will go through a whole list of alternative 'quote' 
  3186.           characters, if none of these can be used then ppwizard will terminate.
  3187.  
  3188.          $$HTMLQ 
  3189.           The parameter is all or part of a string surrounded by double quotes, 
  3190.           any double quotes that exist in the data should be converted to ""e;".
  3191.  
  3192.          $$SQX2 
  3193.           The value is modified such that all single quote characters are 
  3194.           doubled up. This can be very useful if you wish to use the value in a 
  3195.           rexx string which is surrounded by single quotes as rexx will in this 
  3196.           situation treat the two single quotes as a single single quote that 
  3197.           does not terminate the string.
  3198.  
  3199.          $$UPPER 
  3200.           The parameter will be converted to upper case.
  3201.  
  3202.          $$LOWER 
  3203.           The parameter will be converted to lower case.
  3204.  
  3205.          $$ADDCOMMA 
  3206.           The parameter will be formatted using AddCommasToDecimalNumber().
  3207.  
  3208.          $$? 
  3209.           If the '$$' command is otherwise unknown you can create your own 
  3210.           formatting (ie you can not redefine an existing format). 
  3211.  
  3212.           To define a format you need to define a macro which contains the rexx 
  3213.           formatting code. The macro must have the name of "REXX_$$" followed 
  3214.           by the name of your command, for example to use the command 
  3215.           "$$TO_C_STRING" you would create "REXX_$$TO_C_STRING". The value to 
  3216.           be formatted is in the "TheValue" variable. 
  3217.  
  3218.           If required you can also determine the source of the value (macro or 
  3219.           parameter name) as it is stored in "TheName" (for case insensitive 
  3220.           items it is in upper case). For macro parameters only the name of the 
  3221.           macro being expanded is in the "TheMacro" variable. 
  3222.  
  3223.  Note that the quoting routines above do more than just make your code 
  3224.  "prettier", without using these commands you have to decide on a quote 
  3225.  character yourself and then a parameters value must never contain this 
  3226.  character. These special commands won't solve all quoting issues (remember 
  3227.  parameter processed left to right - imbedded parameters are not processed 
  3228.  first) however they will make life much easier. 
  3229.  
  3230.  Lets make sure that parameters 2 and 3 in the following macro get translated 
  3231.  to upper case: 
  3232.  
  3233.       ;--- Define macro ---------
  3234.       #define  SimpleTest P1={$parm1}, P2={$parm2="parm1_default" $$upper}, P3={$parm3 $$upper $$DSQ}
  3235.  
  3236.       ;--- Expand macro ---------
  3237.       <$SimpleTest Parm1='value1' Parm2='value2' Parm3='value3'>
  3238.  
  3239.  
  3240. ΓòÉΓòÉΓòÉ 4.11. Multi Line Macros With Logic ΓòÉΓòÉΓòÉ
  3241.  
  3242. Multi Line Macros With Logic 
  3243.  
  3244. The subject of macros is reasonably complex (but well worth learning) please 
  3245. ensure you have at least read the macro introduction before reading this 
  3246. section. 
  3247.  
  3248. In this example we add some conditional inclusion where the same macro can 
  3249. generate different text based on the environment or parameters that are passed 
  3250. to it.  In the following macro the size of the image file is calculated unless 
  3251. a value was passed to it. 
  3252.  
  3253. You might create a macros as follows to display some photos in a table: 
  3254.  
  3255.    ;--- Photo macro will either use passed size or work out correct size for you ---
  3256.    #define Photo                                                               \
  3257.            #evaluate+  LocalFileName    ^"..\graphics\{$Image}"^               \
  3258.            #DependsOn  INPUT            "<$LocalFileName>"                     \
  3259.            <TR>                                                                \
  3260.            #if "{$Size=''}" <> ""                                              \
  3261.                #define+   TmpSize {$Size=''}     ;;User supplied size          \
  3262.            #elseif                                                             \
  3263.                #evaluate+ TmpSize ^GetImageHeightWidth("<$LocalFileName>")^    \
  3264.            #endif                                                              \
  3265.            <TD ALIGN=CENTER>                                                   \
  3266.            <IMG SRC="graphics/clear1x1.gif" WIDTH=1 HEIGHT=1 VSPACE=20>        \
  3267.            {$Title}<BR><BR>                                                    \
  3268.            <IMG SRC="graphics/{$Image}" BORDER=0 <$TmpSize> ALT="{$Title}">    \
  3269.            <IMG SRC="graphics/clear1x1.gif" WIDTH=1 HEIGHT=1 VSPACE=20>        \
  3270.            </TR>
  3271.  
  3272. It is then a simple matter to create format and add new photos as follows (note 
  3273. that the image size is automatically calculated): 
  3274.  
  3275.     ;--- Create table of photos --------------------------------------------
  3276.     <BR><CENTER><TABLE COLS=1 BORDER=10 CELLSPACING=10>
  3277.        <TR>
  3278.        <TH ALIGN=CENTER>Pictures
  3279.        </TR>
  3280.  
  3281.        ;--- Include all my photos ------------------------------------------
  3282.        <$Photo Image="lazy.jpg"     Title="Watching TV">
  3283.        <$Photo Image="carback.jpg"  Title="New Car (Back Left)">
  3284.     </TABLE></CENTER>
  3285.  
  3286.  
  3287. ΓòÉΓòÉΓòÉ 5. Rexx ΓòÉΓòÉΓòÉ
  3288.  
  3289. Rexx 
  3290.  
  3291. REXX is a very powerful interpreted programming language. While you don't need 
  3292. to know much about rexx to use PPWIZARD you will find that you can do so much 
  3293. more if you do. There is a lot of 3rd party support for rexx, not only for OS/2 
  3294. but for windows as well. 
  3295.  
  3296. This program is written in rexx and has specific commands that allow you to 
  3297. embed rexx code. The following situations allow you to execute rexx code (some 
  3298. other minor situations as well): 
  3299.  
  3300.        1. #if commands. 
  3301.        2. #evaluate commands. 
  3302.        3. #import filters. 
  3303.        4. <?=RexxExpression> "standard definition". 
  3304.        5. In the CompareReplaceFixed() routine. 
  3305.  
  3306.  For OS/2 users an online rexx manual was installed for you (by OS/2 install 
  3307.  process).  Otherwise you can get a copy of the regina documentation from 
  3308.  http://www.lightlink.com/hessling/ 
  3309.  
  3310.  There is a DebugLevel option of REXXTRACE that you can turn on or off to 
  3311.  control level of debugging output from the rexx commands you execute. 
  3312.  Regina's debugging is not as good as OS/2's native debugging but its still a 
  3313.  help. 
  3314.  
  3315.  The following information provides a very small summary of rexx, for people 
  3316.  unfamiliar with programming this may not be enough and you may need to look 
  3317.  elsewhere. A good place to ask questions or just sit back and watch is the 
  3318.  news group "comp.lang.rexx". 
  3319.  
  3320.  Some Examples of Rexx Code Integration 
  3321.  
  3322.  Some simple one liners: 
  3323.  
  3324.       ;--- Capture some HTML information ---
  3325.       #evaluate ShortNameHtml            "_filespec('name', '<?OutputFile>')"
  3326.       #evaluate ShortNameHtmlLowerCase   "ToLowerCase('<$ShortNameHtml>')"
  3327.  
  3328.       ;--- Capture date/time information ---
  3329.       #evaluate DateTime @date('WeekDay') || ' ' || date('Month') || ' ' || substr(date('Sorted'), 7, 2) || ' ' || left(date('Sorted'), 4) || ' at ' || time('Civil')@
  3330.  
  3331.  More complex example where multi statement rexx is formatted in a very 
  3332.  readable manner (using #DefineRexx): 
  3333.  
  3334.       #DefineRexx IMPORT_RECORD_FILTER
  3335.                   if Column.1 = "Wendy" then
  3336.                      Remove='This is "Wendy" record'    ;;Don't want this record
  3337.                   else
  3338.                      Column.1 = translate(Column.1)     ;;Make column #1 upper case
  3339.       #DefineRexx
  3340.       #import ImportMe.CMA CMA "" "First<BR>Name" "Surname" "Job"
  3341.  
  3342.  
  3343. ΓòÉΓòÉΓòÉ 5.1. Rexx Resources - Tools & Links ΓòÉΓòÉΓòÉ
  3344.  
  3345. Rexx Resources - Tools & Links 
  3346.  
  3347.        1. REXXIO 
  3348.           A free rexx extension for Windows and OS/2. Contains File Functions, 
  3349.           Directory Functions, Search Functions, Window Functions, 
  3350.           Keyboard/Mouse Event Functions, Rexx Functions, Registry Functions, 
  3351.           Global Stem Variable Functions, General Functions, Comms Functions 
  3352.           Event Functions. http://www.lestec.com.au/freelibrary.htm. 
  3353.  
  3354.        2. REGUTIL 
  3355.           A free rexx extension for unix and windows. It provides access to 
  3356.           windows registry as well as some other powerful file and directory 
  3357.           features. It was created by Patrick McPhee and is available from 
  3358.           http://www.interlog.com/~ptjm/. 
  3359.  
  3360.        3. RexxSQL - SQL ACCESS 
  3361.           Another free product for a large range of operating systems. Support 
  3362.           covers a very large number of different databases. It is available 
  3363.           from http://www.lightlink.com/hessling/. 
  3364.  
  3365.        4. Rexx Tips and Tricks 
  3366.           Absolutely a must read for anyone using rexx under OS/2, only 
  3367.           available as an OS/2 INF file. Note that a lot of the information is 
  3368.           also applicable to other operating systems. You can get it from 
  3369.           http://www.cfsrexx.com/pub/welcome.htm#rxtt. 
  3370.  
  3371.        5. Rexx Language Organisation 
  3372.           Links to rexx sites and other interested info, available at 
  3373.           http://www.rexxla.org/ 
  3374.  
  3375.        6. TCP-IP (RxSock) Tutorial 
  3376.           A good short tutorial on using sockets (URL checking etc) is 
  3377.           available at http://www2.hursley.ibm.com/rexxtut/socktut1.htm 
  3378.  
  3379.        7. RxSock For Windows 
  3380.           Get a windows version of the RxSock.DLL from 
  3381.           http://home.hiwaay.net/~abbott/regina/ 
  3382.  
  3383.  
  3384. ΓòÉΓòÉΓòÉ 5.2. Rexx Variables ΓòÉΓòÉΓòÉ
  3385.  
  3386. Rexx Variables 
  3387.  
  3388. Rexx unlike many other programming languages does not require its variables to 
  3389. be predefined and there is only one type (string). A number is just a string of 
  3390. characters. 
  3391.  
  3392. Variable names can be any reasonable length and can contain the letters 'A' to 
  3393. 'Z', the digits '0' to '9' or any of "!?_" (digits can't start a variable 
  3394. name). 
  3395.  
  3396. In PPWIZARD you must not try to use the value of a variable which does not 
  3397. exist or it will trap with a "NOVALUE" abort and output diagnostic information 
  3398. which should spell out your problem. 
  3399.  
  3400. I very much recommend that you don't use simple rexx variable names such as 
  3401. "Count".  This is dangerous as it may clash with PPWIZARD variables. If this 
  3402. occurs it will probably be very difficult to diagnose and PPWIZARD (and your 
  3403. code) will probably malfunction in unpredictable ways. 
  3404.  
  3405. No PPWIZARD variables start with '_' and for this reason I recommend that you 
  3406. preceed all variable names with this character. For example instead of 'Count' 
  3407. use '_Count'. 
  3408.  
  3409. All rexx variables you define are global, as are those used by PPWIZARD.  This 
  3410. gives a lot of its power but it can also be dangerous. Always try to be aware 
  3411. of this fact. 
  3412.  
  3413. You also need to be aware that PPWIZARD may modify the rexx RC or RESULT 
  3414. variables that you believe has been set by an #evaluate command.  Do not rely 
  3415. on these variables, set your own (of course within a single #evaluate PPWIZARD 
  3416. will not touch these variables). 
  3417.  
  3418. Some examples of giving rexx variables a value: 
  3419.  
  3420.        #evaluate ^^   ^_Count   = 1^             ;;Both this and next line set value to the number 1
  3421.        #evaluate ^^   ^_Count   = '1'^
  3422.        #evaluate ^^   ^_Count   = _Count + 1^    ;;Increase value by 1
  3423.        #evaluate ^^   ^_Array.1 = 'a value'^
  3424.        #evaluate ^^   ^_Fred    = "a value"^
  3425.  
  3426.  
  3427. ΓòÉΓòÉΓòÉ 5.3. Rexx Expressions ΓòÉΓòÉΓòÉ
  3428.  
  3429. Rexx Expressions 
  3430.  
  3431. The following operators can be used: 
  3432.  
  3433.          + 
  3434.           Adds values. 
  3435.  
  3436.          - 
  3437.           Subtracts values. 
  3438.  
  3439.          * 
  3440.           Multiplies values. 
  3441.  
  3442.          / 
  3443.           Divides values (5/2 => 2.5). 
  3444.  
  3445.          % 
  3446.           Divides values, want whole number (5/2 => 2). 
  3447.  
  3448.          // 
  3449.           Divides values, want remainder (5//2 => 1). 
  3450.  
  3451.  Expressions can also make use of PPWIZARD or standard rexx functions. 
  3452.  
  3453.  Some examples of expressions being used: 
  3454.  
  3455.          #evaluate ^^   ^ResultOfExpression = (10 + 8) / 2^        ;;Value 9
  3456.          #evaluate ^^   ^ResultOfExpression = (_Count - 1) % $Div^
  3457.          #evaluate ^^   ^Path               = GetEnv('PATH')^
  3458.  
  3459.  
  3460. ΓòÉΓòÉΓòÉ 5.4. Rexx Conditional Logic ΓòÉΓòÉΓòÉ
  3461.  
  3462. Rexx Conditional Logic 
  3463.  
  3464. The #if command allows you to evaluate any rexx conditional expression to 
  3465. determine whether its true or not. 
  3466.  
  3467. The following tests operators are concidered to be "non-strict" (leading and 
  3468. trailing blanks are ignored as are leading zeros on numbers): 
  3469.  
  3470.          = 
  3471.           Tests if values are equal. 
  3472.  
  3473.          <> 
  3474.           Tests if values are not equal. 
  3475.  
  3476.          < 
  3477.           Tests if left value is less than the right value (can be text or 
  3478.           number). 
  3479.  
  3480.          <= 
  3481.           Tests if left value is less than or equal to the right value (can be 
  3482.           text or number). 
  3483.  
  3484.          > 
  3485.           Tests if left value is greater than the right value (can be text or 
  3486.           number). 
  3487.  
  3488.          >= 
  3489.           Tests if left value is greater than or equal to the right value (can 
  3490.           be text or number). 
  3491.  
  3492.  The following tests operators are concidered to be "strict": 
  3493.  
  3494.          == 
  3495.           Tests if values are equal. 
  3496.  
  3497.          \== 
  3498.           Tests if values are not equal. 
  3499.  
  3500.          << 
  3501.           Tests if left value is less than the right value (can be text or 
  3502.           number). 
  3503.  
  3504.          <<= 
  3505.           Tests if left value is less than or equal to the right value (can be 
  3506.           text or number). 
  3507.  
  3508.          >> 
  3509.           Tests if left value is greater than the right value (can be text or 
  3510.           number). 
  3511.  
  3512.          >>= 
  3513.           Tests if left value is greater than or equal to the right value (can 
  3514.           be text or number). 
  3515.  
  3516.  The following logical operators are also useful: 
  3517.  
  3518.          & - AND (both must be true) 
  3519.  
  3520.          | - OR (either can be true) 
  3521.  
  3522.  Some examples follow: 
  3523.  
  3524.       #if  lines(<$LanguageFile>) = 0
  3525.       #if  Defined('Var1') = 'Y' | Defined('Var2') = 'Y'
  3526.       #if <$TmpHH> < 12
  3527.       #if translate(GetEnv("PRJSRCDIR")) = "E:\DB\PROJECTS\HOMEPAGE"
  3528.  
  3529.  
  3530. ΓòÉΓòÉΓòÉ 5.5. Rexx Looping ΓòÉΓòÉΓòÉ
  3531.  
  3532. Rexx Looping 
  3533.  
  3534. Loops are one of the complex areas of rexx and most things you will wish to do 
  3535. with PPWIZARD will either not require them or the simpler PPWIZARD loops will 
  3536. be enough. 
  3537.  
  3538. The syntax of rexx loops is as follows: 
  3539.  
  3540.     DO [ symbol=start   [TO  finish]  ]     [WHILE expression_w]
  3541.        [                [BY  step  ]  ]
  3542.        [                [FOR count ]  ]     [UNTIL expression_u]
  3543.  
  3544.        [ expression_c                 ]     [FOREVER           ]
  3545.  
  3546. Examples follow (these would need to be integrated with PPWIZARD using the 
  3547. #evaluate command : 
  3548.  
  3549.     do 10
  3550.        /* Do something 10 times */
  3551.     end
  3552.  
  3553.     do _Count = 1 to 100
  3554.        /* Do something 100 times (Count given values 1,2,3 to 100) */
  3555.     end
  3556.  
  3557.     do _Multiple = 0 to 20 by 2.3
  3558.        /* Loop with _Multiple = all multiples of 2.3 not more than 20 */
  3559.     end
  3560.  
  3561.     do _Multiple = 0 for 6 by 5.7
  3562.        /* Loop with _Multiple = the first six multiples of 5.7 */
  3563.     end
  3564.  
  3565.     _Finished = 'N'
  3566.     do while _Finished = 'N'
  3567.        /* Set _Finished variable to 'Y' to exit loop */
  3568.     end;
  3569.  
  3570.     do until _Finished = 'Y' & _Fred <> 0
  3571.        /* Set _Finished variable to 'Y' to exit loop (_Fred must also be non zero) */
  3572.     end;
  3573.  
  3574.     do 3 until _Answer = "YES"
  3575.        /* Exits loop after 3 times or if _Answer becomes 'YES' */
  3576.     end
  3577.  
  3578.     do _Count = 1 to 10 until Fred == ""
  3579.        /* Loop 1 to 10 unless condition met */
  3580.     end
  3581.  
  3582.     do _Count = 1 to 10
  3583.        /* Looping 1 to 10 */
  3584.  
  3585.        /* Want to restart loop (don't execute following loop code)? */
  3586.        if _Restart = 'Y' then
  3587.           iterate;         /* Go back to start of loop (_Count incremented) */
  3588.  
  3589.        /* Want to exit loop early? */
  3590.        if _Flag = 'Y' | _State = 'R' then
  3591.           break;           /* Exit loop */
  3592.     end
  3593.  
  3594.  
  3595. ΓòÉΓòÉΓòÉ 5.6. Rexx Parsing ΓòÉΓòÉΓòÉ
  3596.  
  3597. Rexx Parsing 
  3598.  
  3599. Parsing is another of rexx's complex areas, a subset of its syntax is 
  3600. summarised here: 
  3601.  
  3602.     PARSE [UPPER] LINEIN [template]
  3603.     PARSE [UPPER] NUMERIC template
  3604.     PARSE [UPPER] VAR symbol template
  3605.     PARSE [UPPER] VALUE expression WITH template
  3606.  
  3607.         template        -> [firstPosition] assignments [assignments]
  3608.         assignments     -> [nextPosition] varlist [stopPosition]
  3609.         varlist         -> varname ' ' [varlist]
  3610.         varname         ->   "non-constant symbol"
  3611.                            | '.'
  3612.         firstPosition   -> position
  3613.         nextPosition    -> position [nextPosition]
  3614.         stopPosition    -> position
  3615.         position        ->   searchPosition
  3616.                            | absPosition
  3617.                            | relPosition
  3618.                            | '(' "expression" ')'
  3619.         searchPosition  -> "string constant"
  3620.         absPosition     ->   "integer"
  3621.                            | '=' numexpr
  3622.         relPosition     ->   '+' numexpr
  3623.                            | '-' numexpr
  3624.         numexpr         ->   "integer"
  3625.                            | '(' "integer expression" ')'
  3626.  
  3627. This is an example of extracting each directory (one at a time) from the path 
  3628. (located in DOS or OS/2 environment): 
  3629.  
  3630.     ;--- Get "PATH" from environment
  3631.     #evaluate ^^  ^_Path = GetEnv('PATH')^
  3632.  
  3633.     ;--- Start list -----------------
  3634.     <P>The path is:
  3635.     <OL>
  3636.  
  3637.     ;--- List Components ------------
  3638.     #{
  3639.        ;--- Get next directory name -
  3640.        #evaluate ^^ ^parse var _Path _ThisBit ';' _Path^
  3641.  
  3642.        ;--- Exit if at end of path --
  3643.        #if  _ThisBit = '' & _Path=''
  3644.             #break
  3645.        #endif
  3646.  
  3647.        ;--- Output directory name ---
  3648.        <LI><??_ThisBit>
  3649.     #}
  3650.  
  3651.     ;--- End list -------------------
  3652.     </OL>
  3653.  
  3654.  
  3655. ΓòÉΓòÉΓòÉ 5.7. Standard Rexx Routines ΓòÉΓòÉΓòÉ
  3656.  
  3657. SUMMARY OF REXX "BUILT IN" ROUTINES 
  3658.  
  3659. Note that some of the routines listed below may not be available in the rexx 
  3660. version you are using (neither does it list all functions): 
  3661.  
  3662.     ABBREV(information,info[,length])  - check for valid abbreviations
  3663.     ABS(number)                        - return the absolute value
  3664.     B2D(binary)
  3665.     B2X(binary)
  3666.     D2B(decimal)
  3667.     C2X(string)
  3668.     C2D(string[,n])
  3669.     D2C(decimal[,n])                   - convert between data formats
  3670.     D2X(decimal[,n])
  3671.     X2B(hex)
  3672.     X2C(hex)
  3673.     X2D(hex)
  3674.     CENTER(s,n[,pad])                  - centre a string in a field
  3675.     CENTRE(s,n[,pad])
  3676.     COMPARE(s1,s2[,pad])               - compare two strings
  3677.  
  3678.     COPIES(s,n)                        - replicate a string
  3679.     DATATYPE(string[,type])            - test datatype. Type can be:
  3680.                                        A (alphanumeric) B (bits) L (lowercase)
  3681.                                        M (mixed case) N (number) S (symbol chars)
  3682.                                        U (upper case) W (whole number) X (hex)
  3683.  
  3684.     DATE([format])                     - get date. Format can be:
  3685.                                        B (base date - days since 1/1/1 AD)
  3686.                                        C (days in century) D (days in year)
  3687.                                        E (European) J (Julian) M (month name)
  3688.                                        N (normal: dd Mon yyyy) O (ordered)
  3689.                                        S (sorted) U (USA) W (day of week)
  3690.  
  3691.  
  3692.     FORMAT(number [,[before] [,[after] [,[expp] [,expt]]]] )
  3693.                                        - format a number as specified
  3694.     FUZZ()                             - NUMERIC FUZZ setting
  3695.     INSERT(new,target[,[n][,[length][,pad]]])  - insert new string into target
  3696.     JUSTIFY(s,n[,pad])                 - justify text to given width
  3697.     LASTPOS(needle,haystack[,start])   - find last occurrence of a string
  3698.     LEFT(string,num[,pad])             - return an initial substring
  3699.     LENGTH(string)                     - find the length of a string
  3700.     MAX(number[,number...])            - find the maximum of a set
  3701.     MIN(number[,number...])            - find the minimum of a set
  3702.     OVERLAY(new,target[,[n][,[length][,pad]]])  - overlay new string on to target
  3703.     POS(needle,haystack[,start])       - find the first occurance of a string
  3704.     RANDOM([min][,[max][,seed]])       - return a random number
  3705.     REVERSE(string)                    - find the reverse of a string
  3706.     RIGHT(string,num[,pad])            - return a final substring
  3707.     SPACE(s[,[n][,pad]])               - evenly space words in a sentence
  3708.     STRIP(string[,[opt][,char]])       - remove leading/trailing spaces
  3709.     SUBSTR(string,n[,length[,pad]])    - return a substring
  3710.     SUBWORD(string,n[,k])              - return a substring of words
  3711.     SYMBOL(name)                       - test to see if a symbol is defined
  3712.     TIME([format])                     - get the time. Format can be:
  3713.                                        C (civil time) N (normal) L (long)
  3714.                                        H (hours since midnight)
  3715.                                        M (minutes since midnight)
  3716.                                        S (seconds since midnight) E (elapsed time)
  3717.                                        R (elapsed time then reset)
  3718.  
  3719.     TRANSLATE(string[,[tableo][,[tablei][,pad]]])
  3720.                                        - translate characters using given tables
  3721.     TRUNC(number[,n])                  - truncate floating point number
  3722.     VALUE(s[,[newvalue][,selector]])   - get or set value of a symbol
  3723.  
  3724.     VERIFY(string,reference[,[option][,start]])
  3725.                                        - verify string for valid characters
  3726.     WORD(string,n)                     - return a word from a string
  3727.     WORDINDEX(string,n)                - return the position of a word in a string
  3728.     WORDLENGTH(string,n)               - return the length of a word in a string
  3729.     WORDPOS(phrase,string[,start])     - find a phrase in a string
  3730.     WORDS(string)                      - return the number of words in a string
  3731.     XRANGE([a[,b]])                    - return a range of characters
  3732.  
  3733. Some rexx interpreters support functions which are not ANSI standard, others 
  3734. won't support all standard ANSI routines.  If you care about operating system 
  3735. portability you will be careful about which routines you use. PPWIZARD has its 
  3736. own routines which may be be used, these should be used in preference to 
  3737. "standard" rexx ones as they will work in all operating systems that PPWIZARD 
  3738. supports. 
  3739.  
  3740.  
  3741. ΓòÉΓòÉΓòÉ 5.8. Rexx Fragments - Kick Start ΓòÉΓòÉΓòÉ
  3742.  
  3743. Rexx Fragments - Kick Start 
  3744.  
  3745. This section will show you some small portions of rexx code (not complete) 
  3746. which can be used to quickly get you up to speed in rexx. 
  3747.  
  3748. Note that the examples below are isolated fragments, you could not cut and 
  3749. paste them and run them though PPWIZARD as they are... 
  3750.  
  3751.            ;--- Assign a value to a variable ---
  3752.            SomeVariable = 'the cat sat on the mat';
  3753.  
  3754.            ;--- Convert string to upper case ---
  3755.            UpperCaseString = translate(SomeVariable);
  3756.  
  3757.            ;--- Get first 2 characters of string ---
  3758.            Left2 = left('abcd', 2);
  3759.  
  3760.            ;--- Get last 2 characters of string ---
  3761.            Right2 = right('abcd', 2);
  3762.  
  3763.            ;--- Get middle 2 characters of string (first char at posn 1) ---
  3764.            Middle2 = substr('abcd', 2, 2);      ;;Last '2' is length
  3765.  
  3766.            ;--- See if first char of string is 'A' (either case) ---
  3767.            if  translate(left(UpperCaseString, 1)) = 'A' then
  3768.            do;
  3769.                ;--- Any number of rexx statements ---
  3770.            end;
  3771.  
  3772.            ;--- Does "SomeVariable" contain the characters "Fred"? ---
  3773.            if  pos('Fred', SomeVariable) <> 0 then     ;Does var
  3774.                SingleStatement;
  3775.            else
  3776.            do
  3777.                ;--- Any number of rexx statements ---
  3778.            end;
  3779.  
  3780.            ;--- Is the second word of "SomeVariable" the word "the"? ---
  3781.            if  word(SomeVariable, 2) = 'the' then
  3782.                SingleStatement;
  3783.  
  3784.  
  3785. ΓòÉΓòÉΓòÉ 5.9. Rexx Extensions ΓòÉΓòÉΓòÉ
  3786.  
  3787. Rexx Extensions 
  3788.  
  3789. Any of these PPWIZARD routines may be used by your rexx code: 
  3790.  
  3791.          AddCommasToDecimalNumber() 
  3792.          AddInputFileToDependancyList() 
  3793.          AddOutputFileToDependancyList() 
  3794.          AddressCmd() 
  3795.          AsIs() 
  3796.          AsIsPrepare() 
  3797.          AutoTag() 
  3798.          BaseDate() 
  3799.          BreakAt() 
  3800.          BulkChar2String() 
  3801.          BulkChangePrepare() 
  3802.          CompareReplaceFixed() 
  3803.          DataGet() 
  3804.          DataSave() 
  3805.          Debug() 
  3806.          DebugIndent() 
  3807.          Defined() 
  3808.          DieIfIoErrorOccurred() 
  3809.          EnsureFileHasCorrectCase() 
  3810.          Error() 
  3811.          ExpandXCodes() 
  3812.          GenerateFileName() 
  3813.          GetAmPmTime() 
  3814.          GetEnv() 
  3815.          GetFileLineBeingProcessed() 
  3816.          GetFileTimeStamp() 
  3817.          GetId() 
  3818.          GetIdPrepare() 
  3819.          GetImageHeightWidth() 
  3820.          GetInputFileNameAndLine() 
  3821.          GetLineBeingProcessed() 
  3822.          Info() 
  3823.          InputComponentLevel() 
  3824.          InputComponentLineLevel() 
  3825.          IsDebugOn() 
  3826.          MacroGet() 
  3827.          MacroSet() 
  3828.          PadString() 
  3829.          ProcessNext() 
  3830.          QuoteIt() 
  3831.          ReplaceMacros() 
  3832.          ReplaceString() 
  3833.          ReplaceStringCI() 
  3834.          ReverseArray() 
  3835.          SetEnv() 
  3836.          SetId() 
  3837.          SortArray() 
  3838.          Summary() 
  3839.          ToLowerCase() 
  3840.          UrlDecode() 
  3841.          UrlEncode() 
  3842.          Warning() 
  3843.          WriteLineToTmpImportFile() 
  3844.          RexGetTmpFileName() 
  3845.          _filespec() 
  3846.          _SysFileDelete() 
  3847.          _SysFileTree() 
  3848.          _SysSearchPath() 
  3849.  
  3850.  
  3851. ΓòÉΓòÉΓòÉ 5.9.1. AddCommasToDecimalNumber() ΓòÉΓòÉΓòÉ
  3852.  
  3853. AddCommasToDecimalNumber() 
  3854.  
  3855. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  3856. extensions) can be used with any operating system supported by PPWIZARD. 
  3857.  
  3858. This function takes a single parameter (a decimal integer) and adds commas as 
  3859. required. 
  3860.  
  3861.  
  3862. ΓòÉΓòÉΓòÉ 5.9.2. AddInputFileToDependancyList() ΓòÉΓòÉΓòÉ
  3863.  
  3864. AddInputFileToDependancyList() 
  3865.  
  3866. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  3867. extensions) can be used with any operating system supported by PPWIZARD. 
  3868.  
  3869. This function allows you to specify an input dependancy. The function should be 
  3870. called before the file is read for the most accurate result in all 
  3871. circumstances. 
  3872.  
  3873. This routine is an alternative to the "#DependsOn" command. 
  3874.  
  3875.  
  3876. ΓòÉΓòÉΓòÉ 5.9.3. AddOutputFileToDependancyList() ΓòÉΓòÉΓòÉ
  3877.  
  3878. AddOutputFileToDependancyList() 
  3879.  
  3880. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  3881. extensions) can be used with any operating system supported by PPWIZARD. 
  3882.  
  3883. This function allows you to specify an output dependancy. The function should 
  3884. be called after you have completed all updating of the file. 
  3885.  
  3886. This routine is an alternative to the "#DependsOn" command. 
  3887.  
  3888.  
  3889. ΓòÉΓòÉΓòÉ 5.9.4. AddressCmd() ΓòÉΓòÉΓòÉ
  3890.  
  3891. AddressCmd() 
  3892.  
  3893. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  3894. extensions) can be used with any operating system supported by PPWIZARD. 
  3895.  
  3896. This routine will pass the command that you specify to the operating system's 
  3897. command processor. The command will by default by logged when debug is on. 
  3898. This is a major reason why you should use this call. 
  3899.  
  3900. If your command produces some files as output or you create some by redirection 
  3901. you can specify the names of the files as parameter 2 onwards and these will be 
  3902. dumped when debug is on 
  3903.  
  3904. Under OS/2 if the command to be executed is a rexx batch file you should 
  3905. preceed the command with "CMD.EXE /c" or the command will fail. If you don't 
  3906. know what the command is you should preceed all commands with that string to 
  3907. play safe. 
  3908.  
  3909. Stupid Example 
  3910.  
  3911. This example shows a directory commands output going into one file and any 
  3912. error messages into another.  If debug is on the contents of both files as well 
  3913. as the return code will be dumped. 
  3914.  
  3915.     #evaluate "" ^call AddressCmd "dir /od >dirlist.out 2>error.out", "dirlist.out", "error.out"^
  3916.  
  3917.  
  3918. ΓòÉΓòÉΓòÉ 5.9.5. AsIs() ΓòÉΓòÉΓòÉ
  3919.  
  3920. AsIs() 
  3921.  
  3922. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  3923. extensions) can be used with any operating system supported by PPWIZARD. 
  3924.  
  3925. This function takes a single parameter and will return the string after all "as 
  3926. is" conversion has taken place (see the #AsIs command). 
  3927.  
  3928. Note that this replacement occurs whether or not "as is" mode is currently on, 
  3929. the AsIsPrepare() function can be called to set up exactly what you wish 
  3930. modified. 
  3931.  
  3932. Note that you may not wish to use this routine because of interference you 
  3933. might cause with the use of the #AsIs command, in this case you might find 
  3934. BulkChar2String() useful. 
  3935.  
  3936. This routine is useful where you are reading in data directly rather than using 
  3937. #include or #import commands.  You could be using the rexx linein() routine or 
  3938. accessing SQL data. 
  3939.  
  3940. Stupid Example 
  3941.  
  3942.     ;--- Setup INTERNATIONAL symbols (2 only for this demo) ---
  3943.     #AutoTagState +
  3944.     #AutoTag      '╨ö'    'ä'
  3945.     #AutoTag      '╨Ö'    'ë'    ;;Only 2 for this example
  3946.     #AsIs         SETUP  INTERNATIONAL_SYMBOLS
  3947.     #AutoTagState -
  3948.  
  3949.     ;--- Prepare ASIS Tagging ----------------------------
  3950.     #evaluate "" ^AsIsPrepare("INTERNATIONAL_SYMBOLS")^
  3951.  
  3952.     ;--- Assign to some variables ------------------------
  3953.     #evaluate "NoChanges"   ^"╨Ö ╨Ö ╨Ö"^
  3954.     #evaluate "Changesmade" ^AsIs("╨Ö ╨Ö ╨Ö")^
  3955.  
  3956.     ;--- Generate couple of lines ------------------------
  3957.     BEFORE: <$NoChanges>
  3958.     AFTER : <$Changesmade>
  3959.  
  3960.  
  3961. ΓòÉΓòÉΓòÉ 5.9.6. AsIsPrepare() ΓòÉΓòÉΓòÉ
  3962.  
  3963. AsIsPrepare() 
  3964.  
  3965. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  3966. extensions) can be used with any operating system supported by PPWIZARD. 
  3967.  
  3968. This function takes a single parameter made up zero or more "names" previous 
  3969. setup with the "SETUP" command of #AsIs. 
  3970.  
  3971. It basically identifies the tagging you wish to have take place when the AsIs() 
  3972. routine is called. 
  3973.  
  3974.  
  3975. ΓòÉΓòÉΓòÉ 5.9.7. AutoTag() ΓòÉΓòÉΓòÉ
  3976.  
  3977. AutoTag() 
  3978.  
  3979. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  3980. extensions) can be used with any operating system supported by PPWIZARD. 
  3981.  
  3982. This function takes a single parameter and will return the string after all 
  3983. currently defined #AutoTag replacements have been make. 
  3984.  
  3985. Note that this replacement occurs whether or not "auto tag" mode is currently 
  3986. on. 
  3987.  
  3988. This routine is useful where you are reading in data directly rather than using 
  3989. #include or #import commands.  You could be using the rexx linein() routine or 
  3990. accessing SQL data. 
  3991.  
  3992. Stupid Example 
  3993.  
  3994.     #AutoTagState +
  3995.     #AutoTag      'FROM'    'TO'
  3996.     #evaluate     'Result'  AutoTag('from / FROM');
  3997.     <$Result>                              ;;Output saved result.
  3998.     #AutoTagState -
  3999.  
  4000.  
  4001. ΓòÉΓòÉΓòÉ 5.9.8. BaseDate() ΓòÉΓòÉΓòÉ
  4002.  
  4003. BaseDate() 
  4004.  
  4005. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4006. extensions) can be used with any operating system supported by PPWIZARD. 
  4007.  
  4008. This function can be called to work out a basedate (julian day) given a date. 
  4009. The integer will be negative if an error occurred. You can tell how many days 
  4010. apart 2 dates are by subtraction of one from the other.  The basedate is the 
  4011. number of days since 1 January 0001. 
  4012.  
  4013. If the returned basedate integer is divided by 7, the remainder will tell you 
  4014. what day of the week it is (where 0=Monday, 6=Sunday). 
  4015.  
  4016. The number returned for a date is compatible with rexx's "date('BaseDate')" 
  4017. call. 
  4018.  
  4019. INPUT DATE 
  4020.  
  4021. The routine takes a single parameter (the date) with the year, month and day of 
  4022. month being supplied in that order.  The year should either be supplied as 4 
  4023. digits or will pivot at 1980. 
  4024.  
  4025. It will take the input in these formats: 
  4026.  
  4027.        1. YYYYMMDD - any following characters ignored. 
  4028.        2. YY/MM/DD or YYYY/MM/DD 
  4029.        3. YY-MM-DD or YYYY-MM-DD 
  4030.        4. YY MM DD or YYYY MM DD 
  4031.        5. If nothing passed (or blank) then todays date is used. 
  4032.  
  4033.  Note that it actually does not matter how many digits are supplied for day of 
  4034.  month and month, however a resonable amount of validation occurs. 
  4035.  
  4036.  EXAMPLE INPUT DATES 
  4037.  
  4038.        1. date('Sorted'); 
  4039.        2. date('Ordered'); 
  4040.        3. "98-2-12" 
  4041.        4. "1998/02/01" 
  4042.        5. "20001230" 
  4043.        6. "20001230235959" 
  4044.  
  4045.  
  4046. ΓòÉΓòÉΓòÉ 5.9.9. BreakAt() ΓòÉΓòÉΓòÉ
  4047.  
  4048. BreakAt() 
  4049.  
  4050. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4051. extensions) can be used with any operating system supported by PPWIZARD. 
  4052.  
  4053. This function gets passed a string and ensures that no component is larger than 
  4054. a value you specify.  It is useful for automatically breaking up long URLs in 
  4055. tables etc so a column does not get too wide. The function takes the following 
  4056. parameters: 
  4057.  
  4058.        1. Break Length 
  4059.           There are 2 formats for this value: 
  4060.  
  4061.               A single integer specifies the maximum width of each component. 
  4062.                The minimum is a third of this value. 
  4063.  
  4064.               You can supply both the minimum & maximum values by separating 
  4065.                them with "-" (as in "5-40"). 
  4066.  
  4067.        2. String 
  4068.           This is the string we are adjusting. 
  4069.  
  4070.        3. Break At Char List 
  4071.           This is a list of chars.  We will try and find the longest string 
  4072.           less than or equal to "Break Length" that breaks after one of these 
  4073.           specified characters, if we can't find one the string is just 
  4074.           truncated at the maximum length.  If this optional value is not 
  4075.           specified then "./:#" is used. 
  4076.  
  4077.        4. Break With Character 
  4078.           This specifies the string used to break the string. If this optional 
  4079.           value is not specified then "<BR>" is used. 
  4080.  
  4081.  The resultant string is returned. 
  4082.  
  4083.  EXAMPLE 
  4084.  
  4085.  This example shows a table where the first column contains a URL as a 
  4086.  hypertext link to the URL shown.  We don't wish the column to be wider than 18 
  4087.  characters (longer URLs will span multiple lines). 
  4088.  
  4089.       ;--- Define a macro to (1) Create link (2) split up long URLS ---
  4090.       #define LinkToDisplayedURL                             \
  4091.               #evaluate "TmpResult" @BreakAt(18, '{$URL}')@  \
  4092.               <A TARGET=_top HREF="http://{$URL}">           \
  4093.               <$TmpResult></A>                               \
  4094.               #undef     TmpResult
  4095.  
  4096.       ;--- Example of use in a table ----------------------------------
  4097.       <BR><CENTER><TABLE COLS=2 BORDER=5 CELLSPACING=5>
  4098.           ;------------------------------------------------------------
  4099.           <TR>
  4100.           <TH ALIGN=CENTER>http://
  4101.           <TH ALIGN=CENTER>Information</B>
  4102.           </TR>
  4103.  
  4104.           ;------------------------------------------------------------
  4105.           <TR>
  4106.           <TD ALIGN=CENTER><$LinkToDisplayedURL URL="www.geocities.com/SiliconValley/Heights/6121/">
  4107.           <TD ALIGN=CENTER>
  4108.           Programmer's Info Page.
  4109.           </TR>
  4110.       </TABLE></CENTER>
  4111.  
  4112.  
  4113. ΓòÉΓòÉΓòÉ 5.9.10. BulkChar2String() ΓòÉΓòÉΓòÉ
  4114.  
  4115. BulkChar2String() 
  4116.  
  4117. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4118. extensions) can be used with any operating system supported by PPWIZARD. 
  4119.  
  4120. This function is used to convert a whole series of single characters into 
  4121. strings. To convert single characters to other single characters you would of 
  4122. course use the rexx translate() routine. 
  4123.  
  4124. This function takes 2 parameters as follows: 
  4125.  
  4126.        1. The name of the source string. 
  4127.  
  4128.        2. The name of a rexx variable which lists each of the characters (in 
  4129.           order) which you wish to convert. For each character in this string 
  4130.           an element in the array of the same name contains what it should be 
  4131.           converted to. The BulkChangePrepare() routine can be used to simplify 
  4132.           the creation of the change information. 
  4133.  
  4134.  The routine returns the possibly modified source string. 
  4135.  
  4136.  When this routine returns the rexx variable ReplaceCount will have been 
  4137.  incremented by the number of replacements made. 
  4138.  
  4139.  Silly Example 
  4140.  
  4141.       ;--- Set up the conversion information ------
  4142.       #DefineRexx ""
  4143.          call BulkChangePrepare "Conv";                 ;;Initialize to empty
  4144.          call BulkChangePrepare "Conv", '&', '&';
  4145.          call BulkChangePrepare "Conv", '<', '<';
  4146.          call BulkChangePrepare "Conv", '>', '>';
  4147.       #DefineRexx
  4148.  
  4149.       ;--- Modify the input string -----------------
  4150.       #evaluate '' ^say 'MODIFIED = ' || BulkChar2String('AAAA <&> BBBB', 'Conv')^
  4151.  
  4152.  
  4153. ΓòÉΓòÉΓòÉ 5.9.11. BulkChangePrepare() ΓòÉΓòÉΓòÉ
  4154.  
  4155. BulkChangePrepare() 
  4156.  
  4157. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4158. extensions) can be used with any operating system supported by PPWIZARD. 
  4159.  
  4160. This function is used to prepare the information required by the 
  4161. BulkChar2String() routine. 
  4162.  
  4163. This function takes 1 or 3 parameters as follows: 
  4164.  
  4165.        1. The name of a rexx variable which you will use in the change call. 
  4166.  
  4167.        2. The character to be replaced. 
  4168.  
  4169.        3. The string that will replace the character. 
  4170.  
  4171.  To initialize the change information this routine should be called with out 
  4172.  the second and third parameters. This routine does not return anything. 
  4173.  
  4174.  
  4175. ΓòÉΓòÉΓòÉ 5.9.12. CompareReplaceFixed() ΓòÉΓòÉΓòÉ
  4176.  
  4177. CompareReplaceFixed() 
  4178.  
  4179. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4180. extensions) can be used with any operating system supported by PPWIZARD. 
  4181.  
  4182. This function has 2 main operations as follows: 
  4183.  
  4184.        1. Compare a string against a compare specification. The return 
  4185.           specification parameter is not passed by the caller. Returns 0 if not 
  4186.           matched and 1 if match. 
  4187.  
  4188.        2. Compare a string against a compare specification. Either return the 
  4189.           original string on no match or a new string as specified by the 
  4190.           return specification. 
  4191.  
  4192.  This is quite a complicated routine and hopefully the examples will clarify 
  4193.  things. 
  4194.  
  4195.  This routine can be very useful in #AsIs and #AutoTag processing. 
  4196.  
  4197.  The function takes 3 parameters as follows: 
  4198.  
  4199.        1. The string to be compared with. 
  4200.  
  4201.        2. The COMPARE specification. This is made up of one or more of the 
  4202.           following command sequences (in any order): 
  4203.  
  4204.               @Operator,Posn=^CmpText^ 
  4205.                The "operator" is a rexx compare operator such as "=" or "<>". 
  4206.  
  4207.                The "posn" is the integer position of the substring within the 
  4208.                "COMPARE" parameter to compare with "CmpText". If the value is 
  4209.                positive then the value refers to a position from the left else 
  4210.                it refers to a position from the right. For example "2" 
  4211.                indicates the second character from the left while "-2" 
  4212.                indicates the second last character. The length of the substring 
  4213.                is the same as the length of "CmpText". 
  4214.  
  4215.                Any character can be used for a quote character around the 
  4216.                "CmpText". 
  4217.  
  4218.               ?Operator/CmpText/ 
  4219.                The operator should be either "=" or "!".  If "=" then we expect 
  4220.                to find "CmpText" in the first parameter, otherwise we don't. 
  4221.  
  4222.                Any character can be used for a quote character around the 
  4223.                "CmpText". 
  4224.  
  4225.               !SubCommand 
  4226.                The subcommand is one of: 
  4227.  
  4228.                  -  S 
  4229.                     The following compares are to be case sensitive (each time 
  4230.                     this routine is called it begins in case sensitive mode). 
  4231.  
  4232.                  -  i 
  4233.                     The following compares are to be case insensitive (you 
  4234.                     should supply upper case "CmpText" text). 
  4235.  
  4236.                  -  I 
  4237.                     Ignore leading and trailing whitespace. Convert multiple 
  4238.                     spaces into a single space. 
  4239.  
  4240.                  -  B 
  4241.                     Ignore leading and trailing whitespace. 
  4242.  
  4243.                  -  L 
  4244.                     Ignore leading whitespace. 
  4245.  
  4246.                  -  T 
  4247.                     Ignore trailing whitespace. 
  4248.  
  4249.        3. The RETURN specification. If not supplied then we are doing a simple 
  4250.           compare operation and returning 1 on match and 0 if not. 
  4251.  
  4252.           This parameter determines what string this routine will return. You 
  4253.           can extract parts of the first parameter and intermix text of your 
  4254.           own. A return command is imbedded in text and begins with the '@' 
  4255.           character, the following byte determines the type of command, valid 
  4256.           commands are: 
  4257.  
  4258.               @ 
  4259.                A '@@' indicates that the user wishes a single '@'. This is an 
  4260.                escape sequence which allows the '@' character to be specified. 
  4261.  
  4262.               $Posn,Len; 
  4263.                You wish to extract a string out of the first parameter. You 
  4264.                need to specify its position and length. You may supply '*' for 
  4265.                the length to indicate that the rest of the string is desired. 
  4266.  
  4267.                If the value is positive then the value refers to a position 
  4268.                from the left else it refers to a position from the right. For 
  4269.                example "2" indicates the second character from the left while 
  4270.                "-2" indicates the second last character. 
  4271.  
  4272.               =/RexxExpression/ 
  4273.                A rexx expression is executed to determine the text to be used, 
  4274.                you have access to the first parameter of this routine in the 
  4275.                variable "CompareString". This method should be avoided where 
  4276.                ever possible as it is significantly slower. 
  4277.  
  4278.                Any character can be used for a quote character around the 
  4279.                "RexxExpression" parameter. 
  4280.  
  4281.  While some validation of the parameters is performed you should be careful 
  4282.  with the parameters passed. If invalid parameters are passed you probably will 
  4283.  not get the "change" you desire and I'm not ruling out a PPWIZARD trap. 
  4284.  Validations are only performed when they will not (greatly) affect 
  4285.  performance. 
  4286.  
  4287.  Example - Compare Specifications 
  4288.  
  4289.        1. @=,1=^HTML^ 
  4290.           To see if a string starts with the characters "HTML" (in that case). 
  4291.  
  4292.        2. @=,1=^HTML^!i@=,-2=^YZ^ 
  4293.           To see if a string starts with the characters "HTML" (in that case) 
  4294.           and ends with the characters "YZ" (in any case). 
  4295.  
  4296.        3. !B@=,1=^HTML^!i@=,-2=^YZ^ 
  4297.           Same as above but leading and trailing whitespace is ignored. 
  4298.  
  4299.        4. @=,1=/HTML/!i@<>,-2=\YZ\ 
  4300.           To see if a string starts with the characters "HTML" (in that case) 
  4301.           and does not end with the characters "YZ" (in any case). 
  4302.  
  4303.        5. !i?=/HTML/ 
  4304.           We expect the compare string to contain "HTML" (in any case). 
  4305.  
  4306.  Example - Return Specifications 
  4307.  
  4308.        1. ABCD 
  4309.           Return the string "ABCD". 
  4310.  
  4311.        2. AB@@C@@D 
  4312.           Return the string "AB@C@D". 
  4313.  
  4314.        3. REM @$1,*; 
  4315.           Return the compare string (first parameter) preceeded by "REM ". 
  4316.  
  4317.        4. REM @$1,1;@$3,1;@$-1,1; 
  4318.           Return the 1st and 3rd and last characters of the compare string 
  4319.           preceeded by "REM ". 
  4320.  
  4321.        5. REM (@=/strip(CompareString)/) 
  4322.           Return the line stripped of leading and trailing whitespace 
  4323.           surrounded by round brackets and preceeded by "REM ". 
  4324.  
  4325.  Stupid Examples 
  4326.  
  4327.       ;--- The following compare operation will return "1" as the compare "matches" ---
  4328.       #evaluate ^^ ^say 'Expect to see 1    ==> ' || CompareReplaceFixed('HTML', '@=,1=~HTML~')^
  4329.  
  4330.       ;--- The following compare matches and the return specification is processed ---
  4331.       #evaluate ^^ ^say 'Expect to see ASDF ==> ' || CompareReplaceFixed('HTML', '@=,1=~HTML~', 'ASDF')^
  4332.  
  4333.  
  4334. ΓòÉΓòÉΓòÉ 5.9.13. DataGet() ΓòÉΓòÉΓòÉ
  4335.  
  4336. DataGet() 
  4337.  
  4338. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4339. extensions) can be used with any operating system supported by PPWIZARD. 
  4340.  
  4341. This function is used to retrieve a value previously stored away with the 
  4342. DataSave() function. 
  4343.  
  4344. It is OK for the value not to exist, if this is the case the "default" value 
  4345. you specified will be returned.  If you wish you can make the "default" value 
  4346. some sort of "invalid value" to detect what you consider to be an error. 
  4347.  
  4348. The function takes 3 parameters as follows: 
  4349.  
  4350.        1. The Application Key. 
  4351.  
  4352.        2. The Key. 
  4353.  
  4354.        3. The default value (optional, default is ''). 
  4355.  
  4356.  
  4357. ΓòÉΓòÉΓòÉ 5.9.14. Debug() ΓòÉΓòÉΓòÉ
  4358.  
  4359. Debug() 
  4360.  
  4361. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4362. extensions) can be used with any operating system supported by PPWIZARD. 
  4363.  
  4364. This function is used to output a debug line. The line is only output if debug 
  4365. mode is currently on. 
  4366.  
  4367. The DebugIndent() call can be used to make your output easier to understand. 
  4368.  
  4369. The function takes a single parameter and that is the line to be output. 
  4370.  
  4371.  
  4372. ΓòÉΓòÉΓòÉ 5.9.15. DebugIndent() ΓòÉΓòÉΓòÉ
  4373.  
  4374. DebugIndent() 
  4375.  
  4376. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4377. extensions) can be used with any operating system supported by PPWIZARD. 
  4378.  
  4379. This function is passed a single numeric parameter which is positive or 
  4380. negative (normally -1 or 1). A postive value causes a bigger indent on the left 
  4381. of Debug() output. 
  4382.  
  4383. If you increase the indent you should remember to decrease it when finished. 
  4384.  
  4385.  
  4386. ΓòÉΓòÉΓòÉ 5.9.16. DataSave() ΓòÉΓòÉΓòÉ
  4387.  
  4388. DataSave() 
  4389.  
  4390. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4391. extensions) can be used with any operating system supported by PPWIZARD. 
  4392.  
  4393. This function is used to save a value away using a 2 part key.  If you wish you 
  4394. can make the first part constant.  The value can be retrieved using the 
  4395. DataGet() function. 
  4396.  
  4397. The function takes 3 parameters as follows: 
  4398.  
  4399.        1. The Application Key. 
  4400.  
  4401.        2. The Key. 
  4402.  
  4403.        3. The data to store. 
  4404.  
  4405.  Note that there is no information returned by this function. 
  4406.  
  4407.  WARNING 
  4408.  
  4409.  Currently the value you save is kept between compiles, this is not the aim and 
  4410.  will be corrected in a future release.  Do not code anything that relies on 
  4411.  this fact.  If you use this routine you will need to consider if you can 
  4412.  compile more than one source at a time. 
  4413.  
  4414.  
  4415. ΓòÉΓòÉΓòÉ 5.9.17. Defined() ΓòÉΓòÉΓòÉ
  4416.  
  4417. Defined() 
  4418.  
  4419. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4420. extensions) can be used with any operating system supported by PPWIZARD. 
  4421.  
  4422. This function can be called (probably in a #if command) to determine if a 
  4423. variable has been defined with either #define or #evaluate.  The return code is 
  4424. either 'N' or 'Y'. 
  4425.  
  4426. You would use this routine in a #if command rather than a #ifdef or #ifndef if 
  4427. you want to do something which involves testing the existance of more than one 
  4428. variable. 
  4429.  
  4430. The parameters are as follows: 
  4431.  
  4432.        1. Define Name 
  4433.           This is the name of the variable. 
  4434.  
  4435.  EXAMPLE 
  4436.  
  4437.       #ifdef Var1
  4438.            ...
  4439.       #endif
  4440.  
  4441.       #if  Defined('Var1') = 'Y' | Defined('Var2') = 'Y'
  4442.            ...
  4443.       #endif
  4444.  
  4445.  
  4446. ΓòÉΓòÉΓòÉ 5.9.18. DieIfIoErrorOccurred() ΓòÉΓòÉΓòÉ
  4447.  
  4448. DieIfIoErrorOccurred() 
  4449.  
  4450. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4451. extensions) can be used with any operating system supported by PPWIZARD. 
  4452.  
  4453. This function can be called to at any time prior to the closing of a file 
  4454. (stream) to determine if any input/output errors have occurred. 
  4455.  
  4456. The routine will display a message and abort PPWIZARD processing if an error 
  4457. has occurred. 
  4458.  
  4459. The parameters are as follows: 
  4460.  
  4461.        1. File Name 
  4462.           This is the name of an unclosed file. 
  4463.  
  4464.  
  4465. ΓòÉΓòÉΓòÉ 5.9.19. EnsureFileHasCorrectCase() ΓòÉΓòÉΓòÉ
  4466.  
  4467. EnsureFileHasCorrectCase() 
  4468.  
  4469. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4470. extensions) can be used with any operating system supported by PPWIZARD. 
  4471.  
  4472. This routine takes a filename as its only parameter and adjusts its filename as 
  4473. specified with the "/FileNames" command line switch. 
  4474.  
  4475. Note that while the intention of this routine is to adjust the case of 
  4476. filenames there is no reason why any rexx string can't be passed if you have 
  4477. the need. 
  4478.  
  4479.  
  4480. ΓòÉΓòÉΓòÉ 5.9.20. Error() ΓòÉΓòÉΓòÉ
  4481.  
  4482. Error() 
  4483.  
  4484. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4485. extensions) can be used with any operating system supported by PPWIZARD. 
  4486.  
  4487. This routine is probably most useful in #import filter code and takes from 1 to 
  4488. 10 parameters. Each parameter contains the contents of a line to be displayed. 
  4489.  
  4490. The passed message line(s) will be displayed and PPWIZARD processing 
  4491. terminated. 
  4492.  
  4493.  
  4494. ΓòÉΓòÉΓòÉ 5.9.21. ExpandXCodes() ΓòÉΓòÉΓòÉ
  4495.  
  4496. ExpandXCodes() 
  4497.  
  4498. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4499. extensions) can be used with any operating system supported by PPWIZARD. 
  4500.  
  4501. This routine can be called to expand <?xXX> codes. 
  4502.  
  4503. This routine is passed a single parameter. The codes are expanded and the 
  4504. result returned. 
  4505.  
  4506.  
  4507. ΓòÉΓòÉΓòÉ 5.9.22. GenerateFileName() ΓòÉΓòÉΓòÉ
  4508.  
  4509. GenerateFileName() 
  4510.  
  4511. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4512. extensions) can be used with any operating system supported by PPWIZARD. 
  4513.  
  4514. This function returns a filename which is translated in the same way as the 
  4515. "/Output" switch. It also ensures that any directory component of the generated 
  4516. filename exists. 
  4517.  
  4518. The parameters are as follows: 
  4519.  
  4520.        1. Name of a file 
  4521.           This is the name of a file that is used as a basic for conversion 
  4522.           using the second parameter. 
  4523.  
  4524.        2. Conversion Specification 
  4525.           This tells PPWIZARD how to convert the first parameter. 
  4526.  
  4527.  Example 
  4528.  
  4529.       ;--- For the current input file work out a good name for a debug file ---
  4530.       #evaluate '' ^DebugFile = GenerateFileName('<?InputFile>', 'out\*.DBG')^
  4531.  
  4532.  
  4533. ΓòÉΓòÉΓòÉ 5.9.23. GetAmPmTime() ΓòÉΓòÉΓòÉ
  4534.  
  4535. GetAmPmTime() 
  4536.  
  4537. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4538. extensions) can be used with any operating system supported by PPWIZARD. 
  4539.  
  4540. This function takes no parameters and returns the time including seconds with 
  4541. "am" or "pm" attached. 
  4542.  
  4543.  
  4544. ΓòÉΓòÉΓòÉ 5.9.24. GetEnv() ΓòÉΓòÉΓòÉ
  4545.  
  4546. GetEnv() 
  4547.  
  4548. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4549. extensions) can be used with any operating system supported by PPWIZARD. 
  4550.  
  4551. This function returns the value of an operating system environment variable. An 
  4552. empty string is returned if the variable is unknown. 
  4553.  
  4554. The parameters are as follows: 
  4555.  
  4556.        1. Variable Name 
  4557.           This is the name of the environment variable. 
  4558.  
  4559.        2. Die if Missing? 
  4560.           This optional variable is used to tell ppwizard to abort if the 
  4561.           variable could not be found. To tell PPWIZARD to abort pass upper 
  4562.           case 'Y'. 
  4563.  
  4564.  Example 
  4565.  
  4566.       ;--- Lets keep all WORK/HOME conditional logic here -------------------------
  4567.       #define AtHome  translate(GetEnv("PRJSRCDIR", 'Y')) =  "E:\DB\PROJECTS\HOMEPAGE\HTML"
  4568.       #define AtWork  translate(GetEnv("PRJSRCDIR", 'Y')) <> "E:\DB\PROJECTS\HOMEPAGE\HTML"
  4569.  
  4570.       ...
  4571.       ...
  4572.  
  4573.       ;--- External Links ---------------------------------------------------------
  4574.       #if    <$AtHome>
  4575.               #define ExtLink   <A TARGET=_top HREF="{$URL}">{$VISIBLE=`{$URL}`}</A>
  4576.       #elseif
  4577.               #define ExtLink   {$VISIBLE=`{$URL}`}{$URL-}
  4578.       #endif
  4579.  
  4580.  
  4581. ΓòÉΓòÉΓòÉ 5.9.25. GetFileLineBeingProcessed() ΓòÉΓòÉΓòÉ
  4582.  
  4583. GetFileLineBeingProcessed() 
  4584.  
  4585. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4586. extensions) can be used with any operating system supported by PPWIZARD. 
  4587.  
  4588. This function takes no parameters and returns the text of the current line 
  4589. being processed. The line is as read from a file and may or may not be the 
  4590. current line being processed (after macro expansion etc). The line being 
  4591. processed is available using the GetLineBeingProcessed() call. 
  4592.  
  4593. The returned line has been stripped of leading and trailing whitespace. This 
  4594. call would usually be called to remember details about a current situation 
  4595. which you may wish to report at some future stage. 
  4596.  
  4597. If using this call you may also wish to use GetInputFileNameAndLine(), see this 
  4598. section for an example of these calls in use. 
  4599.  
  4600.  
  4601. ΓòÉΓòÉΓòÉ 5.9.26. GetFileTimeStamp() ΓòÉΓòÉΓòÉ
  4602.  
  4603. GetFileTimeStamp() 
  4604.  
  4605. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4606. extensions) can be used with any operating system supported by PPWIZARD. 
  4607.  
  4608. This function takes a single parameter (the name of the file we wish the 
  4609. date/time imformation of). 
  4610.  
  4611. If successful this routine returns a decimal number of the form 
  4612. "YYYYMMDDHHMMSS".  The returned number can be compared with others to determine 
  4613. the newest file etc. You can substr() etc to transform the result into whatever 
  4614. format you desire. 
  4615.  
  4616. If the call fails (for example if the specified file does not exist) then a 
  4617. WARNING is generated and a return code of "-1" is returned. 
  4618.  
  4619. You can determine the day of the week for the file using the BaseDate routine. 
  4620.  
  4621. Example 
  4622.  
  4623. The following example shows how the date/time of a file can be retrieved and 
  4624. converted into whatever format you wish.  Note that in the following macro I 
  4625. was careful not to redefine any variables and that a file not found is treated 
  4626. as a fatal error. 
  4627.  
  4628.     #define   GetFileDateTime                                                    \
  4629.               #evaluate  TmpDateTime  ^GetFileTimeStamp("{$File}");^             \
  4630.               #if   <$TmpDateTime> = -1                                          \
  4631.                     #error ^The file "{$File}" was not found.^                   \
  4632.               #elseif                                                            \
  4633.                     #evaluate TmpDate ^substr('<$TmpDateTime>', 7, 2) || '/' || substr('<$TmpDateTime>', 5, 2) || '/' || left('<$TmpDateTime>', 4)^  \
  4634.                     #evaluate TmpHH ^substr('<$TmpDateTime>', 9, 2)^             \
  4635.                     #if <$TmpHH> < 12                                            \
  4636.                         #define TmpAmPm am                                       \
  4637.                     #elseif                                                      \
  4638.                         #define TmpAmPm pm                                       \
  4639.                     #endif                                                       \
  4640.                     #if <$TmpHH> > 12                                            \
  4641.                         #evaluate TmpHHAmPm ^<$TmpHH> - 12^                      \
  4642.                     #elseif                                                      \
  4643.                         #evaluate TmpHHAmPm ^<$TmpHH>^                           \
  4644.                     #endif                                                       \
  4645.                     #evaluate TmpTime    ^"<$TmpHHAmPm><$colon>" || substr('<$TmpDateTime>', 11, 2) || '<$colon>' || substr('<$TmpDateTime>', 13, 2) || '<$TmpAmPm>'^ \
  4646.                                                                                  \
  4647.                     ;--- Output the information ("DD/MM/YYYY at HH<$colon>MM<$colon>SSam") --- \
  4648.                     <$TmpDate> at <$TmpTime>                                     \
  4649.                     #undef TmpDate                                               \
  4650.                     #undef TmpTime                                               \
  4651.                     #undef TmpHH                                                 \
  4652.                     #undef TmpHHAmPm                                             \
  4653.                     #undef TmpAmPm                                               \
  4654.               #endif                                                             \
  4655.               #undef TmpDateTime
  4656.  
  4657.     ;--- Use my macro to get a timestamp -------------------------------------
  4658.     <P>The date/time stamp of "C:\AUTOEXEC.BAT" is "<$GetFileDateTime File="C:\AUTOEXEC.BAT">".
  4659.  
  4660.  
  4661. ΓòÉΓòÉΓòÉ 5.9.27. GetId() ΓòÉΓòÉΓòÉ
  4662.  
  4663. GetId() 
  4664.  
  4665. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4666. extensions) can be used with any operating system supported by PPWIZARD. 
  4667.  
  4668. This function is useful if you wish to ensure that all characters in a string 
  4669. are valid.  This can be useful when you wish to use a value as a key of some 
  4670. sort.  For the value that you pass, this routine will determine a unique key 
  4671. (or ID) of the format you requested. 
  4672.  
  4673. The routine has a memory and will always return the same ID for the same value. 
  4674.  
  4675. The function takes at least 3 parameters as follows: 
  4676.  
  4677.        1. A handle that was previously prepared with GetIdPrepare(). 
  4678.  
  4679.        2. The type of ID you'd like, valid types being: 
  4680.  
  4681.               2_ 
  4682.                Non valid characters are converted to underscores.  Leading and 
  4683.                trailing underscores are removed.  Duplicated underscores are 
  4684.                also removed. 
  4685.  
  4686.                The upper and lower case characters as well as zero to nine are 
  4687.                always valid characters.  You may specify additional valid 
  4688.                characters in the optional 4th parameter to this function. 
  4689.  
  4690.               MAXCHARS 
  4691.                The value is first converted in a similar manner to that used 
  4692.                for "2_" mode. The leftmost 'x' chars are kept. 
  4693.  
  4694.                The upper and lower case characters as well as zero to nine are 
  4695.                always valid characters.  You may specify additional valid 
  4696.                characters in the optional 4th parameter to this function. 
  4697.  
  4698.                The optional 5th parameter specifies the maximum number of 
  4699.                characters in an ID with the default being 8. 
  4700.  
  4701.                This type can be used to generate file names for a 8.3 based 
  4702.                file system. 
  4703.  
  4704.               C2X 
  4705.                Non valid characters are converted to 'x??', where '??' is the 
  4706.                characters ASCII code in hexadecimal. 
  4707.  
  4708.                The upper and lower case characters as well as zero to nine are 
  4709.                always valid characters.  You may specify additional valid 
  4710.                characters in the optional 4th parameter to this function. 
  4711.  
  4712.        3. The value for which you want an ID generated.  This is case 
  4713.           sensitive, to make case insensitive simply convert your value to 
  4714.           either upper or lower case before calling this routine. 
  4715.  
  4716.        4. Depending on the type of ID being generated there may be a 4th or 
  4717.           other parameters. 
  4718.  
  4719.  Example 
  4720.  
  4721.       ;--- Example #1 ---
  4722.       #evaluate ''   ^call GetIdPrepare 'PPW'^
  4723.       #evaluate ''   ^call SetId 'PPW', '#define', "HashDef"^       ;;Set preferred ID
  4724.       #evaluate ''   ^say GetId('PPW', 'MAXCHARS', 'define')^
  4725.       #evaluate ''   ^say GetId('PPW', 'MAXCHARS', '#define')^
  4726.       #evaluate ''   ^say GetId('PPW', 'MAXCHARS', 'define it')^
  4727.       #evaluate ''   ^say GetId('PPW', 'MAXCHARS', 'define')^
  4728.       #evaluate ''   ^say GetId('PPW', 'MAXCHARS', 'aaaaaaaaaaaaaaaa',, 10)^  ;;Max 10 chars
  4729.       #evaluate ''   ^say GetId('PPW', 'MAXCHARS', 'aaaaaaaaaaaaaaab',, 10)^
  4730.       #evaluate ''   ^say GetId('PPW', 'MAXCHARS', 'aaaaaaaaaaaaaaac',, 10)^
  4731.       #evaluate ''   ^say GetId('PPW', 'MAXCHARS', 'aaaaaaaaaaaaaaaa',, 10)^
  4732.  
  4733.       ;--- Example #2 ---
  4734.       #evaluate ''   ^call GetIdPrepare 'PPW'^
  4735.       #evaluate ''   ^say GetId('PPW', '2_', '#define')^
  4736.       #evaluate ''   ^say GetId('PPW', '2_', '#include', '#')^  ;;Allow Hash to be valid as well
  4737.  
  4738.  
  4739. ΓòÉΓòÉΓòÉ 5.9.28. GetIdPrepare() ΓòÉΓòÉΓòÉ
  4740.  
  4741. GetIdPrepare() 
  4742.  
  4743. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4744. extensions) can be used with any operating system supported by PPWIZARD. 
  4745.  
  4746. This function is used to prepare a handle for use in the GetId() routine. 
  4747.  
  4748. The function takes 2 parameters: 
  4749.  
  4750.        1. The handle to be used in GetId() and SetId(). 
  4751.  
  4752.        2. An optional parameter which if 'Y' means that you wish unique IDs 
  4753.           generated by GetId() for what are probably non-unique values (or 
  4754.           keys). When you specify unique IDs you are only allowed to use 
  4755.           SetId() with a key of '' otherwise you are contradicting yourself! 
  4756.  
  4757.           Normally when GetId() is called you pass it a unique key for which 
  4758.           you wish a unique ID generated. If you ask for an ID for the same key 
  4759.           at some later stage the original ID is returned. 
  4760.  
  4761.           When 'Y' is used you intend to pass non-unique keys but YOU ensure or 
  4762.           know that each time GetId() is called it is for a different entity 
  4763.           even if the key looks identical!  GetId() will generate a unique ID 
  4764.           each time it is called and will not remember it. This mode can 
  4765.           generate "prettier" IDs (at least until the key is duplicated) and 
  4766.           without tricky code. The "FTPLIKE.IH" header file uses the "unique" 
  4767.           mode. 
  4768.  
  4769.  
  4770. ΓòÉΓòÉΓòÉ 5.9.29. GetImageHeightWidth() ΓòÉΓòÉΓòÉ
  4771.  
  4772. GetImageHeightWidth() 
  4773.  
  4774. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4775. extensions) can be used with any operating system supported by PPWIZARD. 
  4776.  
  4777. This function can be used to automatically generate the HEIGHT and WIDTH 
  4778. parameters on a html "IMG" tag. 
  4779.  
  4780. The function takes 3 parameters (the 2nd and 3rd are optional), the parameters 
  4781. are: 
  4782.  
  4783.        1. The name of a file (.GIF or .JPG) 
  4784.  
  4785.        2. The width  scaling factor (default = "100%"). 
  4786.  
  4787.        3. The height scaling factor (default = "?"). 
  4788.  
  4789.  The scaling factor can be in these formats: 
  4790.  
  4791.          A number followed by a percentage sign scales the size by the amount 
  4792.           specified. "50%" would halve the size while 200% would double it. 
  4793.  
  4794.          A number on its own (such as "100") fixes the size to the value 
  4795.           supplied.  It would be a common thing for the other sides size to be 
  4796.           specified with "?" to have it scaled down in a proportional manner. 
  4797.  
  4798.          A "?" causes the side to be sized in the same proportion as the other 
  4799.           side. 
  4800.  
  4801.  Note that scaling both sizes of an image by "50%" gives you an image a 1/4 of 
  4802.  the size. 
  4803.  
  4804.  If an error occurs the routine aborts, otherwise a string similar to "WIDTH=10 
  4805.  HEIGHT=20" gets returned. 
  4806.  
  4807.  Note that as the image file needs to be read to determine its size this 
  4808.  routine will slow down the preprocessing of your files.  You could get smart 
  4809.  and generate an image header file of sizes (each one #defined) so that a 
  4810.  separate slow step generates a header file that html source includes. 
  4811.  
  4812.  Example 
  4813.  
  4814.      ;--- Photo macro will either use passed size or work out correct size for you ---
  4815.      #define Photo                                                               \
  4816.              #evaluate+  LocalFileName    ^"..\graphics\{$Image}"^               \
  4817.              #DependsOn  INPUT            "<$LocalFileName>"                     \
  4818.              <TR>                                                                \
  4819.              #if "{$Size=''}" <> ""                                              \
  4820.                  #define+   TmpSize {$Size=''}     ;;User supplied size          \
  4821.              #elseif                                                             \
  4822.                  #evaluate+ TmpSize ^GetImageHeightWidth("<$LocalFileName>")^    \
  4823.              #endif                                                              \
  4824.              <TD ALIGN=CENTER>                                                   \
  4825.              <IMG SRC="graphics/clear1x1.gif" WIDTH=1 HEIGHT=1 VSPACE=20>        \
  4826.              {$Title}<BR><BR>                                                    \
  4827.              <IMG SRC="graphics/{$Image}" BORDER=0 <$TmpSize> ALT="{$Title}">    \
  4828.              <IMG SRC="graphics/clear1x1.gif" WIDTH=1 HEIGHT=1 VSPACE=20>        \
  4829.              </TR>
  4830.  
  4831.       ;--- Create table of photos --------------------------------------------
  4832.       <BR><CENTER><TABLE COLS=1 BORDER=10 CELLSPACING=10>
  4833.          <TR>
  4834.          <TH ALIGN=CENTER>Pictures
  4835.          </TR>
  4836.  
  4837.          ;--- Include all my photos ------------------------------------------
  4838.          <$Photo Image="lazy.jpg"     Title="Watching TV">
  4839.          <$Photo Image="carback.jpg"  Title="New Car (Back Left)">
  4840.       </TABLE></CENTER>
  4841.  
  4842.  
  4843. ΓòÉΓòÉΓòÉ 5.9.30. GetInputFileNameAndLine() ΓòÉΓòÉΓòÉ
  4844.  
  4845. GetInputFileNameAndLine() 
  4846.  
  4847. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4848. extensions) can be used with any operating system supported by PPWIZARD. 
  4849.  
  4850. This function takes no parameters and returns information about the current 
  4851. "location". It reports the current line number and file being processed. This 
  4852. information is already available in other forms (<?InputComponent> & 
  4853. <?InputComponentLine>) however this routine simplifies getting it into a nicely 
  4854. formatted output. 
  4855.  
  4856. If you are interested in this call you should probably also check out the 
  4857. GetFileLineBeingProcessed() and GetLineBeingProcessed() calls. 
  4858.  
  4859. Example 
  4860.  
  4861. This example has been extracted out of the standard PPWIZARD header file 
  4862. NESTCHK.H which can detect and report details of nesting errors such as 
  4863. forgetting a "</TABLE>" tag. 
  4864.  
  4865.     #DefineRexx NestingInc_REXX
  4866.                 ;--- Ensure ID is valid -------
  4867.                 if symbol('{$ID $$SQx2}_Level') <> 'VAR' then
  4868.                    Error('The ID of "{$ID $$SQx2}" is unknown (you must use "NestingInit")!');
  4869.  
  4870.                 ;--- Increase nesting level ---
  4871.                 call _valueS "{$ID}_Level", {$ID}_Level + 1;
  4872.  
  4873.                 ;--- Record details about current location ---
  4874.                 call _valueS "{$ID}_FilePosn.{$ID}_Level", GetInputFileNameAndLine();
  4875.                 call _valueS "{$ID}_CurrLine.{$ID}_Level", GetFileLineBeingProcessed();
  4876.     #DefineRexx
  4877.     #define NestingInc                                            \
  4878.             #evaluate  '' ^<$NestingInc_REXX ID='{$ID}'>^
  4879.  
  4880. The reported output (on nesting errors) looks something like: 
  4881.  
  4882.     NESTING ERRORS
  4883.     ~~~~~~~~~~~~~~
  4884.     Missing 2 end nesting tags on "HTML TABLE tag"
  4885.       * line 8 of "E:\DB\PROJECTS\OS2\ppwizard\1.in"
  4886.         <<$TABLE> COLS=1 blah blah>
  4887.       * line 9 of "E:\DB\PROJECTS\OS2\ppwizard\1.in"
  4888.         <<$TABLE> COLS=2 blah blah>
  4889.  
  4890.  
  4891. ΓòÉΓòÉΓòÉ 5.9.31. GetLineBeingProcessed() ΓòÉΓòÉΓòÉ
  4892.  
  4893. GetLineBeingProcessed() 
  4894.  
  4895. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4896. extensions) can be used with any operating system supported by PPWIZARD. 
  4897.  
  4898. This function takes no parameters and returns the text of the current line 
  4899. being processed. The line returned is after macro expansion and may or may not 
  4900. be as read from the file. The line as read from the file is available using the 
  4901. GetFileLineBeingProcessed() call. 
  4902.  
  4903. The returned line has been stripped of leading and trailing whitespace. This 
  4904. call would usually be called to remember details about a current situation 
  4905. which you may wish to report at some future stage. 
  4906.  
  4907. If using this call you may also wish to use GetInputFileNameAndLine(), see this 
  4908. section for an example of these calls in use. 
  4909.  
  4910.  
  4911. ΓòÉΓòÉΓòÉ 5.9.32. Info() ΓòÉΓòÉΓòÉ
  4912.  
  4913. Info() 
  4914.  
  4915. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4916. extensions) can be used with any operating system supported by PPWIZARD. 
  4917.  
  4918. This routine takes a single parameter which is displayed as if the #Info 
  4919. command was used. 
  4920.  
  4921.  
  4922. ΓòÉΓòÉΓòÉ 5.9.33. InputComponentLevel() ΓòÉΓòÉΓòÉ
  4923.  
  4924. InputComponentLevel() 
  4925.  
  4926. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4927. extensions) can be used with any operating system supported by PPWIZARD. 
  4928.  
  4929. This routine takes a single parameter which is the include level that you are 
  4930. interested in. The full name of the input file at that level is returned. 
  4931.  
  4932. If you don't pass any value then the current level is assumed. If you pass an 
  4933. invalid value the empty string ("") is returned. 
  4934.  
  4935. This rexx routine does a similar job to the "<?InputComponent>" special 
  4936. variable (but for any level - not just the current one). 
  4937.  
  4938. Stupid Example 
  4939.  
  4940. Simple example in which one file works out who included it and at what line: 
  4941.  
  4942.     ;--- Work out who included this file (and what line) ---
  4943.     #evaluate ParentFile  ^InputComponentLevel(<?IncludeLevel>-1)^
  4944.     #if  '<$ParentFile>' = ''
  4945.          <P>There is no parent file!
  4946.     #elseif
  4947.          #evaluate ParentLine  ^InputComponentLineLevel(<?IncludeLevel>-1)^
  4948.          <P>The parent file is: "<$ParentFile>" (line <$ParentLine>)
  4949.     #endif
  4950.  
  4951.  
  4952. ΓòÉΓòÉΓòÉ 5.9.34. InputComponentLineLevel() ΓòÉΓòÉΓòÉ
  4953.  
  4954. InputComponentLineLevel() 
  4955.  
  4956. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4957. extensions) can be used with any operating system supported by PPWIZARD. 
  4958.  
  4959. This routine takes a single parameter which is the include level that you are 
  4960. interested in. The line number being processed of the input file at that level 
  4961. is returned. 
  4962.  
  4963. If you don't pass any value then the current level is assumed. If you pass an 
  4964. invalid value the empty string ("") is returned. 
  4965.  
  4966. This rexx routine does a similar job to the "<?InputComponentLine>" special 
  4967. variable (but for any level - not just the current one). 
  4968.  
  4969. For an example of how it could be used have a look at the InputComponentLevel() 
  4970. routine. 
  4971.  
  4972.  
  4973. ΓòÉΓòÉΓòÉ 5.9.35. IsDebugOn() ΓòÉΓòÉΓòÉ
  4974.  
  4975. IsDebugOn() 
  4976.  
  4977. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  4978. extensions) can be used with any operating system supported by PPWIZARD. 
  4979.  
  4980. This function can be called to simply determine whether debug is on or off or 
  4981. to determine the level of user debug currently active (see DebugLevel). 
  4982.  
  4983. This function would be useful if you wished to conditionally call Debug() or 
  4984. conditionally generate html comments in your output etc. 
  4985.  
  4986. The function takes either zero or one parameters as follows: 
  4987.  
  4988.          No parameters indicates that you simply want a Y/N response to 
  4989.           whether or not debug is on (similar to "<?DebugOn>" variable). 
  4990.  
  4991.          If a parameter is supplied it should be a digit (one of 1, 2 or 3). 
  4992.           If debug is off this routine will return 0 otherwise it will return 
  4993.           the result of the supplied number anded to the value of the user bits 
  4994.           (which of course could also result in 0). 
  4995.  
  4996.           That is you can check on each bit seperately if you wish. If you 
  4997.           simply wish to tell if any user debug state is on then pass 3, if you 
  4998.           wish to check the state of one of your flags then pass it's value, a 
  4999.           return code of 0 indicates that that level of debug is not on. 
  5000.  
  5001.  
  5002. ΓòÉΓòÉΓòÉ 5.9.36. MacroGet() ΓòÉΓòÉΓòÉ
  5003.  
  5004. MacroGet() 
  5005.  
  5006. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  5007. extensions) can be used with any operating system supported by PPWIZARD. 
  5008.  
  5009. This function takes a single parameter (the name of a macro) and returns its 
  5010. contents. 
  5011.  
  5012. The macro must already exist (created by #define or #evaluate). The value of 
  5013. the macro is returned, if this contains any macros to be replaced, macro 
  5014. parameters or commands to be executed they are not replaced or executed. 
  5015.  
  5016. If you need parameter substitution you could create unique strings and use 
  5017. ReplaceString() to perform the "substitution" yourself. 
  5018.  
  5019. Note that there is also a MacroSet() routine. 
  5020.  
  5021.  
  5022. ΓòÉΓòÉΓòÉ 5.9.37. MacroSet() ΓòÉΓòÉΓòÉ
  5023.  
  5024. MacroSet() 
  5025.  
  5026. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  5027. extensions) can be used with any operating system supported by PPWIZARD. 
  5028.  
  5029. This function is used to create a macro. Note that there is also a MacroGet() 
  5030. routine. 
  5031.  
  5032. The function takes 2 or 3 parameters as follows: 
  5033.  
  5034.        1. Name of variable. 
  5035.  
  5036.        2. The macros value. 
  5037.  
  5038.        3. Optional parameter, pass 'Y' if its OK to redefine the macro. 
  5039.  
  5040.  
  5041. ΓòÉΓòÉΓòÉ 5.9.38. PadString() ΓòÉΓòÉΓòÉ
  5042.  
  5043. PadString() 
  5044.  
  5045. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  5046. extensions) can be used with any operating system supported by PPWIZARD. 
  5047.  
  5048. This function will generate a padded string, it can pad Left, Right or Center 
  5049. the string you supply. 
  5050.  
  5051. The function takes 3 parameters: 
  5052.  
  5053.        1. The string to be padded (never truncated if wanted length too short). 
  5054.  
  5055.        2. The length of the new string. 
  5056.  
  5057.        3. A single character (for Left, Right or Center). 
  5058.  
  5059.  
  5060. ΓòÉΓòÉΓòÉ 5.9.39. ProcessNext() ΓòÉΓòÉΓòÉ
  5061.  
  5062. ProcessNext() 
  5063.  
  5064. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  5065. extensions) can be used with any operating system supported by PPWIZARD. 
  5066.  
  5067. PPWIZARD  macros utilize a buffer to hold lines that they generate, these are 
  5068. read before the file is accessed. This function allows you to add data to be 
  5069. processed next. 
  5070.  
  5071. The function takes a single parameter which is the line or lines (for multiple 
  5072. lines they should separated with a newline character). 
  5073.  
  5074. This routine is handy where you may have captured some text, including 
  5075. references to macros etc and you wish to process the data where the data might 
  5076. otherwise be written directly to the output file. 
  5077.  
  5078.  
  5079. ΓòÉΓòÉΓòÉ 5.9.40. QuoteIt() ΓòÉΓòÉΓòÉ
  5080.  
  5081. QuoteIt() 
  5082.  
  5083. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  5084. extensions) can be used with any operating system supported by PPWIZARD. 
  5085.  
  5086. This function will determine a quote character that is not contained within the 
  5087. string you pass. Processing will abort if it can not do so. 
  5088.  
  5089. The function takes 2 parameters: 
  5090.  
  5091.        1. The string that you wish to quote. 
  5092.  
  5093.        2. An option list of all possible quote characters. If not supplied it 
  5094.           defaults to trying double then single quotes. 
  5095.  
  5096.  This routine is handy when a macro is passed some information and needs to 
  5097.  generate the data in a quoted format. Some languages such as HTML allow 
  5098.  information to be quoted with either a single or a double quote. 
  5099.  
  5100.  Stupid Example 
  5101.  
  5102.       #evaluate     ''  ~RxQuote=QuoteIt('AS"DF')~
  5103.       Should be double = <??RxQuote>
  5104.       #evaluate     ''  ~RxQuote=QuoteIt("AS'DF")~
  5105.       Should be single = <??RxQuote>
  5106.       #evaluate     ''  ~RxContainsBothQuotes = 'AS"' || "'DF"~
  5107.       #evaluate     ''  ~RxQuote=QuoteIt(RxContainsBothQuotes, '"' || "'^")~
  5108.       Should be '^'    = <??RxQuote>
  5109.       #evaluate     ''  ~RxQuote=QuoteIt(RxContainsBothQuotes)~   ;;Will die
  5110.  
  5111.  
  5112. ΓòÉΓòÉΓòÉ 5.9.41. ReplaceMacros() ΓòÉΓòÉΓòÉ
  5113.  
  5114. ReplaceMacros() 
  5115.  
  5116. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  5117. extensions) can be used with any operating system supported by PPWIZARD. 
  5118.  
  5119. This function takes a single parameter (the string) and will return a new 
  5120. string where all Macros and standard symbols have been replaced. 
  5121.  
  5122.  
  5123. ΓòÉΓòÉΓòÉ 5.9.42. ReplaceString() ΓòÉΓòÉΓòÉ
  5124.  
  5125. ReplaceString() 
  5126.  
  5127. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  5128. extensions) can be used with any operating system supported by PPWIZARD. 
  5129.  
  5130. This function will convert all occurances of a substring as you specify. 
  5131.  
  5132. The function takes 3 parameters as follows: 
  5133.  
  5134.        1. The string which is to be translated. 
  5135.  
  5136.        2. The FROM string. 
  5137.  
  5138.        3. The TO string. 
  5139.  
  5140.  When this routine returns the rexx variable ReplaceCount will have been 
  5141.  incremented by the number of replacements made. 
  5142.  
  5143.  Note that its faster to use BulkChar2String() to modify a whole lot of 
  5144.  characters to strings.  Of course converting single characters to other single 
  5145.  characters is better done with the rexx translate() routine. 
  5146.  
  5147.  If you need to do case insensitive changes then use the ReplaceStringCI() 
  5148.  routine. 
  5149.  
  5150.  
  5151. ΓòÉΓòÉΓòÉ 5.9.43. ReplaceStringCI() ΓòÉΓòÉΓòÉ
  5152.  
  5153. ReplaceStringCI() 
  5154.  
  5155. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  5156. extensions) can be used with any operating system supported by PPWIZARD. 
  5157.  
  5158. This function will convert all occurances of a substring as you specify. 
  5159.  
  5160. The function takes 3 parameters as follows: 
  5161.  
  5162.        1. The string which is to be translated. 
  5163.  
  5164.        2. The FROM string. 
  5165.  
  5166.        3. The TO string. 
  5167.  
  5168.  When this routine returns the rexx variable ReplaceCount will have been 
  5169.  incremented by the number of replacements made. 
  5170.  
  5171.  This routine is very similar to the ReplaceString() except that it is case 
  5172.  insensitive and that the "TO" string may contain one or more "{*}" strings 
  5173.  which will get replaced with the "FROM" string. 
  5174.  
  5175.  
  5176. ΓòÉΓòÉΓòÉ 5.9.44. ReverseArray() ΓòÉΓòÉΓòÉ
  5177.  
  5178. ReverseArray() 
  5179.  
  5180. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  5181. extensions) can be used with any operating system supported by PPWIZARD. 
  5182.  
  5183. This function is used to reverse the order of elements in an array. The "array" 
  5184. has numeric indexes with the ".0" element holding the number of elements. 
  5185.  
  5186. The function takes a single parameter which is the name of the array (without 
  5187. dot). 
  5188.  
  5189. The routine returns the number of items in the array. 
  5190.  
  5191. Silly Example 
  5192.  
  5193.     ;--- Set up the array -----------------------
  5194.     #evaluate ''               \
  5195.               ^                \
  5196.                 A.1 = "5345";  \
  5197.                 A.2 = "4123";  \
  5198.                 A.3 = "61743"; \
  5199.                 A.4 = "1678";  \
  5200.                 A.0 = 4;       \
  5201.               ^
  5202.  
  5203.     ;--- Sort array & Reverse order & display ---
  5204.     #evaluate '' ^call SortArray "A"^
  5205.     #evaluate '' ^call ReverseArray  "A"^
  5206.     #evaluate '' ^do I = 1 to A.0; say a.i; end;^
  5207.  
  5208.  
  5209. ΓòÉΓòÉΓòÉ 5.9.45. RexGetTmpFileName() ΓòÉΓòÉΓòÉ
  5210.  
  5211. RexGetTmpFileName() 
  5212.  
  5213. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  5214. extensions) can be used with any operating system supported by PPWIZARD. 
  5215.  
  5216. This function returns the name of of currently non-existing file which can be 
  5217. used as a temporary file. 
  5218.  
  5219. If you want some control over the name of the file then you may pass a single 
  5220. parameter which is a filename with '?' in any positions where a "random" digit 
  5221. can be placed (example "IMP_????.TMP"). 
  5222.  
  5223.  
  5224. ΓòÉΓòÉΓòÉ 5.9.46. SetEnv() ΓòÉΓòÉΓòÉ
  5225.  
  5226. SetEnv() 
  5227.  
  5228. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  5229. extensions) can be used with any operating system supported by PPWIZARD. 
  5230.  
  5231. This function takes two parameters as follows: 
  5232.  
  5233.        1. The name of the environment variable. 
  5234.        2. The new value ("" to delete it). 
  5235.  
  5236.  The return value is the original value of the environment variable or "" if it 
  5237.  did not exist. 
  5238.  
  5239.  This command may be useful to pass information to any filters you may have set 
  5240.  up (with /FilterInput or /FilterOutput). 
  5241.  
  5242.  
  5243. ΓòÉΓòÉΓòÉ 5.9.47. SetId() ΓòÉΓòÉΓòÉ
  5244.  
  5245. SetId() 
  5246.  
  5247. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  5248. extensions) can be used with any operating system supported by PPWIZARD. 
  5249.  
  5250. This function is useful if you wish to ensure that when GetId() is called a 
  5251. specific value for an ID is used. An example of where this might be useful is 
  5252. if you have external entry points into a set of generated html pages. You 
  5253. normally would not care what they are called as long as all the links work, 
  5254. however as soon as you wish externally generated html to link to specific pages 
  5255. you must do something to ensure that the links name does not change. 
  5256.  
  5257. The function takes 3 parameters as follows: 
  5258.  
  5259.        1. A handle that was previously prepared with GetIdPrepare(). 
  5260.  
  5261.        2. The value (KEY) for which you are specifying an ID This is case 
  5262.           sensitive, to make case insensitive simply convert your value to 
  5263.           either upper or lower case before calling this routine. 
  5264.  
  5265.           There is one situation where you may wish to pass a empty key ('') 
  5266.           and that is when you specified unique ID mode on GetIdPrepare(). You 
  5267.           would do this to pass an ID that you never want returned by GetId(). 
  5268.  
  5269.        3. The ID you wish to give to the value (KEY). Note that this is not 
  5270.           validated in any way. It is up to you to ensure its correct. 
  5271.  
  5272.  Example 
  5273.  
  5274.       #evaluate ''   ^call GetIdPrepare 'PPW'^
  5275.       #evaluate ''   ^call SetId 'PPW', '#define', "HashDef"^       ;;Set preferred ID
  5276.       #evaluate ''   ^say GetId('PPW', 'MAXCHARS', 'define')^
  5277.       #evaluate ''   ^say GetId('PPW', 'MAXCHARS', '#define')^
  5278.  
  5279.  
  5280. ΓòÉΓòÉΓòÉ 5.9.48. SortArray() ΓòÉΓòÉΓòÉ
  5281.  
  5282. SortArray() 
  5283.  
  5284. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  5285. extensions) can be used with any operating system supported by PPWIZARD. 
  5286.  
  5287. This function is used to sort a rexx array. The "array" has numeric indexes 
  5288. with the ".0" element holding the number of elements. The array can hold 
  5289. numbers or strings. 
  5290.  
  5291. The sort is always ascending. You can use the ReverseArray() routine if 
  5292. required. 
  5293.  
  5294. The function takes 1 or more parameters as follows: 
  5295.  
  5296.        1. The name of the array (don't include the dot). 
  5297.  
  5298.        2. If you wish to sort only over specific columns then the starting 
  5299.           column number (first column is 1). 
  5300.  
  5301.        3. If the optional starting column was specified then this specifies the 
  5302.           ending column. If not specified then the rest of the string is used. 
  5303.  
  5304.        4. This is an optional parameter. Do you want a strict compare? If you 
  5305.           do then pass 'Y'. A strict compare does not ignore leading and 
  5306.           trailing whitespace, however it won't correctly sort numbers. 
  5307.  
  5308.  The routine returns the number of items in the array. 
  5309.  
  5310.  If you are sorting a very large array with a fixed known name then you might 
  5311.  wish to have a look at the faster and more powerful PPWSORT.H header file. 
  5312.  
  5313.  Silly Example 
  5314.  
  5315.       ;--- Set up the array ------------------------
  5316.       #evaluate ''               \
  5317.                 ^                \
  5318.                   A.1 = "ASDFG"; \
  5319.                   A.2 = "4123";  \
  5320.                   A.3 = "61743"; \
  5321.                   A.4 = "1678";  \
  5322.                   A.0 = 4;       \
  5323.                 ^
  5324.  
  5325.       ;--- Sort array & display --------------------
  5326.       #evaluate '' ^call SortArray "A"^
  5327.       #evaluate '' ^do I = 1 to A.0; say '"'a.i'"'; end; say ''^
  5328.  
  5329.       ;--- Sort array (start column 3) & display ---
  5330.       #evaluate '' ^call SortArray "A", 3^
  5331.       #evaluate '' ^do I = 1 to A.0; say '"'a.i'"'; end;
  5332.  
  5333.  
  5334. ΓòÉΓòÉΓòÉ 5.9.49. Summary() ΓòÉΓòÉΓòÉ
  5335.  
  5336. Summary() 
  5337.  
  5338. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  5339. extensions) can be used with any operating system supported by PPWIZARD. 
  5340.  
  5341. This function can be called to add (or remove) details on the displayed 
  5342. summaries. 
  5343.  
  5344. The function takes parameters as follows: 
  5345.  
  5346.        1. The text for the left hand side (before ':'). 
  5347.  
  5348.        2. The text for the right hand side (after ':'). 
  5349.  
  5350.        3. Type of summary line as follows: 
  5351.  
  5352.               To see the details on this build's summary only then pass "" (or 
  5353.                anything other than valid values shown below). 
  5354.  
  5355.               To see the details on this build and all future build's (other 
  5356.                files) summaries then pass "A" or "ALL". 
  5357.  
  5358.               To see the details on the overall summary for all builds then 
  5359.                pass "O" or "OVERALL". 
  5360.  
  5361.               To drop summary details whether user or system generated pass 
  5362.                "D" or "DROP", in which case parameter 2 is ignored. The text in 
  5363.                parameter 1 must EXACTLY match that in a summary line. 
  5364.  
  5365.  Example 
  5366.  
  5367.       ;--- Don't want to see operating system version ---
  5368.       #evaluate "" "call Summary 'Operating Syst',, 'D'"
  5369.  
  5370.       ;--- Add a summary line to this build -------------
  5371.       #evaluate "" "call Summary 'Left', 'Right'"
  5372.  
  5373.  
  5374. ΓòÉΓòÉΓòÉ 5.9.50. ToLowerCase() ΓòÉΓòÉΓòÉ
  5375.  
  5376. ToLowerCase() 
  5377.  
  5378. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  5379. extensions) can be used with any operating system supported by PPWIZARD. 
  5380.  
  5381. This function takes a single parameter and returns it in lower case. 
  5382.  
  5383. Note that there is no PPWIZARD "upper case" case routine as the standard rexx 
  5384. "translate()" routine with a single parameter does this nicely. 
  5385.  
  5386.  
  5387. ΓòÉΓòÉΓòÉ 5.9.51. UrlDecode() ΓòÉΓòÉΓòÉ
  5388.  
  5389. UrlDecode() 
  5390.  
  5391. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  5392. extensions) can be used with any operating system supported by PPWIZARD. 
  5393.  
  5394. This function can be called to convert a string (encoded URL) back into its 
  5395. plain text format.  The decoded string is returned. 
  5396.  
  5397. The parameters are as follows: 
  5398.  
  5399.        1. Input String 
  5400.           This is the string which is to be decoded. 
  5401.  
  5402.        2. Mode 
  5403.           Normally occurances of '+' are replaced with spaces. Pass "LEAVE+" to 
  5404.           not handle the plus characters. 
  5405.  
  5406.  
  5407. ΓòÉΓòÉΓòÉ 5.9.52. UrlEncode() ΓòÉΓòÉΓòÉ
  5408.  
  5409. UrlEncode() 
  5410.  
  5411. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  5412. extensions) can be used with any operating system supported by PPWIZARD. 
  5413.  
  5414. This function can be called to convert a string into a valid format for use in 
  5415. a URL. Characters such as '#' are converted to codes as they have special 
  5416. meanings when found within a URL. The new encoded string is returned. This 
  5417. routine should eliminate the need for having to see encoded URLs in your source 
  5418. code. 
  5419.  
  5420. The parameters are as follows: 
  5421.  
  5422.        1. Input String 
  5423.           This is the string which is to be encoded. 
  5424.  
  5425.        2. Mode 
  5426.  
  5427.               EncodeAll 
  5428.                All characters in the input string are encoded, so that it can 
  5429.                be called as a poor man's encryption scheme. It can hide stuff 
  5430.                (at least from casual browsing) in plain html code etc. A space 
  5431.                in not encoded as a plus. 
  5432.  
  5433.               To% 
  5434.                You need to supply a 3rd parameter which is a list of all 
  5435.                characters that you would like to encode. A space in not encoded 
  5436.                as a plus. 
  5437.  
  5438.               ? 
  5439.                If you can tell me a scheme that is required then let me know 
  5440.                and I can add it... 
  5441.  
  5442.        3. Mode Dependent Parameters 
  5443.           There may be one or more extra parameters depending on the mode. 
  5444.  
  5445.  Example 
  5446.  
  5447.       #evaluate 'HiddenText'   ^UrlEncode("Password", "EncodeAll")^
  5448.  
  5449.  
  5450. ΓòÉΓòÉΓòÉ 5.9.53. Warning() ΓòÉΓòÉΓòÉ
  5451.  
  5452. Warning() 
  5453.  
  5454. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  5455. extensions) can be used with any operating system supported by PPWIZARD. 
  5456.  
  5457. This routine is probably most useful in #import filter code and takes a two 
  5458. parameters. The first parameter is the message ID and the second is the message 
  5459. text, see the #warning command for more details. 
  5460.  
  5461. The passed warning message will be displayed. 
  5462.  
  5463.  
  5464. ΓòÉΓòÉΓòÉ 5.9.54. WriteLineToTmpImportFile() ΓòÉΓòÉΓòÉ
  5465.  
  5466. WriteLineToTmpImportFile() 
  5467.  
  5468. This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD 
  5469. extensions) can be used with any operating system supported by PPWIZARD. 
  5470.  
  5471. This function takes a single parameter and has no return code (on failure 
  5472. PPWIZARD will terminate). It must only be called while #Import is being 
  5473. processed. 
  5474.  
  5475. You may pass one or more lines of data which will be written to the temporary 
  5476. file that pass one of an import generates. 
  5477.  
  5478. To indicate the end of a line the Linefeed character (decimal 10) should be 
  5479. used the actual characters written to the file are determined by the /CrLf 
  5480. state. 
  5481.  
  5482. For an example have a look at a complex import example. 
  5483.  
  5484.  
  5485. ΓòÉΓòÉΓòÉ 5.9.55. _filespec() ΓòÉΓòÉΓòÉ
  5486.  
  5487. _filespec() 
  5488.  
  5489. This is a rexx function provided by PPWIZARD. This routine is named similar to 
  5490. an OS/2 specific call with a similar purpose, this PPWIZARD version works in 
  5491. all operating systems supported by PPWIZARD. 
  5492.  
  5493. This function takes two parameters as follows: 
  5494.  
  5495.        1. The part of the filename to extract. Valid are (note you are also 
  5496.           allowed to passed only the 1st character of each command): 
  5497.  
  5498.               drive    - Drive (example 'C:') 
  5499.               path     - Path  (example '\OS2\') 
  5500.               name     - Shortname (example 'XCOPY.EXE') 
  5501.               location   - Location (example 'C:\OS2\') 
  5502.               extn     - Extension (example 'EXE') 
  5503.               withoutextn - No extension (example 'C:\OS2\XCOPY') 
  5504.  
  5505.        2. The name of the file. 
  5506.  
  5507.  The return value is the extracted component you requested. It is important to 
  5508.  note that a partial filename is not converted to its full name before 
  5509.  extraction, the part is extracted from what you supply. It is also assumed 
  5510.  that the filename is of a valid format. 
  5511.  
  5512.  Example 
  5513.  
  5514.       ;--- Capture some HTML information ---
  5515.       #evaluate  ShortNameHtml  ^_filespec('name', '<?OutputFile>')^
  5516.  
  5517.  
  5518. ΓòÉΓòÉΓòÉ 5.9.56. _SysFileDelete() ΓòÉΓòÉΓòÉ
  5519.  
  5520. _SysFileDelete() 
  5521.  
  5522. This is a rexx function provided by PPWIZARD. This routine is named similar to 
  5523. an OS/2 specific call with a similar purpose, this PPWIZARD version works in 
  5524. all operating systems supported by PPWIZARD. 
  5525.  
  5526. This function takes a single parameter which is the filename to delete. This 
  5527. routine returns a non-zero return code on error. 
  5528.  
  5529.  
  5530. ΓòÉΓòÉΓòÉ 5.9.57. _SysFileTree() ΓòÉΓòÉΓòÉ
  5531.  
  5532. _SysFileTree() 
  5533.  
  5534. This is a rexx function provided by PPWIZARD. This routine is named similar to 
  5535. an OS/2 specific call with a similar purpose, this PPWIZARD version works in 
  5536. all operating systems supported by PPWIZARD. 
  5537.  
  5538. This function takes two parameters as follows: 
  5539.  
  5540.        1. The name of a file or directory to look for (normally containing 
  5541.           wildcard characters appropriate to the operating system being used). 
  5542.  
  5543.           In linux specify a directory name with a terminating slash to capture 
  5544.           all files or subdirectories in that directory. 
  5545.  
  5546.        2. The name of a rexx stem (array) to place the list of matching files 
  5547.           (example "Files"). On return "Files.0" contains the number of files, 
  5548.           "Files.1" contains the first filename etc. 
  5549.  
  5550.        3. List of options, supported are: 
  5551.  
  5552.               D - Directories only. 
  5553.               F - Files only (default). 
  5554.               S - Follow subdirectories. 
  5555.  
  5556.  If successful a return code of 0 is returned. The contents of the "array" may 
  5557.  not be valid if an error occurred so always either check the return code or 
  5558.  preset the ".0" element to 0 before making the call. 
  5559.  
  5560.  The full (absolute) name of files is always returned, however the names of 
  5561.  directories may be absolute or relative depending on what you passed as the 
  5562.  first parameter to this routine. 
  5563.  
  5564.  
  5565. ΓòÉΓòÉΓòÉ 5.9.58. _SysSearchPath() ΓòÉΓòÉΓòÉ
  5566.  
  5567. _SysSearchPath() 
  5568.  
  5569. This is a rexx function provided by PPWIZARD. This routine is named similar to 
  5570. an OS/2 specific call with a similar purpose, this PPWIZARD version works in 
  5571. all operating systems supported by PPWIZARD. 
  5572.  
  5573. This function takes two parameters as follows: 
  5574.  
  5575.        1. The name of an environment variable which contains a sequence of 
  5576.           directories to be searched (such as "PATH"). 
  5577.  
  5578.           Unix unix directories should be separated by ':', for all other 
  5579.           operating systems the ';' character should be used. 
  5580.  
  5581.        2. The file to be searched for. 
  5582.  
  5583.  The return value is the full name of the file or '' if not found. 
  5584.  
  5585.  
  5586. ΓòÉΓòÉΓòÉ 6. Dependancies ΓòÉΓòÉΓòÉ
  5587.  
  5588. Dependancies 
  5589.  
  5590. If you know what a make file does then this is basically the functionality 
  5591. PPWIZARD is trying to supply.  Once you have built your output files you don't 
  5592. need to rebuild them unless you modify one of your source files.  PPWIZARD 
  5593. actually does a very much better job than any make file based process. 
  5594.  
  5595. Lets consider a very complicated example where: 
  5596.  
  5597.        1. The source file is called "INPUT.IT". 
  5598.  
  5599.        2. It #includes "MACROS.IH". 
  5600.  
  5601.        3. For some stupid reason it reads in line one of "CONFIG.SYS". 
  5602.  
  5603.        4. It creates "OUTPUT.OUT" and "ALSO.OUT". 
  5604.  
  5605.        5. You have many other ".IT" files with their own dependancies. 
  5606.  
  5607.  The whole process might take a while.  You really only want to preprocess the 
  5608.  above 3 input files to produce the 2 output files if you need to. PPWIZARD 
  5609.  stores information in a dependancy file for each compile which will allow it 
  5610.  to check whether a build is required or not.  It will detect if any input or 
  5611.  output files have changed or if they are missing and begin to rebuild the 
  5612.  output. 
  5613.  
  5614.  To conditionally make your ".IT" files you could use: 
  5615.  
  5616.       ppwizard.cmd  *.it  /output:out\*.htm /CrLf /DependsOn:Depends\*.dep
  5617.  
  5618.  This command says to make "*.IT" and put all output into the "OUT" directory 
  5619.  and creates a "DEPENDS" directory and places dependancy information in this 
  5620.  directory. 
  5621.  
  5622.  Most dependancies can be handled by the preprocessor but sometimes you need to 
  5623.  help identify the input and output files.  For example you probably used a 
  5624.  rexx linein() command to read from "CONFIG.SYS", you will need to use the 
  5625.  #DependsOn command to indicate this one. In a similar manner the example 
  5626.  generates 2 output files, if you used the rexx lineout() command to create 
  5627.  these then you would again need to use the #DependsOn command to indicate this 
  5628.  output dependancy. 
  5629.  
  5630.  
  5631. ΓòÉΓòÉΓòÉ 7. Commands ΓòÉΓòÉΓòÉ
  5632.  
  5633. Commands 
  5634.  
  5635. The following commands are available to you when you use the PPWIZARD.CMD 
  5636. Preprocessor: 
  5637.  
  5638.          #AsIs 
  5639.          #AutoTag 
  5640.          #AutoTagClear 
  5641.          #AutoTagState 
  5642.          #debug 
  5643.          #define[+] 
  5644.          #DefineRexx[+] 
  5645.          #DependsOn 
  5646.          #ElseIf 
  5647.          #EndIf 
  5648.          #EOF 
  5649.          #error 
  5650.          #evaluate[+] 
  5651.          #if 
  5652.          #IfDef 
  5653.          #IfNDef 
  5654.          #import 
  5655.          #include 
  5656.          #Info 
  5657.          #MacroSpace 
  5658.          #OneLine 
  5659.          #OnExit 
  5660.          #option 
  5661.          #output 
  5662.          #require 
  5663.          #RexxVar 
  5664.          #UnDef 
  5665.          #warning 
  5666.  
  5667.  The following commands allow you to perform PPWIZARD looping: 
  5668.  
  5669.          #{ 
  5670.          #} 
  5671.          #break 
  5672.          #continue 
  5673.  
  5674.  
  5675. ΓòÉΓòÉΓòÉ 7.1. #{ ΓòÉΓòÉΓòÉ
  5676.  
  5677. #{ 
  5678.  
  5679. This command is used to define the start of a loop which ends with the "#}" 
  5680. statement. 
  5681.  
  5682. You may use the #continue to restart at the top of the loop and #break will 
  5683. cause you to exit the loop. 
  5684.  
  5685. Restrictions 
  5686.  
  5687.        1. Both the start and end of a loop must occur within the same input 
  5688.           file. 
  5689.  
  5690.        2. Loops can't be nested (within a single file). 
  5691.  
  5692.        3. Since PPWIZARD loads the whole loop without processing lines in 
  5693.           between the affect of any intermediate "HashPrefix" option is ignored 
  5694.           for the purposes of finding the end of the loop. 
  5695.  
  5696.  Example 1 - Loop 12 Times 
  5697.  
  5698.       ;--- Output 12 text lines ---------------------------------------------------
  5699.       #RexxVar Count = 1              ;;"#RexxVar" is fastest way to set or update a rexx variable
  5700.       #{
  5701.          ;--- Output one line -----------------------------------------------------
  5702.          <B>From Loop #<??Count></B><BR>
  5703.  
  5704.          ;--- Only do 12 times ----------------------------------------------------
  5705.          #RexxVar Count + 1
  5706.          #if [<??Count> > 12]         ;;Note the square brackets to improve performance (since simple test)
  5707.              #break                   ;;Now done 12 times
  5708.          #endif
  5709.       #}
  5710.       <HR>                            ;;Break sends us here
  5711.  
  5712.  Example 2 - Read File Until End 
  5713.  
  5714.  This example is used to load a list of languages and to create a directory for 
  5715.  each ones generated html.  The languages file looks like: 
  5716.  
  5717.       en     ;;English
  5718.       it     ;;Italian
  5719.       fr     ;;French
  5720.  
  5721.  The code to read the above file and create the directories is: 
  5722.  
  5723.       ;--- Code written for OS/2 so gain access to rexx extensions ----------------
  5724.       #evaluate "" "call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'"
  5725.       #evaluate "" "call SysLoadFuncs"
  5726.  
  5727.       ;--- Define some directories ------------------------------------------------
  5728.       #define site.root            C:\sitetest
  5729.       #define site.out.dir         <$site.root>\html     ;;output root
  5730.  
  5731.       ;--- Make required base directories -----------------------------------------
  5732.       #evaluate "" "MkDirRc=SysMkDir('<$site.root>')"
  5733.       #evaluate "" "MkDirRc=SysMkDir('<$site.out.dir>')"
  5734.  
  5735.       ;--- Make language directories ----------------------------------------------
  5736.       #define    LanguageFile   "LANG.IH"           ;;Note in this case would be more CPU efficent if rexx variable
  5737.       #DependsOn INPUT <$LanguageFile>
  5738.       #evaluate "" ^CloseFileRc = stream(<$LanguageFile>, 'c', 'close');^
  5739.       #{
  5740.          ;--- Exit on EOF ---------------------------------------------------------
  5741.          #if  lines(<$LanguageFile>) = 0
  5742.               #break
  5743.          #endif
  5744.  
  5745.          ;--- Read the language line, strip out comment and make directory --------
  5746.          #evaluate "" "MkDirRc=SysMkDir('<$site.out.dir>\' || '<?=word(linein(<$LanguageFile>), 1)>')"
  5747.       #}
  5748.       #evaluate "" ^CloseFileRc = stream(<$LanguageFile>, 'c', 'close');^
  5749.  
  5750.  
  5751. ΓòÉΓòÉΓòÉ 7.2. #} ΓòÉΓòÉΓòÉ
  5752.  
  5753. #} 
  5754.  
  5755. This command is used to define the end of a loop the start of which must also 
  5756. occur within the same input file. 
  5757.  
  5758. Please see the "#{" command for an example and more information. 
  5759.  
  5760.  
  5761. ΓòÉΓòÉΓòÉ 7.3. #AsIs ΓòÉΓòÉΓòÉ
  5762.  
  5763. #AsIs 
  5764.  
  5765. This command is frequently used to allow you to #include real working code as 
  5766. examples.  Any modifications required to get the file (or part of) to display 
  5767. "as is" occurs automatically as programmed by you. 
  5768.  
  5769. Turning on "asis" mode basically allows you to read in text without PPWIZARD 
  5770. getting in the way.  More than this is can simplify issues such as the fact 
  5771. that the viewer may not be able to display certain characters unless converted. 
  5772. For example a html viewer may have trouble with '<' characters unless they are 
  5773. converted to '<'. 
  5774.  
  5775. Turning "asis" mode on will modify a number of PPWIZARD #Options so that lines 
  5776. will get passed through "as is".  This means blank lines are kept, line comment 
  5777. and continuation is ignored and a number of other options may be modified. Use 
  5778. "#Debug" to see all that are modified. 
  5779.  
  5780. While #AsIs mode is turned on, PPWIZARD commands are still processed. This is 
  5781. fine if your examples either don't include ppwizard commands or you wish to 
  5782. conditionally include parts of the example. If you did not want this you would 
  5783. need to use the "HashPrefix" option or take some other action to prevent it. 
  5784.  
  5785. You may need to do more than this to get the effect you desire. For example to 
  5786. have have the lines appear in a HTML browser as they do in your source you will 
  5787. need to do more work (or blank lines get removed and long lines wrap etc).  The 
  5788. minimum you would require for HTML is to use <PRE> & </PRE> tags around the 
  5789. lines. 
  5790.  
  5791. Using "<PRE>" as mentioned above only handles part of your issues with a HTML 
  5792. browser, any html tags such as "<P>" will get interpreted by the browser and 
  5793. generate a new paragraph. This is fine if that was your intention however you 
  5794. probably wish to see the characters "<P>" in the browser.  You could make use 
  5795. of the "#AutoTag" or "#AsIs" autotagging facility to convert all occurrances of 
  5796. "<" to "<". 
  5797.  
  5798. Its normally more flexible to have basic autotagging such as that mentioned for 
  5799. the "<" character handled by this command and any extensions to the fundamental 
  5800. changes handled by the "#AutoTag" command.  You would also wish to check out 
  5801. the "#AutoTagClear" & "#AutoTagState" commands. 
  5802.  
  5803. There are some tricky bits that you may need to handle - such as how do you 
  5804. tell PPWIZARD where the end of the example code is.  If you are not careful any 
  5805. end of example marker you place could get autotagged in such a way that 
  5806. PPWIZARD will not recogise it! This can be tricky, to see examples of how this 
  5807. can be handled, see my "OL_DOC.DH" header file which handles examples for IPF 
  5808. and HTML examples. 
  5809.  
  5810. All AsIs tagging is performed before "#AutoTag" tagging. As mentioned earlier 
  5811. it can be difficult or impossible (in some situations) to escape out of an 
  5812. "example" mode that you set up. It will help you to remember that all 
  5813. autotagging is case sensitive and only occurs on data as it is read from a file 
  5814. (not on lines from memory/macros). If you don't get the results you expect you 
  5815. will need to use "#debug" or "/debug" to watch what occurs. In debug mode lines 
  5816. from a file are show in a similar manner to "0012:" where a line from memory 
  5817. could be shown as "####:". 
  5818.  
  5819. Like autotagging you must be very careful in the order that you tag things for 
  5820. example specifing that '<' gets replaced with '<' and then that '&' gets 
  5821. replaced with '&' is wrong as you would be tagging the '<' from the 
  5822. first replacement.  For the example given here you would need to swap the 
  5823. order, in other cases you may need to use an intermediate 'unique' string and 
  5824. convert it back as the last change. 
  5825.  
  5826. If possible try and group changes so that all single character changes are 
  5827. together this allows PPWIZARD to perform faster replacments as it can make good 
  5828. use of the BulkChar2String() routine. 
  5829.  
  5830. Syntax 
  5831.  
  5832.     [WhiteSpace]#AsIs ["]SETUP["]  ["]NAME["]         OR
  5833.     [WhiteSpace]#AsIs ["]OFF["]                       OR
  5834.     [WhiteSpace]#AsIs ["]ON["]   [["]NAME1["]  ...]>
  5835.  
  5836. The "SETUP" command is used to store all currently defined "#AutoTag" commands 
  5837. under the "NAME" you supply. The existing AutoTags are cleared. 
  5838.  
  5839. The "OnOrOffCommand" specifies whether or not "asis" mode is on. 
  5840.  
  5841. When turning #AsIs mode on you may specify one or more named sets of tags that 
  5842. were previously set up with "SETUP". 
  5843.  
  5844. Example - SETUP 
  5845.  
  5846.     ;--- Setup minimum tagging for IPF lines ---------------------------------
  5847.     #AutoTagState +                        ;;Lets not effect current tags
  5848.     #AutoTag      "&"   "&."
  5849.     #AutoTag      ":"   "&colon."
  5850.     #AsIs         SETUP IpfAsIsChanges     ;;Copy tags and clear (name tags "IpfAsIsChanges")
  5851.     #AutoTagState -                        ;;Restore Original AutoTag state
  5852.  
  5853. Example - Including Example File 
  5854.  
  5855. The following is an example of a macro which will display an example file with 
  5856. a nice border and title (in a table).  The included file does not contain 
  5857. conditional commands etc (or if it does we want to see it as part of the 
  5858. example).  This is one example of a macro you could use: 
  5859.  
  5860.     #define    IncludeExampleFile                    \
  5861.                <BR><TABLE BORDER=5 CELLSPACING=5>    \
  5862.                <TR>                                  \
  5863.                <TH ALIGN=LEFT>{$TEXT}                \
  5864.                </TR>                                 \
  5865.                <TR><TH ALIGN=LEFT>                   \
  5866.                <PRE>                                 \
  5867.                <FONT size=-1>                        \
  5868.                #AsIs       ON HtmlAsIsChanges        \
  5869.                #AutoTag    ON                        \
  5870.                #option     PUSH HashPrefix="#$@!"    \
  5871.                #$@!include "{$FILE}"                 \
  5872.                #$@!option  POP   ;;Restore Prefix    \
  5873.                #AutoTag    OFF                       \
  5874.                #AsIs       OFF                       \
  5875.                </FONT>                               \
  5876.                </PRE>                                \
  5877.                </TR>                                 \
  5878.                </TABLE>
  5879.  
  5880. Prior to using the above macro we need to have defined up the "HtmlAsIsChanges" 
  5881. tagging.  This could have been done as follows: 
  5882.  
  5883.     #Autotagstate +                     ;;Lets not stuff up any existing autotags
  5884.     #AutoTag '<' '<'                 ;;Browser may not display text unless '<' etc changed.
  5885.     #AutoTag '>' '>'
  5886.     #AsIs    SETUP     HtmlAsIsChanges  ;;Remember tagging we wish to take place
  5887.     #Autotagstate -                     ;;Restore previous autotag state
  5888.  
  5889. Now lets use the above macro (and do some automatic tagging): 
  5890.  
  5891.     #AutoTagClear
  5892.     #AutoTag  "REM "    '<A HREF="rem.htm">REM</A> '
  5893.     #AutoTag  /SET /    *<A HREF="set.htm">SET</A> *
  5894.     #AutoTag  "set "    ~<A HREF="set.htm">set</A> ~
  5895.  
  5896.     <$IncludeExampleFile FILE="C:\AUTOEXEC.BAT" TEXT='Example file "C:\AUTOEXEC.BAT"'>
  5897.  
  5898. Note that in the example above all existing autotags were cleared before 
  5899. setting our own.  This is restrictive and intelligent use of the 
  5900. "#AutoTagState" command will be more useful. 
  5901.  
  5902.  
  5903. ΓòÉΓòÉΓòÉ 7.4. #AutoTag ΓòÉΓòÉΓòÉ
  5904.  
  5905. #AutoTag 
  5906.  
  5907. This command allows you to automatically modify text.  This is mainly handly 
  5908. when "#AsIs" mode is on and you are including text which you don't wish to 
  5909. modify (such as a real live working module you wish to use as an example). 
  5910.  
  5911. By default the search operation is case sensitive and a simple textual 
  5912. replacement occurs. There are other options such as case insensitive 
  5913. replacements that you can set using the AtChangeType option. 
  5914.  
  5915. When used with the "#AsIs" command  you can include real working code as 
  5916. examples and link parts of this working example to your explanations. 
  5917.  
  5918. Automatic tagging is not recommended for general use as it can greatly decrease 
  5919. performance of this program. 
  5920.  
  5921. AutoTag definitions are applied to lines in the order of declaration in a 
  5922. single pass.  This means that you can make use of common "macro" like tags but 
  5923. they must be defined later than all references.  If AutoTags are used while 
  5924. "#AsIs" mode is off then it can generate references to #define variables and 
  5925. they will be expanded. 
  5926.  
  5927. You can temporarily hide or extend the existing autotag list with the 
  5928. "#AutoTagState" command. You can clear all or some AutoTags with 
  5929. "#AutoTagClear". 
  5930.  
  5931. Only lines that come directly from a file are tagged. Macro contents are safe. 
  5932. Autotagging occurs after any required "#AsIs" tagging. 
  5933.  
  5934. The parameters shown below do not have macros expanded before this command 
  5935. processes them.  This ensures that complex macros can be handled.  The 
  5936. replacement will occur after the autotag text has been replaced. 
  5937.  
  5938. Syntax #1 
  5939.  
  5940.     [WhiteSpace]#AutoTag  ["]OnOrOffCommand["]
  5941.  
  5942. This form of the command turns on or off the automatic tagging of text.  The 
  5943. "OnOrOffCommand" parameter should be "+", "ON" or "YES" to keep leading 
  5944. whitespace otherwise use "-", "OFF" or "NO". 
  5945.  
  5946. Syntax #2 
  5947.  
  5948.     [WhiteSpace]#AutoTag  ["]BeforeText["] [ ["]AfterText["]  [#Slot]>]>
  5949.  
  5950. The "BeforeText" is translated into "AfterText".  Note that the "AfterText" can 
  5951. contain the "BeforeText" and both can contain absolutely any characters.  If 
  5952. the "AfterText" parameter is missing (not empty) then the first autotag for 
  5953. "BeforeText" is deleted.  Note that "AfterText" can contain the string "{$AT}" 
  5954. which will get replaced with the value of "BeforeText". 
  5955.  
  5956. The optional "Slot" parameter can be used to adjust the ordering of the tag. 
  5957. Normally the new tag is placed after all existing ones, to make it first 
  5958. specify "#1". A tag of "#2" would ensure its the second change etc. 
  5959.  
  5960. Note that its perfectly legal and in some cases may be required that you 
  5961. specify the same "BeforeText" more than once. 
  5962.  
  5963. When "#AsIs" mode is on you need to be very careful about what you use as 
  5964. replacement text, for example if you wish to see a '<' character you will 
  5965. actually need to use '<' instead! 
  5966.  
  5967. Example 
  5968.  
  5969. In the following example we are including "C:\AUTOEXEC.BAT" and wish to create 
  5970. hypertext links from the "REM" command to "rem.htm" and from the "SET" command 
  5971. to "set.htm".  Note that I expect  my source to contain "set" or "SET" but not 
  5972. "SeT" etc.  Also note that to eliminate the chance (in this example certainty) 
  5973. of clashes with future #defines I use the text ">$<" to split up the file 
  5974. "set.htm". Also note that I look for "SET" and not "SET ", this is silly as it 
  5975. would also match on "SETTLE" or other similar text and not just "SET" commands 
  5976. which I know need at least one space. 
  5977.  
  5978.     #AutoTagClear
  5979.     #AutoTag  "REM "    '<A HREF="rem.htm">REM</A> '
  5980.     #AutoTag  /SET/    *<A HREF="s><?Dollar><et.htm">SET</A>*
  5981.     #AutoTag  "set"    ~<A HREF="s><?Dollar><et.htm">set</A>~
  5982.     #AutoTag  "><?Dollar><"    ""
  5983.     #AutoTag  ON
  5984.     <$IncludeExampleFile FILE="C:\AUTOEXEC.BAT" TEXT='Example file "C:\AUTOEXEC.BAT"'>
  5985.     #AutoTag  OFF
  5986.  
  5987.  
  5988. ΓòÉΓòÉΓòÉ 7.5. #AutoTagClear ΓòÉΓòÉΓòÉ
  5989.  
  5990. #AutoTagClear 
  5991.  
  5992. This command allows you to clear out unwanted #AutoTags that you probably used 
  5993. to tag a previous sample so as not to interfere with the next one. 
  5994.  
  5995. By default only the current autotag state is cleared so it is possible to be 
  5996. selective about the clearing of tags with intelligent use of the #AutoTagState 
  5997. command. 
  5998.  
  5999. Syntax 
  6000.  
  6001.     [WhiteSpace]#AutoTagClear  [["]ALL["] ]>
  6002.  
  6003. If the literal value "ALL" is specified the autotag state is cleared as well as 
  6004. all tags.  The default is to only clear autotags defined in the current state. 
  6005.  
  6006.  
  6007. ΓòÉΓòÉΓòÉ 7.6. #AutoTagState ΓòÉΓòÉΓòÉ
  6008.  
  6009. #AutoTagState 
  6010.  
  6011. This command can be used to create autotag "pools" which can be selectively 
  6012. used and cleared without affecting any previously defined pools.  This allows a 
  6013. self contained macro to create, use and clear autotags and still restore the 
  6014. state so as not to affect the rest of the system. 
  6015.  
  6016. This command also saves and restores whether or not tagging was on. 
  6017.  
  6018. A common use of this command is to temporarily hide all autotags, another is to 
  6019. make a temporary copy then delete one or more tags, perform some tagging and 
  6020. then restore the original state. 
  6021.  
  6022. Syntax 
  6023.  
  6024.     [WhiteSpace]#AutoTagState  ["]Name["]                               OR
  6025.     [WhiteSpace]#AutoTagState  ["]Mode["]   [["]REMEMBER["]]>            OR
  6026.     [WhiteSpace]#AutoTagState  ["]+["]       ["]REMEMBER["]|["]Name["]  ...
  6027.  
  6028. It is possible to name a state at any time.  When you increment the state the 
  6029. name will be remembered as the "Name" you supply.  When incrementing to a new 
  6030. state you can copy tags from one or more named states. 
  6031.  
  6032. The "Mode" parameter should be either: 
  6033.  
  6034.        1. "+" 
  6035.           This saves the current state.  By default the new state has no tags 
  6036.           available.  If the literal value "REMEMBER" is also used then the new 
  6037.           state has access to all tags available in the previous state.  You 
  6038.           can also specify one or more previously defined state names to copy 
  6039.           their tags. 
  6040.  
  6041.           Note that if #AutoTagClear is used (without 'ALL') in a state where 
  6042.           "REMEMBER" was also used then this will only clear tags that you have 
  6043.           defined in the current state (not all tags available in that state). 
  6044.  
  6045.        2. "-" 
  6046.           This restores the previous state.  If the literal value "REMEMBER" is 
  6047.           also used then the new (previous) state's tags are replaced with 
  6048.           those currently available. 
  6049.  
  6050.  EXAMPLE 
  6051.  
  6052.       #Autotagstate FirstState                   ;;Name this state
  6053.       #AutoTag      "1"   "one"                  ;;Create a tag
  6054.       #Autotagstate +                            ;;Create new state (no tags available)
  6055.       #Autotagstate SecondState                  ;;Name this state
  6056.       #AutoTag      "2"   "two"                  ;;Create a tag
  6057.       #Autotagstate +  REMEMBER                  ;;Create new state (get access to last states tags)
  6058.       #AutoTag      "2"                          ;;Delete this tag
  6059.       #Autotagstate +                            ;;Create new state (no tags available)
  6060.       #Autotagstate +  FirstState 'SecondState'  ;;Create new state (copy tags from 2 states)
  6061.       #Autotagstate -  REMEMBER                  ;;Go back to previous state (overwriting any tags it might have)
  6062.       #Autotagstate -                            ;;Go back one state (keep that states tags)
  6063.       #Autotagstate -
  6064.       #Autotagstate -
  6065.  
  6066.  
  6067. ΓòÉΓòÉΓòÉ 7.7. #Break ΓòÉΓòÉΓòÉ
  6068.  
  6069. #Break 
  6070.  
  6071. This command is used to exit a PPWIZARD loop (similar to rexx 'leave' loop 
  6072. instruction). 
  6073.  
  6074. Please see the "#{" command for an example and more information. 
  6075.  
  6076.  
  6077. ΓòÉΓòÉΓòÉ 7.8. #Continue ΓòÉΓòÉΓòÉ
  6078.  
  6079. #Continue 
  6080.  
  6081. This command is used to immediately restart a PPWIZARD loop from the top 
  6082. (similar to rexx 'iterate' loop instruction). 
  6083.  
  6084. Please see the "#{" command for an example and more information. 
  6085.  
  6086.  
  6087. ΓòÉΓòÉΓòÉ 7.9. #Debug ΓòÉΓòÉΓòÉ
  6088.  
  6089. #Debug 
  6090.  
  6091. This will turn debug mode on or off.  Debug mode is normally off but can also 
  6092. be turned on with the /debug command line switch. 
  6093.  
  6094. Note that this command will not adjust the debugging mode if the /debug switch 
  6095. was used. 
  6096.  
  6097. The output is fairly easy to understand and aims to actually teach (or help you 
  6098. to understand) certain commands (such as #import). 
  6099.  
  6100. Syntax 
  6101.  
  6102.     [WhiteSpace]#Debug  ["]OnOrOffCommand["]
  6103.  
  6104. The "OnOrOffCommand" should be "+", "ON" or "YES" to turn debug on otherwise 
  6105. use "-", "OFF" or "NO". 
  6106.  
  6107. Example 
  6108.  
  6109.     #debug on
  6110.     ...
  6111.     ...
  6112.     #debug 'no'
  6113.  
  6114.  
  6115. ΓòÉΓòÉΓòÉ 7.10. #define[+] ΓòÉΓòÉΓòÉ
  6116.  
  6117. #define[+] 
  6118.  
  6119. A #define can be used to define a value (constant) once and then refer to it 
  6120. elsewhere. It allows you to update one place and have all necessary change flow 
  6121. though to all the statements that refer to it. If the command was "#define+" 
  6122. then if a redefine of a variable occurs then this is considered to be OK and no 
  6123. warnings are generated. For more information on macros and their use please see 
  6124. the macros section. 
  6125.  
  6126. There are some situations where you may wish to use the #AutoTag facility 
  6127. instead.  The main difference is with a #define'd variable you indicate where 
  6128. the replacement will occur - if it can't do it the build fails, when using 
  6129. #AutoTags the replacement occurs automatically but it may not always come out 
  6130. the way you wish and of course no error if it "fails" (use of #defines is also 
  6131. very much faster).  I mainly use #AutoTag when I'm including real working code 
  6132. from a file and I want to created hypertext links or highlight sections.  I can 
  6133. then quickly change the example without having to worry about having to retag 
  6134. it. 
  6135.  
  6136. You should also have a look at the #evaluate command which can do things that a 
  6137. #define can't. 
  6138.  
  6139. Note that there are some extreme situations which you will not be able to wrap 
  6140. up in a #define (or at least easily). As an example of a situation which will 
  6141. be very difficult (if not impossible) would be to include a reference to a 
  6142. macro which then uses the #AsIs command, also be careful with #AutoTag. 
  6143. commands. In these situations you can use a #Include command to perform the 
  6144. textual replacement. 
  6145.  
  6146. The DefineMacroReplace option affects how this command works. 
  6147.  
  6148. Syntax 
  6149.  
  6150. The syntax of this command is different from most others as it does not accept 
  6151. quoted strings, the reason for this is to ensure that you can include 'C' 
  6152. header files with a bit of care (allowing sharing of the common header). 
  6153.  
  6154.     [WhiteSpace]#define[+] Variable  Contents
  6155.  
  6156. The "Variable" is the name of the macro and when seen in following lines will 
  6157. be replaced by the contents. If the macro you are creating contains ppwizard 
  6158. commands then you must use the line continuation characters and place each 
  6159. ppwizard command on a line of it's own. 
  6160.  
  6161. The "Contents" is basically the rest of the line and is what is placed into the 
  6162. output.  This may contain any number of mandatory or optional parameters. 
  6163.  
  6164. The line containing a #define does not itself have variables substituted.  What 
  6165. this means is that if the "Contents" contains other definitions, the values of 
  6166. these at the time of use will be used. If this is not what you wish then use 
  6167. the "#evaluate" to create the definition. 
  6168.  
  6169. You can redefine a variable if you wish. 
  6170.  
  6171. Example 1 - No Parameters Used 
  6172.  
  6173.     ;--- #define some standard stuff --------------------------------------------
  6174.     #define Img100%PureJava         <IMG SRC="graphics/java100.gif" ALT="{100% pure Java}" HSPACE=5 VSPACE=10 ALIGN=middle BORDER=0 WIDTH=100 HEIGHT=100>
  6175.     #define ImgFreeIbmVisualAgeJava <IMG                                 \
  6176.                                             SRC="graphics/vaj_free.gif"  \
  6177.                                             ALT="{Free Visual Age Java}" \
  6178.                                             HSPACE=5                     \
  6179.                                             ALIGN=middle                 \
  6180.                                             BORDER=0                     \
  6181.                                             WIDTH=88 HEIGHT=31           \
  6182.                                     >
  6183.     #define ImgBarbedWire           <P><CENTER><IMG SRC="graphics/barbwire.gif"></CENTER>
  6184.  
  6185.     ;--- Now use some #defines -------------------------------------------------
  6186.     <P>Paragraph before barbed wire.
  6187.  
  6188.     <$ImgBarbedWire>
  6189.  
  6190.     <P>Paragraph after barbed wire.
  6191.  
  6192. Example 2 - Parameters Used 
  6193.  
  6194.     ;--- Define an image -------------------------------------------------------
  6195.     #define AnImage <IMG SRC="graphics/AnImage.gif" WIDTH={$WIDTH} HEIGHT={$HEIGHT}>
  6196.  
  6197.     ;--- Refer to image twice, each with different size ------------------------
  6198.     <P>Image at Size 1 = <$AnImage WIDTH="100" HEIGHT="33">
  6199.     <P>Image at Size 2 = <$AnImage WIDTH='200' HEIGHT=|66|>
  6200.  
  6201.  
  6202.     ;--- Define an image -------------------------------------------------------
  6203.     #define AnImage2 <IMG SRC="graphics/AnImage.gif" {$All}>>
  6204.  
  6205.     ;--- Refer to the image supplying any and all parameters -------------------
  6206.     <P>Image = <$AnImage2 All=/ALT="{An Image}" WIDTH="100" HEIGHT="33"/>
  6207.  
  6208.     ;--- Refer to the image supplying NO parameters ----------------------------
  6209.     <P>Image = <$AnImage2 All="">
  6210.  
  6211. Example 3 - Contains Logic 
  6212.  
  6213.     ;--- Define a macro that can be used to include my example files -----------
  6214.     #define    IncludeExampleFile                    \
  6215.                <BR><TABLE BORDER=5 CELLSPACING=5>    \
  6216.                <TR>                                  \
  6217.                <TH ALIGN=LEFT>{$TEXT}                \
  6218.                </TR>                                 \
  6219.                <TR><TH ALIGN=LEFT>                   \
  6220.                <PRE>                                 \
  6221.                <FONT size=-1>                        \
  6222.                #AsIs    ON                           \
  6223.                #include "{$FILE}"                    \
  6224.                #AsIs    OFF                          \
  6225.                </FONT>                               \
  6226.                </PRE>                                \
  6227.                </TR>                                 \
  6228.                </TABLE>
  6229.  
  6230.     <$IncludeExampleFile FILE="Example.TXT" TEXT='Example file "EXAMPLE.TXT"'>
  6231.  
  6232. Example 4 - Default Parameters 
  6233.  
  6234.     ;--- Define a stupid macro which defaults some parameters ------------------
  6235.     #define    AMacro /{Parm1}/{Parm2="Default2"}/{Parm3=+Default3+}/
  6236.  
  6237.     ;--- Use the macro ---------------------------------------------------------
  6238.     <$AMacro Parm1='Text1'>
  6239.     <$AMacro Parm1='Text1' Parm2=*Text2*>
  6240.  
  6241.  
  6242. ΓòÉΓòÉΓòÉ 7.11. #DefineRexx[+] ΓòÉΓòÉΓòÉ
  6243.  
  6244. #DefineRexx[+] 
  6245.  
  6246. This command provides a simple way to define multi line/statement rexx code 
  6247. without requiring line continuation characters. 
  6248.  
  6249. The rexx code would typically be executed at some later stage (if not 
  6250. immediately). 
  6251.  
  6252. Rather than execute the code you may wish to create a macro for later expansion 
  6253. when you use ppwizard as a rexx preprocessor. It then becomes a powerful tool 
  6254. of creating rexx code which can be used in multiple locations. 
  6255.  
  6256. You use this command to define the start and end of a block of rexx code and 
  6257. anything in between is either rexx code or a ppwizard command. The fact that 
  6258. ppwizard commands are interpreted while the block is being processed allows you 
  6259. to use useful commands such as #include or #if to selectively include or 
  6260. exclude parts of the rexx code. 
  6261.  
  6262. Each line of rexx goes through the following processing: 
  6263.  
  6264.        1. The line goes through all normal PPWIZARD processing except symbol 
  6265.           substitution. This means for example that line continuation occurs so 
  6266.           that a "line" that this command sees can actually be made up of many 
  6267.           source lines. 
  6268.  
  6269.        2. All leading and trailing whitespace is removed. 
  6270.  
  6271.        3. A trailing rexx comment if it exists is removed. 
  6272.  
  6273.        4. A trailing ';' is removed if it exists. 
  6274.  
  6275.        5. Unless you specify otherwise the line is packed and you should be 
  6276.           aware of some of the restrictions involved (described below). Packing 
  6277.           reduces the chance that the rexx interpreter you are using will 
  6278.           reject the code due to clause or line length restrictions. The 
  6279.           packing also means that you can format the code to be easier to read 
  6280.           (since you aren't worried about the extra spacing etc). 
  6281.  
  6282.        6. The line is added to any previously collected (separated with 
  6283.           "<?xRexxEos>"). This seperator string is automatically handled if the 
  6284.           rexx is executed under ppwizard control. If you generate the rexx 
  6285.           code (into the output rexx program) then the default is that it is 
  6286.           converted to a newline. 
  6287.  
  6288.           Note that the end of each rexx line is expected to be the end of a 
  6289.           rexx statement so if a rexx statement spans multiple lines you will 
  6290.           still need to use line continuation on these lines. 
  6291.  
  6292.           Note that if you combine multiple macros generated this way you must 
  6293.           seperate them with ';' as this command does not terminate the last 
  6294.           statement. 
  6295.  
  6296.  At the end of the block the complete rexx code may have symbols substituted 
  6297.  depending on how the DefineMacroReplace option is set. 
  6298.  
  6299.  Note that the last line/statement of the block will not be terminated with a 
  6300.  semicolon, if you wish to combine blocks you will need to take this into 
  6301.  account. 
  6302.  
  6303.  Syntax 
  6304.  
  6305.       [WhiteSpace]#DefineRexx[+]  [["]Variable["] ["]NOPACK["]]>
  6306.  
  6307.  If the command was "#DefineRexx+" then if a redefine of a variable occurs then 
  6308.  this is considered to be OK and no warnings are generated. 
  6309.  
  6310.  If the Variable parameter is supplied it defines the name of a #define to be 
  6311.  generated with the following lines as their contents. If no parameters are 
  6312.  supplied the rexx code block is completed. 
  6313.  
  6314.  If the Variable parameter is given as "" (empty) then the rexx code is 
  6315.  immediately executed and not saved. When code is executed immediately then any 
  6316.  macro parameters are always replaced. 
  6317.  
  6318.  The default situation is that rexx code is packed, the optional NOPACK keyword 
  6319.  allows you to prevent this. Some rexx interpreters have trouble with legal 
  6320.  rexx code when excess spaces are removed! Rather than completely disabling all 
  6321.  packing you can also make use of the AllowPack option to selectively prevent 
  6322.  the packing of certain lines. 
  6323.  
  6324.  MORE ON PACKING 
  6325.  
  6326.  The preprocessor packs well written code (by my definition!) and can fail to 
  6327.  correctly pack code where strings are appended without the use of the "||" 
  6328.  operator (as the excess spaces will be removed).  For example the following 
  6329.  statement will not create the string you expect when packed: 
  6330.  
  6331.          BothPartsCombined = 'Value:'   TheValue;
  6332.  
  6333.  The following statement is a version of the above that will work: 
  6334.  
  6335.           BothPartsCombined = 'Value:   ' || TheValue;
  6336.  
  6337.  Note that PPWIZARD may not be able to correctly pack lines that refer to macro 
  6338.  variables such as in the following: 
  6339.  
  6340.       #DefineRexx ValidateUrlR_REXX_Location
  6341.                   #Option PUSH AllowPack=NO
  6342.                   do  IncIndex = 1 to <?IncludeLevel>  ;;This line can't be packed
  6343.                   #Option POP
  6344.                      ;--- Format the input file at this level ---
  6345.                      ThisBit = _filespec('name', InputComponentLevel(IncIndex));
  6346.                      ThisBit = ThisBit || '(' || AddCommasToDecimalNumber(InputComponentLineLevel(IncIndex)) || ')';
  6347.  
  6348.                      ;--- Update location string ----------------
  6349.                      if  IncIndex = 1 then
  6350.                          UrlSourceLocation = ThisBit;
  6351.                      else
  6352.                          UrlSourceLocation = UrlSourceLocation || '->' || ThisBit;
  6353.                   end
  6354.       #DefineRexx
  6355.  
  6356.  The reason for the failure to pack in this circumstance is that the rexx code 
  6357.  is not valid until the substitution has taken place, this confuses the packing 
  6358.  logic. 
  6359.  
  6360.  EXAMPLE 
  6361.  
  6362.       #DefineRexx  SomeRexxCode
  6363.                    ;--- Comment to be removed (as are blank lines) ---
  6364.                    RexxVar1 = strip(GetEnv('PATH'));
  6365.  
  6366.                    /*--- This rexx comment will also be removed ----*/
  6367.                    RexxVar2 = '[' || 'stuff';  /*This rexx comment gets removed*/
  6368.  
  6369.                    ;--- Lets not pack the following rexx code ---
  6370.                    #option PUSH AllowPack=OFF
  6371.                    BothPartsCombined = 'Value:'   TheValue;
  6372.                    #option POP
  6373.  
  6374.                    ;--- Gets some code from a file ---
  6375.                    #include "SomeRexx.X"
  6376.       #DefineRexx
  6377.       #evaluate   ^^  ^<$SomeRexxCode>^
  6378.  
  6379.  You could also have a look at the PPWSORT.H header file as a further example. 
  6380.  
  6381.  
  6382. ΓòÉΓòÉΓòÉ 7.12. #DependsOn ΓòÉΓòÉΓòÉ
  6383.  
  6384. #DependsOn 
  6385.  
  6386. This command can be used to indicate a dependancy that is not obvious to 
  6387. PPWIZARD. All input and output files seen by PPWIZARD are automatically taken 
  6388. care of but there may be instances where you might need to indicate other 
  6389. files. 
  6390.  
  6391. As an example of an INPUT dependancy, you might have a macro which reads parts 
  6392. of CONFIG.SYS (only you know why!) using the rexx linein() function, because 
  6393. your generated output is dependant on the contents of CONFIG.SYS you will wish 
  6394. to rebuild if the file changes. 
  6395.  
  6396. As an example of an OUTPUT dependancy, you might not wish to use the #output 
  6397. command and therefore directly write to files using a rexx "lineout()" 
  6398. function. 
  6399.  
  6400. An input dependancy should be defined before the file is used. It does not 
  6401. matter when an output dependancy is defined. 
  6402.  
  6403. If /DependsOn was not specified then the command is ignored. 
  6404.  
  6405. Syntax 
  6406.  
  6407.     [WhiteSpace]#DependsOn  ["]DepType["]  ["]StampWhat1["]  ...
  6408.  
  6409. The "DepType" parameter indicates whether the following files are input 
  6410. (source) files or output (target) files. A rebuild or your target files is 
  6411. required if there are any input files which have a later date/time than any of 
  6412. your output files.  A rebuild is also forced if an input or output file can't 
  6413. be located. 
  6414.  
  6415. The "StampWhat" parameter(s) are usually the names of files that should be 
  6416. added to the dependancy list. It is not an error (just time consuming) to 
  6417. specify the same item more than once. Normally files date and time is used for 
  6418. the "stamp" however if the parameter starts with '*' then this has special 
  6419. meaning as follows: 
  6420.  
  6421.          *Files=[+]FileMask 
  6422.           This allows a list of files matching a mask to be stamped in one hit. 
  6423.           You should understand that this is not the same as stamping all the 
  6424.           files matching the mask individually as the number of files matching 
  6425.           the mask can change but a static list of files doesn't. For example 
  6426.           "*Files=+E:\DB\URLS\*.*" will stamp all files in the directory, and 
  6427.           since "+" was used will also process those in it's subdirectories. 
  6428.  
  6429.          *Exec=CommandLine 
  6430.           This allows a you to process any command that can be typed at a 
  6431.           command line. Its redirected output, stripped of carriage return, 
  6432.           Line Feed and End Of File characters is used as the "stamp". 
  6433.  
  6434.  Example 1 - Two files specified 
  6435.  
  6436.       #DependsOn  INPUT   "C:\CONFIG.SYS"   "C:\STARTUP.CMD"
  6437.  
  6438.  Example 2 - Real life macro 
  6439.  
  6440.      ;--- Outputs the size of a file (takes parameter "File") --------------------
  6441.      #define SizeOfFile                                                                                                         \
  6442.              #evaluate+  LocalFileName    ^ReplaceString("../{$File}", "/", "\")^                                               \
  6443.              #DependsOn  INPUT            "<$LocalFileName>"                                                                    \
  6444.              #evaluate+  TmpFileSize      ^AddCommasToDecimalNumber(stream("<$LocalFileName>", "c", "query size"))^             \
  6445.              #if "<$TmpFileSize>" = ""                                                                                          \
  6446.                  #error $Failed getting size of "<$LocalFileName>"$                                                             \
  6447.              #endif                                                                                                             \
  6448.              <$TmpFileSize>
  6449.      #define SizeOfFileInSmallFont   <FONT SIZE=-1>{$Before=""}<$SizeOfFile File=*{$File}*> bytes{$After=""}</FONT>
  6450.      #define (SizeOfFileInSmallFont) <$SizeOfFileInSmallFont File=*{$File}* Before='(' After=')'>
  6451.  
  6452.  
  6453. ΓòÉΓòÉΓòÉ 7.13. #elseif ΓòÉΓòÉΓòÉ
  6454.  
  6455. #elseif 
  6456.  
  6457. This command is used if you wish to have some lines included when the #if 
  6458. condition is false. 
  6459.  
  6460.  
  6461. ΓòÉΓòÉΓòÉ 7.14. #endif ΓòÉΓòÉΓòÉ
  6462.  
  6463. #endif 
  6464.  
  6465. This command is used to terminate a previous #if command.  There should be a 
  6466. matching #endif for every #if command. 
  6467.  
  6468.  
  6469. ΓòÉΓòÉΓòÉ 7.15. #EOF ΓòÉΓòÉΓòÉ
  6470.  
  6471. #EOF 
  6472.  
  6473. This command marks where processing of the current file should be stopped. 
  6474. Anything after this command can be in any format as its never read. 
  6475.  
  6476. This command is ignored if it appears in an #imported file. 
  6477.  
  6478. Syntax 
  6479.  
  6480.     [WhiteSpace]#EOF  [["]EndifCount["]]>
  6481.  
  6482. The "EndifCount" parameter is optional and may be required if you wish to use 
  6483. the #EOF command conditionally.  The number should normally match the nesting 
  6484. level within the file. 
  6485.  
  6486.  
  6487. ΓòÉΓòÉΓòÉ 7.16. #evaluate[+] ΓòÉΓòÉΓòÉ
  6488.  
  6489. #evaluate[+] 
  6490.  
  6491. This command will execute a rexx command line. The result of this command can 
  6492. be stored into a "#define" variable. If the command was "#evaluate+" then if a 
  6493. redefine of a variable occurs then this is considered to be OK and no warnings 
  6494. are generated. For more information on macros and their use please see the 
  6495. macros section. 
  6496.  
  6497. You would use this command (over #define) for one of the following main 
  6498. reasons: 
  6499.  
  6500.        1. You wish to get some some data from rexx.  Any standard rexx 
  6501.           functions (or your own as ".CMD") can be used.  If you are frequently 
  6502.           calling your own routine for performance you may wish to look at the 
  6503.           #MacroSpace command. 
  6504.  
  6505.        2. You wish to perform arithmetic or other similar operation. 
  6506.  
  6507.        3. You wish the macros contents to have leading or trailing whitespace. 
  6508.  
  6509.        4. You wish to get some information out of the environment (contents of 
  6510.           environment variables, information from text or INI files etc). 
  6511.  
  6512.  The #evaluate command will handle syntax errors and unknown variables, dumping 
  6513.  what it knows and then aborting the preprocessing. 
  6514.  
  6515.  It is recommended that you read the performance documentation as this command 
  6516.  is much slower than some other alternatives which you can use in some 
  6517.  circumstances (such as the #define command). 
  6518.  
  6519.  Syntax 
  6520.  
  6521.       [WhiteSpace]#evaluate[+]  ["]Variable["]  [']Expression[']
  6522.  
  6523.  The "Variable" parameter is the name of the macro you wish created or updated. 
  6524.  This parameter is optional if you don't wish to use the result as text in your 
  6525.  HTML.  If supplied the result of the "Expression" is assigned to the macro 
  6526.  specified. 
  6527.  
  6528.  The "Expression" parameter is executed by rexx. As well as supporting all 
  6529.  standard rexx functions and any ".CMD" you care to write yourself, the 
  6530.  following PPWIZARD preprocessor extensions can be called: 
  6531.  
  6532.          AddCommasToDecimalNumber() 
  6533.          AddInputFileToDependancyList() 
  6534.          AddOutputFileToDependancyList() 
  6535.          AddressCmd() 
  6536.          AsIs() 
  6537.          AsIsPrepare() 
  6538.          AutoTag() 
  6539.          BaseDate() 
  6540.          BreakAt() 
  6541.          BulkChar2String() 
  6542.          BulkChangePrepare() 
  6543.          CompareReplaceFixed() 
  6544.          DataGet() 
  6545.          DataSave() 
  6546.          Debug() 
  6547.          DebugIndent() 
  6548.          Defined() 
  6549.          DieIfIoErrorOccurred() 
  6550.          EnsureFileHasCorrectCase() 
  6551.          Error() 
  6552.          ExpandXCodes() 
  6553.          GenerateFileName() 
  6554.          GetAmPmTime() 
  6555.          GetEnv() 
  6556.          GetFileLineBeingProcessed() 
  6557.          GetFileTimeStamp() 
  6558.          GetId() 
  6559.          GetIdPrepare() 
  6560.          GetImageHeightWidth() 
  6561.          GetInputFileNameAndLine() 
  6562.          GetLineBeingProcessed() 
  6563.          Info() 
  6564.          InputComponentLevel() 
  6565.          InputComponentLineLevel() 
  6566.          IsDebugOn() 
  6567.          MacroGet() 
  6568.          MacroSet() 
  6569.          PadString() 
  6570.          ProcessNext() 
  6571.          QuoteIt() 
  6572.          ReplaceMacros() 
  6573.          ReplaceString() 
  6574.          ReplaceStringCI() 
  6575.          ReverseArray() 
  6576.          SetEnv() 
  6577.          SetId() 
  6578.          SortArray() 
  6579.          Summary() 
  6580.          ToLowerCase() 
  6581.          UrlDecode() 
  6582.          UrlEncode() 
  6583.          Warning() 
  6584.          WriteLineToTmpImportFile() 
  6585.          RexGetTmpFileName() 
  6586.          _filespec() 
  6587.          _SysFileDelete() 
  6588.          _SysFileTree() 
  6589.          _SysSearchPath() 
  6590.  
  6591.  EXAMPLE #1 
  6592.  
  6593.       ;--- Get current date ------------------------------------------------------
  6594.       #evaluate TodaysDate      "date('WeekDay') || ' ' || date('Normal')"
  6595.  
  6596.  EXAMPLE #2 
  6597.  
  6598.       ;--- Get SHORT name of Generated HTML file ---------------------------------
  6599.       #evaluate ShortNameHtml   "_filespec('name', '<?OutputFile>')"
  6600.  
  6601.  EXAMPLE #3 
  6602.  
  6603.       ;--- Beep and then generate first 3 lines of CONFIG.SYS into HTML ----------
  6604.       #evaluate ""                "call beep 1000, 800"
  6605.       #evaluate ""                'File2Read = "C:\CONFIG.SYS"'
  6606.       #evaluate ""                "CloseFileRc = stream(File2Read, 'c', 'close')"
  6607.       #evaluate "ConfigSysLine1"  "linein(File2Read, 1)"
  6608.       #evaluate "ConfigSysLine2"  "linein(File2Read)"
  6609.       #evaluate "ConfigSysLine3"  /linein(File2Read)/
  6610.       #evaluate ||                /CloseFileRc = stream(File2Read, 'c', 'close')/
  6611.       <$ConfigSysLine1><BR>
  6612.       <$ConfigSysLine2><BR>
  6613.       <$ConfigSysLine3><BR>
  6614.  
  6615.  
  6616. ΓòÉΓòÉΓòÉ 7.17. #Error ΓòÉΓòÉΓòÉ
  6617.  
  6618. #Error 
  6619.  
  6620. A #Error command is used to abort processing. You would probably have extracted 
  6621. information (maybe from an environment variable) and found that all is not 
  6622. right.  This command allows you to halt processing and display an error to 
  6623. explain the problem. 
  6624.  
  6625. The #Warning command is similar but does not halt processing. 
  6626.  
  6627. Syntax 
  6628.  
  6629.     [WhiteSpace]#Error  [']ErrorMessage[']
  6630.  
  6631. The "ErrorMessage" specifies the text to be displayed. 
  6632.  
  6633. Example 
  6634.  
  6635.     #if GetEnv('FRED') <> 1 & GetEnv('FRED') <> 2
  6636.         #Error "Invalid value for variable 'FRED'"
  6637.     #endif
  6638.  
  6639.  
  6640. ΓòÉΓòÉΓòÉ 7.18. #if ΓòÉΓòÉΓòÉ
  6641.  
  6642. #if 
  6643.  
  6644. A #if command (like #ifdef and #ifndef) can be used to conditionally include 
  6645. lines of text, this can be any other type of line or command except #elseif or 
  6646. #endif.  As an example of its use, #if allows you to examine the machine it is 
  6647. running on (for example its environment variables) and generate the appropriate 
  6648. code. 
  6649.  
  6650. #if commands can be nested to any level and there need not be any lines between 
  6651. a #if and a #endif or #elseif command. 
  6652.  
  6653. There are two forms of this command.  The second exists only to speed up the 
  6654. performance, it supplies a small subset of the full functionality but is very 
  6655. much faster. 
  6656.  
  6657. Syntax #1 - Full Functionality (but slower) 
  6658.  
  6659.     [WhiteSpace]#if  ValidRexxCondition
  6660.  
  6661. The "ValidRexxCondition" specifies a valid rexx conditional test which results 
  6662. in a TRUE or FALSE answer.  The condition may be as complex as you wish and may 
  6663. include the special GetEnv() function (or many others) to obtain information 
  6664. from the environment.  For complex logic an external rexx script could be 
  6665. called, these can return numeric or text return codes. 
  6666.  
  6667. Syntax #2 - Partial Functionality (but fast) 
  6668.  
  6669. Its is recommended that this form be used where possible if you have many tests 
  6670. in your code, if you only have a few you probably don't need to bother.  This 
  6671. form does a single compare between two simple values.  The square brackets 
  6672. surrounding the compare are used to indicate that this form is supplied by the 
  6673. user. 
  6674.  
  6675.     [WhiteSpace]#if  [Value1  Operator  Value2]
  6676.  
  6677. The "Operator" parameter should have whitespace to either side and be one of 
  6678. the following: 
  6679.  
  6680.        1. == Strict compare for equal. 
  6681.        2. = Compare for equal. 
  6682.        3. <> Compare for not equal. 
  6683.        4. < Less than. 
  6684.        5. > Greater than . 
  6685.        6. <= Less than or equal. 
  6686.        7. >= Greater than or equal. 
  6687.  
  6688.  The Value1 & Value2 parameters can be one of the following: 
  6689.  
  6690.          A rexx number. 
  6691.          A rexx variable. 
  6692.          A rexx literal. 
  6693.  
  6694.  Example #1 
  6695.  
  6696.       ;--- Don't not display following graphics on works INTRANET! ----------------
  6697.       #if translate(GetEnv("PRJSRCDIR")) = "E:\DB\PROJECTS\HOMEPAGE"
  6698.           <CENTER><IMG SRC="graphics/fatguy.gif" BORDER=0 WIDTH=182 HEIGHT=181></CENTER>
  6699.       #endif
  6700.  
  6701.  Example #2 
  6702.  
  6703.       #define StupidExampleMacro                                                             \
  6704.               <P>Hi, my name is Dennis Bareis and I have been using OS/2 and developing for  \
  6705.               #if ['<$AtWork>' = 'Y']                                                        \
  6706.                  ANZ                                                                         \
  6707.               elseif                                                                         \
  6708.                  *WRONG INC*                                                                 \
  6709.               endif                                                                          \
  6710.               on and off since the original 1.0 version.
  6711.  
  6712.  
  6713. ΓòÉΓòÉΓòÉ 7.19. #ifdef ΓòÉΓòÉΓòÉ
  6714.  
  6715. #ifdef 
  6716.  
  6717. A #ifdef command (like #if and #ifndef) can be used to conditionally include 
  6718. lines of text, this can be any other type of line or command except #elseif or 
  6719. #endif. 
  6720.  
  6721. #if commands can be nested to any level and there need not be any lines between 
  6722. a #if command and a #endif or #elseif command. 
  6723.  
  6724. Note that this command only checks on a single variable, for more complex 
  6725. requirements you will need to use a #if command along with calls to the 
  6726. Defined() routine. For performance reasons its recommended that you use #ifdef 
  6727. and #ifndef commands where possible. 
  6728.  
  6729. Syntax 
  6730.  
  6731.     [WhiteSpace]#ifdef  VariableName
  6732.  
  6733. The "VariableName" specifies a variable that should exist for the test to 
  6734. evaluate to true. 
  6735.  
  6736. Example 
  6737.  
  6738.     #define Fred FredsValue
  6739.     #ifdef Fred
  6740.         ...
  6741.     #endif
  6742.  
  6743.  
  6744. ΓòÉΓòÉΓòÉ 7.20. #ifndef ΓòÉΓòÉΓòÉ
  6745.  
  6746. #ifndef 
  6747.  
  6748. A #ifndef command (like #if and #ifdef) can be used to conditionally include 
  6749. lines of text, this can be any other type of line or command except #elseif or 
  6750. #endif. 
  6751.  
  6752. #if commands can be nested to any level and there need not be any lines between 
  6753. a #if command and a #endif or #elseif command. 
  6754.  
  6755. Note that this command only checks on a single variable, for more complex 
  6756. requirements you will need to use a #if command along with calls to the 
  6757. Defined() routine. For performance reasons its recommended that you use #ifdef 
  6758. and #ifndef commands where possible. 
  6759.  
  6760. Syntax 
  6761.  
  6762.     [WhiteSpace]#ifndef  VariableName
  6763.  
  6764. The "VariableName" specifies a variable that should NOT exist for the test to 
  6765. evaluate to true. 
  6766.  
  6767. Example 
  6768.  
  6769.     #define Fred FredsValue
  6770.     #ifndef Fred
  6771.         ...
  6772.     #endif
  6773.  
  6774.  
  6775. ΓòÉΓòÉΓòÉ 7.21. #import ΓòÉΓòÉΓòÉ
  6776.  
  6777. #import 
  6778.  
  6779. Many programs and databases (Microsoft Excel or Access, Lotus 123 etc) allow 
  6780. you to export data in many different formats. The #import command allows you to 
  6781. import the most common formats and generate output to your specification. 
  6782.  
  6783. The default output format for quite a few of the import types is a HTML table. 
  6784. Not only don't you need to generate a table at all, you also have a lot of fine 
  6785. tuning parameters if you wish to remain with a table but just wish to tweek its 
  6786. look (give certain columns a special background color etc). I have seen people 
  6787. generate a whole series of #define and #include commands to generate a separate 
  6788. html page for each record (from a product database). 
  6789.  
  6790. This command might seem complicated at first (and in actual fact it is!), I 
  6791. recommend you actually try the examples (cut and paste as required). 
  6792.  
  6793. If you are having problems working out what is going on I highly recommend the 
  6794. use of debugging (/debug or #debug) as this has been designed not just for 
  6795. debugging but for training as well.  Note I recommend that if debugging you cut 
  6796. your database down to a few test records so that you won't be swamped with 
  6797. output. 
  6798.  
  6799. Import Processing Details 
  6800.  
  6801. All import types get handled in two distinct passes as follows: 
  6802.  
  6803.        1. The imported file is read, processed (including calls to your rexx 
  6804.           filter code if defined) and the output is generated to a temporary 
  6805.           file. 
  6806.  
  6807.           If you have a filter then in some advanced applications you may need 
  6808.           to use the WriteLineToTmpImportFile() routine. An example of this is 
  6809.           if you wished to generate PPWIZARD commands such as #output. 
  6810.  
  6811.        2. The temporary file is read in and processed in exactly the same 
  6812.           manner as any file that you yourself might include with a #include 
  6813.           command. This is where any macros you may have referenced as 
  6814.           expanded. 
  6815.  
  6816.           If debug is not on then after pass two completes the temporary file 
  6817.           is deleted. Turn debug on an examine the temporary file if things are 
  6818.           not going to plan! 
  6819.  
  6820.  Syntax 
  6821.  
  6822.       [WhiteSpace]#import  ["]File2Import["]  ["]T2H|WRAP["]  ["]DefineName["]    OR
  6823.       [WhiteSpace]#import  ["]File2Import["]  ["]ImportType[-]["]  ["]DefineName["]  ["]FieldInfo1["]  ...
  6824.  
  6825.  The parameters are as follows: 
  6826.  
  6827.        1. File2Import 
  6828.           This is the name of the file to be imported.  Blank lines are ignored 
  6829.           (is this causing anyone problems?). 
  6830.  
  6831.        2. ImportType 
  6832.           This describes the format of the data to be imported.  If the type 
  6833.           has "-" appended then the first lines of the file are dropped 
  6834.           (default is one line). The currently supported types are: 
  6835.  
  6836.               SQL 
  6837.                PPWIZARD does not support SQL directly but it doesn't need to as 
  6838.                it can interface to any database if a rexx interface is 
  6839.                available. 
  6840.               CMA[-] 
  6841.                All fields are comma delimited (fields can't contain commas 
  6842.                unless quoted). Fields may be empty.  Blank trailing fields may 
  6843.                be missing. 
  6844.               TAB[-] 
  6845.                As above except a tab (ascii 9) is the delimiter. 
  6846.               ???[-] 
  6847.                As above except you specify the exact delimiter you want. For 
  6848.                example "^^^" indicates that you wish a delimiter of "^". 
  6849.               FIX[-] 
  6850.                Unlike all previous types there is no delimiter.  Items appear 
  6851.                in fixed columns in the file.  While you can play with 
  6852.                "FieldInfo" there is not much point as you can specify all the 
  6853.                fields you want in the order you want them. 
  6854.               ML 
  6855.                Each record spans multiple lines and ends with a blank line. 
  6856.                Each field takes up a line and specifies a field name and a 
  6857.                value separated by a user defined delimiter ('=' by default). 
  6858.               T2H 
  6859.                This is a text to HTML type import. 
  6860.               WRAP 
  6861.                This is a specialised import facility. You get passed a line at 
  6862.                a time and you decide how to handle it. 
  6863.  
  6864.        3. DefineName 
  6865.           This parameter gives you a lot of control over how your output is 
  6866.           generated.  The value you supply here is used as a prefix for all 
  6867.           your import options. As an example, if you specified "FRED" as a 
  6868.           value then some import types would look for a #define of 
  6869.           "FRED_DROP_BLANK_LINES" to see if you wished to override the default 
  6870.           handling of blank lines. 
  6871.  
  6872.           The exact #define options which are available will differ depending 
  6873.           on the import type. If you specified a blank value for the prefix a 
  6874.           default is used.  The name of the default also varies with import 
  6875.           type but for the common types is "IMPORT". 
  6876.  
  6877.           In some cases such as when HTML tables are generated there are 
  6878.           multiple levels of defaults and changing a lower level one may have 
  6879.           no effect if you also override a higher one.  This is because the 
  6880.           lower level values became the default values for the higher level. As 
  6881.           an example there is no point specifying that record columns should 
  6882.           have a background color of green and then overriding the record 
  6883.           generation default!  Again the use of debugging support will 
  6884.           generally make this clear as it will show PPWIZARD looking for all 
  6885.           options and display the value PPWIZARD has decided to use. 
  6886.  
  6887.  
  6888. ΓòÉΓòÉΓòÉ 7.21.1. #import - SQL DATABASES ΓòÉΓòÉΓòÉ
  6889.  
  6890. #import - SQL DATABASES 
  6891.  
  6892. This example shows you how to access data using the "mSQL" (free) database 
  6893. program.  The database we will process is called "supersite" and the table we 
  6894. will access is "link". 
  6895.  
  6896. This example makes use of Mark Hessing's RexxSQL library to access the database 
  6897. program.  It's free and is available for multiple operating systems and can 
  6898. access many different database programs.  Its available from 
  6899. "http://www.lightlink.com/hessling/". 
  6900.  
  6901. You may want to have a look at the #evaluate routines AsIs() and AutoTag(). 
  6902.  
  6903. mSQL EXAMPLE 
  6904.  
  6905. ;--- Very simplistic start of HTML ------------------------------------------
  6906. <HTML>
  6907. <BODY>
  6908. <H1>Example - Create Links List from SQL Query</H1>
  6909.  
  6910. ;--- Initialization ---------------------------------------------------------
  6911. #define QueryCategory 3             ;;This query is for this category
  6912. #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
  6913.  
  6914. ;--- Enable PPWIZARD to make use of external SQL library --------------------
  6915. #evaluate  ''  "call RXFuncAdd 'SQLLoadFuncs', 'rexxsql', 'SQLLoadFuncs'"
  6916. #evaluate  ''  "call SQLLoadFuncs;"
  6917.  
  6918. ;--- Connect to the data base ("supersite" on local machine) ----------------
  6919. #evaluate 'ConnectRc' "SQLConnect('PPW',,, 'supersite', 'localhost')"
  6920.  
  6921. ;--- Perform a database query (on the table "link") -------------------------
  6922. #evaluate+ 'QueryRc' ^SQLCommand('RxLink', 'SELECT * FROM link WHERE category = <$QueryCategory>')^
  6923. #info      'QueryRc = <$QueryRc>'
  6924. #info      'Number of records is <??RxLink.url.0>'
  6925.  
  6926. ;--- Generate the html (for simple list) ------------------------------------
  6927. <UL>                            ;;Start of list
  6928. #RexxVar RxCount = 1            ;;Initialize record counter (rexx variable)
  6929. #{                              ;;Start of loop
  6930.    #if ['<??RxCount>' <= '<??RxLink.url.0>']
  6931.        ;--- Use previously defined macro (template) to generate output ------
  6932.        <$LinkTemplate url="<??RxLink.url.RxCount>" title=^<??RxLink.title.RxCount>^ description=^<??RxLink.description.RxCount>^>
  6933.        #RexxVar RxCount + 1     ;;Update record counter
  6934.    #elseif
  6935.        #break
  6936.    #endif
  6937. #}                              ;;End of loop
  6938. </UL>                           ;;End of list
  6939.  
  6940. ;--- Disconnect the data base -----------------------------------------------
  6941. #evaluate 'DisConnectRc' "SQLDisconnect('PPW')"
  6942.  
  6943. ;--- Very simple end of HTML ------------------------------------------------
  6944. <P>
  6945. <HR>
  6946. <CENTER>End of simple SQL IMPORT Example</CENTER>
  6947. </BODY>
  6948. </HTML>
  6949.  
  6950.  
  6951. ΓòÉΓòÉΓòÉ 7.21.2. #import - Delimited Records ΓòÉΓòÉΓòÉ
  6952.  
  6953. #import - Delimited Records 
  6954.  
  6955. These type of #Imports have clearly defined fields.  You would frequently wish 
  6956. to display these in a table (say in a HTML page) however nothing says that you 
  6957. need to do so.  If you wish to create macros and then #include a template file 
  6958. then that is also possible. 
  6959.  
  6960. Within a record the fields are delimited by a single character such as a tab or 
  6961. comma. 
  6962.  
  6963. Field Information Parameters 
  6964.  
  6965. On these types of imports "FieldInfo" followings the "DefineName" parameter. 
  6966.  
  6967. You must specify field information for each field up to the last one you are 
  6968. interested in. The field information is of the format: 
  6969.  
  6970.   [{NewColumn}]TitleText 
  6971.  
  6972. The optional "NewColumn" specifies the column you wish the field to be moved 
  6973. to.  This need only be supplied if you wish to change the order, by default the 
  6974. first field is column 1 etc. 
  6975.  
  6976. The "title text" specifies the value for the field in the header record. A 
  6977. blank "title" is used to indicate that we don't require a field and it should 
  6978. be dropped. 
  6979.  
  6980. DEFINITIONS/OPTIONS 
  6981.  
  6982. If you can't understand how these options work then I suggest you try using 
  6983. /debug or #debug to watch what variables the import uses etc. 
  6984.  
  6985.          DefineName_BLANK_FIELD 
  6986.           Normally a blank field will be displayed as blank. You may wish to 
  6987.           display '-' instead. Another possiblity is to display a 1 by 1 
  6988.           transparent gif so as to have table borders around blank fields look 
  6989.           better. 
  6990.  
  6991.           For even more control (probably rare requirement): 
  6992.  
  6993.             -  DefineName_BLANK_COLUMN_? 
  6994.                This allows you to specify different blank replacement values 
  6995.                for each column. 
  6996.  
  6997.          DefineName_DROP_BLANK_LINES 
  6998.           You can specify whether or not blank lines (or lines where all fields 
  6999.           are blank) are significant.  The default is 'Y' to drop blank lines, 
  7000.           specify 'N' to prevent this. 
  7001.  
  7002.          DefineName_NEWLINE_CHAR 
  7003.           This can be used to determine what newlines within fields should be 
  7004.           replaced with ("<BR>" by default). 
  7005.  
  7006.          DefineName_TAB_CHAR 
  7007.           Normally tabs are ignored by the import process.  This variable 
  7008.           allows you to replace them with something else. 
  7009.  
  7010.          DefineName_ASIS_TAGGING 
  7011.           This option can be used to adjust the conversion of what may be 
  7012.           problem characters (such as '<' in HTML). By default importing does 
  7013.           not handle/convert international characters such as umlauts to html 
  7014.           symbols but there is nothing preventing you from doing so. 
  7015.  
  7016.           Note that you will probably need to override this value (maybe others 
  7017.           as well) if you wished to expand any macros that the imported data 
  7018.           might contain (by default this is not done). 
  7019.  
  7020.          DefineName_DROP_LINE_COUNT 
  7021.           If we are dropping lines (TAB- command etc), then how many should be 
  7022.           dropped.  The default is one. 
  7023.  
  7024.          DefineName_BEFORE 
  7025.           You would probably only use this define if you didn't want to 
  7026.           generate a table at all. You may specify the string "{$Columns}" 
  7027.           which will get replaced with the number of fields to be displayed. If 
  7028.           this define is not used then you can use the following: 
  7029.  
  7030.             -  DefineName_TABLE_ATTRIBS 
  7031.                This value allows you to specify all HTML attributes of the 
  7032.                table apart from the number of columns. 
  7033.  
  7034.          DefineName_HEADER 
  7035.           This is used to control the "code" which handles the "heading" 
  7036.           record, <B>this does not have to be a html table</B>. You can specify 
  7037.           the string {$Column?} to represent a fields value (? = number of 
  7038.           field where 1 is the first). 
  7039.  
  7040.           If this define is not used then you can use the following: 
  7041.  
  7042.             -  DefineName_HEADING_COLUMNS 
  7043.                This value allows you to specify the column (HTML "<TH>" tags) 
  7044.                information to change alignment or colours of columns. This 
  7045.                value becomes the default for all columns. 
  7046.  
  7047.             -  DefineName_HEADING_COLUMN_? 
  7048.                This value allows you to specify the column (HTML "<TH>" tags) 
  7049.                information to change alignment or colours of specific columns. 
  7050.                Another use for this would be to specify the width of a column. 
  7051.                This value is only used for column number '?'. 
  7052.  
  7053.             -  DefineName_HEADING_BEFORE_DATA 
  7054.                This value allows you to specify some text to be placed in front 
  7055.                of the fields data, for example if you wish to change the font 
  7056.                size for each column you might used the value "<FONT SIZE=-1>". 
  7057.                This value becomes the default for all columns. 
  7058.  
  7059.             -  DefineName_HEADING_BEFORE_DATA_? 
  7060.                This value allows you to specify leading data on a column by 
  7061.                column basis. 
  7062.  
  7063.             -  DefineName_HEADING_AFTER_DATA 
  7064.                This value allows you to specify some text to be placed after 
  7065.                the fields data, for example if you wish to change the font size 
  7066.                for each column you might used the value "</FONT>" to close the 
  7067.                previous font tag. This value becomes the default for all 
  7068.                columns. 
  7069.  
  7070.             -  DefineName_HEADING_AFTER_DATA_? 
  7071.                This value allows you to specify trailing data on a column by 
  7072.                column basis. 
  7073.  
  7074.          DefineName_RECORD 
  7075.           This is used to control the "code" for each record, <B>this does not 
  7076.           have to be a html table</B>. You would definately define this option 
  7077.           if you didn't want a html table, you might wish to create s series of 
  7078.           #defines or maybe you are not generating html at all and need to 
  7079.           generate an IPF table. You can specify the string {$Column?} to 
  7080.           represent a fields value (? = number of field where 1 is the first). 
  7081.  
  7082.           If this define is not used then you can use the following: 
  7083.  
  7084.             -  DefineName_RECORD_COLUMNS 
  7085.                This value allows you to specify the column (HTML "<TD>" tags) 
  7086.                information to change alignment or colours of columns. This 
  7087.                value becomes the default for all columns. 
  7088.  
  7089.             -  DefineName_RECORD_COLUMN_? 
  7090.                This value allows you to specify the column (HTML "<TD>" tags) 
  7091.                information to change alignment or colours of specific columns. 
  7092.                Another use for this would be to specify the width of a column. 
  7093.                This value is only used for column number '?'. 
  7094.  
  7095.             -  DefineName_RECORD_BEFORE_DATA 
  7096.                This value allows you to specify some text to be placed in front 
  7097.                of the fields data, for example if you wish to change the font 
  7098.                size for each column you might used the value "<FONT SIZE=-1>". 
  7099.                This value becomes the default for all columns. 
  7100.  
  7101.             -  DefineName_RECORD_BEFORE_DATA_? 
  7102.                This value allows you to specify leading data on a column by 
  7103.                column basis. 
  7104.  
  7105.             -  DefineName_RECORD_AFTER_DATA 
  7106.                This value allows you to specify some text to be placed after 
  7107.                the fields data, for example if you wish to change the font size 
  7108.                for each column you might used the value "</FONT>" to close the 
  7109.                previous font tag. This value becomes the default for all 
  7110.                columns. 
  7111.  
  7112.             -  DefineName_RECORD_AFTER_DATA_? 
  7113.                This value allows you to specify trailing data on a column by 
  7114.                column basis. 
  7115.  
  7116.          DefineName_AFTER 
  7117.           Unless you are not creating a table you are unlikely to want to 
  7118.           change the codes that end the table. 
  7119.  
  7120.          DefineName_RECORD_FILTER 
  7121.           The contents of this variable should be one or more rexx expressions. 
  7122.  
  7123.           Normally all records are displayed. A filter can examine all column 
  7124.           variables and modify them or tell PPWIZARD to ignore the record.  The 
  7125.           filter is not called for the heading record. 
  7126.  
  7127.           The following rexx variables and functions are relevant: 
  7128.  
  7129.             -  Remove 
  7130.                If this variable is set to any non blank value then the record 
  7131.                will be dropped, the variables value is shown when debugging so 
  7132.                it is recommended that the value be the reason for dropping the 
  7133.                record. 
  7134.  
  7135.                If the contents starts with 'EOF:' then the current record and 
  7136.                ALL following are dropped. 
  7137.  
  7138.             -  Column.? 
  7139.                The "Column" array holds the data for each field (that you are 
  7140.                interested in) of the current record in the order you provided. 
  7141.                For example "Column.2" holds the 2nd column's data. 
  7142.  
  7143.             -  Dropped.? 
  7144.                The "Dropped" array holds the data for each field (that you 
  7145.                dropped) of the current record in the order that they were 
  7146.                dropped. For example "Dropped.1" holds the first dropped field. 
  7147.  
  7148.             -  ThisRecordsCodes 
  7149.                This variable gets initialized for each record with the value 
  7150.                that you defined (or allowed to default) for the 
  7151.                "DefineName_RECORD" option.  You can add to or modify this 
  7152.                record in any way. The value of "{$Column1}" gets replaced with 
  7153.                the contents of the rexx variable "Column.1" etc. 
  7154.  
  7155.                If all your records are processed the same way then you should 
  7156.                not need to modify this variable.  It is useful where you might 
  7157.                want the output (row of table) to look different depending on 
  7158.                the records data.  In some cases this can be better done by 
  7159.                updating the rexx "Column.?" array. 
  7160.  
  7161.                If you need multiple lines you can of course use "<?NewLine>" 
  7162.                where required. 
  7163.  
  7164.             -  WriteLineToTmpImportFile() 
  7165.                The passed data is written to the output file, any line feed 
  7166.                characters will indicate the end of a line. 
  7167.  
  7168.             -  RecordFilter 
  7169.                If you don't need to do any more filtering then you can clear 
  7170.                this variable.  This will improve performance. 
  7171.  
  7172.          DefineName_PROTECT_START 
  7173.           By default will be set to the value <?ProtectFromPpwStart>. If you 
  7174.           have filter code that wants to generate PPWIZARD commands then you 
  7175.           will need to override this value. Have a look at the multiple HTML 
  7176.           pages example. 
  7177.  
  7178.          DefineName_PROTECT_END 
  7179.            By default will be set to the value <?ProtectFromPpwEnd>. 
  7180.  
  7181.  You should also check out an example of importing a file into multiple HTML 
  7182.  pages based on the contents of one of the fields. 
  7183.  
  7184.  Examples - Comma Delimited 
  7185.  
  7186.  A tab delimited file is probably be best format to use however this example 
  7187.  will use comma delimited as its a bit hard to display a tab!  Assume the 
  7188.  following file is being imported (Importme.CMA): 
  7189.  
  7190.   Dennis,Bareis,Programmer
  7191.   Wendy,Buxton,Librarian
  7192.   Fred,Nerk,Idiot
  7193.  
  7194.  Please treat each of the following examples in isolation and assume that no 
  7195.  #defines other than those specifically shown for that example have been set. 
  7196.  Please note that I could have used ",,," instead of "CMA" when specifying the 
  7197.  format. 
  7198.  
  7199.  The following code will display the 3 fields in the order they occur (in a 
  7200.  completely default table format): 
  7201.  
  7202.       #import IMPORTME.CMA "CMA" '' "First Name" "Last Name" "Job"
  7203.  
  7204.  We now wish to simply swap the order of the "Job" column so it becomes first: 
  7205.  
  7206.       #import IMPORTME.CMA CMA '' "{2}First Name" "{3}Last Name" "{1}Job"
  7207.  
  7208.  Lets drop the last name altogether so that we only see the first name and job 
  7209.  columns: 
  7210.  
  7211.       #import IMPORTME.CMA CMA '' "First Name" "" "Job"
  7212.  
  7213.  Lets display the above table using slightly different table formatting (column 
  7214.  borders thinner, table border fatter, headings centered on yellow background 
  7215.  and record data left justified): 
  7216.  
  7217.       #define IMPORT_TABLE_ATTRIBS    BORDER=20 CELLSPACING=1
  7218.       #define IMPORT_HEADING_COLUMNS  ALIGN=CENTER BGCOLOR=YELLOW
  7219.       #define IMPORT_RECORD_COLUMNS   ALIGN=LEFT
  7220.       #import IMPORTME.CMA CMA '' "First Name" "" "Job"
  7221.  
  7222.  As above but column 2 is centered: 
  7223.  
  7224.       #define IMPORT_TABLE_ATTRIBS    BORDER=20 CELLSPACING=1
  7225.       #define IMPORT_HEADING_COLUMNS  ALIGN=CENTER BGCOLOR=YELLOW
  7226.       #define IMPORT_RECORD_COLUMNS   ALIGN=LEFT
  7227.       #define IMPORT_RECORD_COLUMN_2  ALIGN=CENTER
  7228.       #import IMPORTME.CMA CMA '' "First Name" "" "Job"
  7229.  
  7230.  
  7231.  Examples - More Complex 
  7232.  
  7233.  This example is based on a real one situation at work.  We export date from 
  7234.  Microsoft's access/Excel and want this data to appear in a table. 
  7235.  
  7236.  The following main points are demonstrated: 
  7237.  
  7238.        1. The use of #defines and line continuation to format things to be 
  7239.           easier to read and understand. 
  7240.  
  7241.        2. The use of #autotag to translate some of the text (for example 
  7242.           "priority") to minimize the width of the columns. 
  7243.  
  7244.        3. More complex overriding of defaults to get smaller font size etc. 
  7245.  
  7246.        4. More field dropping but also swapping of fields. 
  7247.  
  7248.   <HTML>
  7249.  
  7250.   ;--- Problem database data exported from Excel (trying from access) ---------
  7251.   <CENTER><H1>Release 98.0.1</H1></CENTER>
  7252.  
  7253.   ;--- Setup table definitions ------------------------------------------------
  7254.   #define    IMPORT_TABLE_ATTRIBS    BORDER=5 CELLSPACING=1
  7255.   #define    IMPORT_BLANK_FIELD      -
  7256.   ;**      CommentBlock  /* (Tuesday 23/06/1998, 13:00:55, by Dennis_Bareis) */
  7257.   ;**+--------------------------------------------------------------------------
  7258.   ;**|#define    IMPORT_HEADING_COLUMNS  ALIGN=CENTER BGCOLOR=YELLOW
  7259.   ;**|#define    IMPORT_RECORD_COLUMNS   ALIGN=CENTER
  7260.   ;**|#define    IMPORT_RECORD_COLUMN_2  ALIGN=LEFT
  7261.   ;**|#define    IMPORT_RECORD_COLUMN_4  ALIGN=LEFT
  7262.   ;**+--------------------------------------------------------------------------
  7263.   ;**                    /* (Tuesday 23/06/1998, 13:00:55, by Dennis_Bareis) */
  7264.  
  7265.   ;--- Define some data translations (shorten Priority + Problem Type) --------
  7266.   #AutoTag ">High<"       ">H<"
  7267.   #AutoTag ">Low<"        ">L<"
  7268.   #AutoTag ">Medium<"     ">M<"
  7269.   #AutoTag ">Change<"     ">C<"
  7270.   #AutoTag ">Error<"      ">E<"
  7271.  
  7272.   ;--- Try these --------------------------------------------------------------
  7273.   #define  IMPORT_HEADER  <TR>                                                      -\
  7274.                           <TH ALIGN=CENTER BGCOLOR=YELLOW><FONT SIZE=-1>{$Column1}  -\
  7275.                           <TH ALIGN=CENTER BGCOLOR=YELLOW><FONT SIZE=-1>{$Column2}  -\
  7276.                           <TH ALIGN=CENTER BGCOLOR=YELLOW><FONT SIZE=-1>{$Column3}  -\
  7277.                           <TH ALIGN=CENTER BGCOLOR=YELLOW><FONT SIZE=-1>{$Column4}  -\
  7278.                           <TH ALIGN=CENTER BGCOLOR=YELLOW><FONT SIZE=-1>{$Column5}  -\
  7279.                           <TH ALIGN=CENTER BGCOLOR=YELLOW><FONT SIZE=-1>{$Column6}  -\
  7280.                           <TH ALIGN=CENTER BGCOLOR=YELLOW><FONT SIZE=-1>{$Column7}  -\
  7281.                           <TH ALIGN=CENTER BGCOLOR=YELLOW><FONT SIZE=-1>{$Column8}  -\
  7282.                           </TR>
  7283.   #define  IMPORT_RECORD  <TR>                                                      -\
  7284.                           <TD ALIGN=CENTER><FONT SIZE=-1>{$Column1}                 -\
  7285.                           <TD ALIGN=LEFT><FONT SIZE=-1>{$Column2}                   -\
  7286.                           <TD ALIGN=CENTER><FONT SIZE=-1>{$Column3}                 -\
  7287.                           <TD ALIGN=LEFT><FONT SIZE=-1>{$Column4}                   -\
  7288.                           <TD ALIGN=CENTER><FONT SIZE=-1>{$Column5}                 -\
  7289.                           <TD ALIGN=CENTER><FONT SIZE=-1>{$Column6}                 -\
  7290.                           <TD ALIGN=CENTER><FONT SIZE=-1>{$Column7}                 -\
  7291.                           <TD ALIGN=CENTER><FONT SIZE=-1>{$Column8}                 -\
  7292.                           </TR>
  7293.  
  7294.   ;--- Specify the fields -----------------------------------------------------
  7295.   #define  FIELD_NAMES    "{1}Problem<BR>#"                \
  7296.                           "{2}Title"                       \
  7297.                           "{5}P<BR>r<BR>i"                 \
  7298.                           "{8}Pre<BR>/<BR>Spar"            \
  7299.                           "{6}T<BR>y<BR>p<BR>e"            \
  7300.                           "{3}Application"                 \
  7301.                           ""                               \
  7302.                           ""                               \
  7303.                           "{7}Fixed By"                    \
  7304.                           ""                               \
  7305.                           ""                               \
  7306.                           ""                               \
  7307.                           ""                               \
  7308.                           ""                               \
  7309.                           "{4}User Impact"
  7310.  
  7311.   ;--- Make the changes (autotag some text) -----------------------------------
  7312.   #AutoTag ON
  7313.   #import "export.tab" TAB- ""    <$FIELD_NAMES>
  7314.   #AutoTag OFF
  7315.  
  7316.  
  7317.   </HTML>
  7318.  
  7319.  
  7320.  
  7321.  Examples - IPF Import 
  7322.  
  7323.  The following code: 
  7324.  
  7325.   #define IMPORT_NEWLINE_CHAR    <?NewLine>.br<?NewLine>
  7326.   #define IMPORT_BEFORE          :table cols='15 15 10'.
  7327.   #define IMPORT_HEADER          :row.                              -\
  7328.                                  :c.:hp9.{$Column1}:ehp9.           -\
  7329.                                  :c.:hp9.{$Column2}:ehp9.           -\
  7330.                                  :c.:hp9.{$Column3}:ehp9.
  7331.   #define IMPORT_RECORD          :row.                              -\
  7332.                                  :c.{$Column1}                      -\
  7333.                                  :c.{$Column2}                      -\
  7334.                                  :c.{$Column3}
  7335.   #define IMPORT_AFTER           :etable.
  7336.  
  7337.  
  7338.   #define IMPORT_RECORD_COLUMNS   ALIGN=LEFT
  7339.  
  7340.   #import "EXAMPLE.CMA" CMA '' "First Name"  "Surname"   "Job"
  7341.  
  7342.  
  7343.  Produces this IPF table: 
  7344.  
  7345.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  7346.   ΓöéFirst Name     ΓöéSurname        ΓöéJob       Γöé
  7347.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7348.   ΓöéDennis         ΓöéBareis         ΓöéProgrammerΓöé
  7349.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7350.   ΓöéWendy          ΓöéBuxton         ΓöéLibrarian Γöé
  7351.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  7352.   ΓöéFred           ΓöéNerk           ΓöéIdiot     Γöé
  7353.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  7354.  
  7355.  Example - Use of Filter 
  7356.  
  7357.   #DefineRexx IMPORT_RECORD_FILTER
  7358.               if Column.1 = "Wendy" then
  7359.                  Remove='This is "Wendy" record'    ;;Don't want this record
  7360.               else
  7361.                  Column.1 = translate(Column.1)     ;;Make column #1 upper case
  7362.   #DefineRexx
  7363.   #import ImportMe.CMA CMA "" "First<BR>Name" "Surname" "Job"
  7364.  
  7365.  
  7366. ΓòÉΓòÉΓòÉ 7.21.3. #import - Fixed Field Records ΓòÉΓòÉΓòÉ
  7367.  
  7368. #import - Fixed Field Records 
  7369.  
  7370. These type of #Imports have clearly defined fields.  You would frequently wish 
  7371. to display these in a table (say in a HTML page) however nothing says that you 
  7372. need to do so.  If you wish to create macros and then #include a template file 
  7373. then that is also possible. 
  7374.  
  7375. The fields have a fixed starting and ending column.  The last record does not 
  7376. need to have a fixed ending column and can span to the end of the line. 
  7377. Leading and trailing whitespace is removed. 
  7378.  
  7379. Field Information Parameters 
  7380.  
  7381. On these types of imports "FieldInfo" followings the "DefineName" parameter. 
  7382.  
  7383. For each field that you are interested in you need to define information in the 
  7384. format: 
  7385.  
  7386.   {*,StartingColumn-[EndingColumn]}TitleText 
  7387.  
  7388. In place of the '*' you could specify the column number you wish to place the 
  7389. field but its usually easier to simply reorder the fields. 
  7390.  
  7391. The "StartingColumn" specifies the column where the field starts. The optional 
  7392. "EndingColumn" specifies where it ends, if not supplied it ends at the end of 
  7393. the line.  The first column in a line is column 1. 
  7394.  
  7395. The "title text" specifies the value for the field in the header record.  If 
  7396. this "title" is blank the field will be dropped. 
  7397.  
  7398. DEFINITIONS/OPTIONS 
  7399.  
  7400. If you can't understand how these options work then I suggest you try using 
  7401. /debug or #debug to watch what variables the import uses etc. 
  7402.  
  7403.          DefineName_BLANK_FIELD 
  7404.           Normally a blank field will be displayed as blank. You may wish to 
  7405.           display '-' instead. Another possiblity is to display a 1 by 1 
  7406.           transparent gif so as to have table borders around blank fields look 
  7407.           better. 
  7408.  
  7409.           For even more control (probably rare requirement): 
  7410.  
  7411.             -  DefineName_BLANK_COLUMN_? 
  7412.                This allows you to specify different blank replacement values 
  7413.                for each column. 
  7414.  
  7415.          DefineName_DROP_BLANK_LINES 
  7416.           You can specify whether or not blank lines (or lines where all fields 
  7417.           are blank) are significant.  The default is 'Y' to drop blank lines, 
  7418.           specify 'N' to prevent this. 
  7419.  
  7420.          DefineName_NEWLINE_CHAR 
  7421.           This can be used to determine what newlines within fields should be 
  7422.           replaced with ("<BR>" by default). 
  7423.  
  7424.          DefineName_TAB_CHAR 
  7425.           Normally tabs are ignored by the import process.  This variable 
  7426.           allows you to replace them with something else. 
  7427.  
  7428.          DefineName_ASIS_TAGGING 
  7429.           This option can be used to adjust the conversion of what may be 
  7430.           problem characters (such as '<' in HTML). By default importing does 
  7431.           not handle/convert international characters such as umlauts to html 
  7432.           symbols but there is nothing preventing you from doing so. 
  7433.  
  7434.           Note that you will probably need to override this value (maybe others 
  7435.           as well) if you wished to expand any macros that the imported data 
  7436.           might contain (by default this is not done). 
  7437.  
  7438.          DefineName_DROP_LINE_COUNT 
  7439.           If we are dropping lines (TAB- command etc), then how many should be 
  7440.           dropped.  The default is one. 
  7441.  
  7442.          DefineName_HANDLE_IMBEDDED_NEWLINES 
  7443.           Excel and probably other programs can output delimited files where a 
  7444.           "line" can contain a newline.  To detect this takes more work and so 
  7445.           it is not the default situation.  To turn on imbedded newline 
  7446.           detection use a value of 'Y'. 
  7447.  
  7448.          DefineName_BEFORE 
  7449.           You would probably only use this define if you didn't want to 
  7450.           generate a table at all. You may specify the string "{$Columns}" 
  7451.           which will get replaced with the number of fields to be displayed. If 
  7452.           this define is not used then you can use the following: 
  7453.  
  7454.             -  DefineName_TABLE_ATTRIBS 
  7455.                This value allows you to specify all HTML attributes of the 
  7456.                table apart from the number of columns. 
  7457.  
  7458.          DefineName_HEADER 
  7459.           This is used to control the "code" which handles the "heading" 
  7460.           record, <B>this does not have to be a html table</B>. You can specify 
  7461.           the string {$Column?} to represent a fields value (? = number of 
  7462.           field where 1 is the first). 
  7463.  
  7464.           If this define is not used then you can use the following: 
  7465.  
  7466.             -  DefineName_HEADING_COLUMNS 
  7467.                This value allows you to specify the column (HTML "<TH>" tags) 
  7468.                information to change alignment or colours of columns. This 
  7469.                value becomes the default for all columns. 
  7470.  
  7471.             -  DefineName_HEADING_COLUMN_? 
  7472.                This value allows you to specify the column (HTML "<TH>" tags) 
  7473.                information to change alignment or colours of specific columns. 
  7474.                Another use for this would be to specify the width of a column. 
  7475.                This value is only used for column number '?'. 
  7476.  
  7477.             -  DefineName_HEADING_BEFORE_DATA 
  7478.                This value allows you to specify some text to be placed in front 
  7479.                of the fields data, for example if you wish to change the font 
  7480.                size for each column you might used the value "<FONT SIZE=-1>". 
  7481.                This value becomes the default for all columns. 
  7482.  
  7483.             -  DefineName_HEADING_BEFORE_DATA_? 
  7484.                This value allows you to specify leading data on a column by 
  7485.                column basis. 
  7486.  
  7487.             -  DefineName_HEADING_AFTER_DATA 
  7488.                This value allows you to specify some text to be placed after 
  7489.                the fields data, for example if you wish to change the font size 
  7490.                for each column you might used the value "</FONT>" to close the 
  7491.                previous font tag. This value becomes the default for all 
  7492.                columns. 
  7493.  
  7494.             -  DefineName_HEADING_AFTER_DATA_? 
  7495.                This value allows you to specify trailing data on a column by 
  7496.                column basis. 
  7497.  
  7498.          DefineName_RECORD 
  7499.           This is used to control the "code" for each record, <B>this does not 
  7500.           have to be a html table</B>. You would definately define this option 
  7501.           if you didn't want a html table, you might wish to create s series of 
  7502.           #defines or maybe you are not generating html at all and need to 
  7503.           generate an IPF table. You can specify the string {$Column?} to 
  7504.           represent a fields value (? = number of field where 1 is the first). 
  7505.  
  7506.           If this define is not used then you can use the following: 
  7507.  
  7508.             -  DefineName_RECORD_COLUMNS 
  7509.                This value allows you to specify the column (HTML "<TD>" tags) 
  7510.                information to change alignment or colours of columns. This 
  7511.                value becomes the default for all columns. 
  7512.  
  7513.             -  DefineName_RECORD_COLUMN_? 
  7514.                This value allows you to specify the column (HTML "<TD>" tags) 
  7515.                information to change alignment or colours of specific columns. 
  7516.                Another use for this would be to specify the width of a column. 
  7517.                This value is only used for column number '?'. 
  7518.  
  7519.             -  DefineName_RECORD_BEFORE_DATA 
  7520.                This value allows you to specify some text to be placed in front 
  7521.                of the fields data, for example if you wish to change the font 
  7522.                size for each column you might used the value "<FONT SIZE=-1>". 
  7523.                This value becomes the default for all columns. 
  7524.  
  7525.             -  DefineName_RECORD_BEFORE_DATA_? 
  7526.                This value allows you to specify leading data on a column by 
  7527.                column basis. 
  7528.  
  7529.             -  DefineName_RECORD_AFTER_DATA 
  7530.                This value allows you to specify some text to be placed after 
  7531.                the fields data, for example if you wish to change the font size 
  7532.                for each column you might used the value "</FONT>" to close the 
  7533.                previous font tag. This value becomes the default for all 
  7534.                columns. 
  7535.  
  7536.             -  DefineName_RECORD_AFTER_DATA_? 
  7537.                This value allows you to specify trailing data on a column by 
  7538.                column basis. 
  7539.  
  7540.          DefineName_AFTER 
  7541.           Unless you are not creating a table you are unlikely to want to 
  7542.           change the codes that end the table. 
  7543.  
  7544.          DefineName_RECORD_FILTER 
  7545.           The contents of this variable should be one or more rexx expressions. 
  7546.  
  7547.           Normally all records are displayed. A filter can examine all column 
  7548.           variables and modify them or tell PPWIZARD to ignore the record.  The 
  7549.           filter is not called for the heading record. 
  7550.  
  7551.           The following rexx variables and functions are relevant: 
  7552.  
  7553.             -  Remove 
  7554.                If this variable is set to any non blank value then the record 
  7555.                will be dropped, the variables value is shown when debugging so 
  7556.                it is recommended that the value be the reason for dropping the 
  7557.                record. 
  7558.  
  7559.                If the contents starts with 'EOF:' then the current record and 
  7560.                ALL following are dropped. 
  7561.  
  7562.             -  Column.? 
  7563.                The "Column" array holds the data for each field (that you are 
  7564.                interested in) of the current record in the order you provided. 
  7565.                For example "Column.2" holds the 2nd column's data. 
  7566.  
  7567.             -  Dropped.? 
  7568.                The "Dropped" array holds the data for each field (that you 
  7569.                dropped) of the current record in the order that they were 
  7570.                dropped. For example "Dropped.1" holds the first dropped field. 
  7571.  
  7572.             -  ThisRecordsCodes 
  7573.                This variable gets initialized for each record with the value 
  7574.                that you defined (or allowed to default) for the 
  7575.                "DefineName_RECORD" option.  You can add to or modify this 
  7576.                record in any way. The value of "{$Column1}" gets replaced with 
  7577.                the contents of the rexx variable "Column.1" etc. 
  7578.  
  7579.                If all your records are processed the same way then you should 
  7580.                not need to modify this variable.  It is useful where you might 
  7581.                want the output (row of table) to look different depending on 
  7582.                the records data.  In some cases this can be better done by 
  7583.                updating the rexx "Column.?" array. 
  7584.  
  7585.                If you need multiple lines you can of course use "<?NewLine>" 
  7586.                where required. 
  7587.  
  7588.             -  WriteLineToTmpImportFile() 
  7589.                The passed data is written to the output file, any line feed 
  7590.                characters will indicate the end of a line. 
  7591.  
  7592.             -  RecordFilter 
  7593.                If you don't need to do any more filtering then you can clear 
  7594.                this variable.  This will improve performance. 
  7595.  
  7596.          DefineName_PROTECT_START 
  7597.           By default will be set to the value <?ProtectFromPpwStart>. If you 
  7598.           have filter code that wants to generate PPWIZARD commands then you 
  7599.           will need to override this value. Have a look at the multiple HTML 
  7600.           pages example. 
  7601.  
  7602.          DefineName_PROTECT_END 
  7603.            By default will be set to the value <?ProtectFromPpwEnd>. 
  7604.  
  7605.  You should also check out an example of importing a file into multiple HTML 
  7606.  pages based on the contents of one of the fields. 
  7607.  
  7608.  Example 
  7609.  
  7610.  Assume we have a file as follows (IMPORTME.FIX): 
  7611.  
  7612.       First Name         Last Name           Job
  7613.       Dennis             Bareis              Programmer
  7614.       Wendy              Buxton              Librarian
  7615.       Fred               Nerk                Idiot
  7616.  
  7617.  We note that it has the following fields: 
  7618.  
  7619.        1. First Name, starting in column 1 ending at 18 
  7620.        2. Last Name, starting in column 20 ending at 38 
  7621.        3. Job, starting in column 40 ending at end of line. 
  7622.  
  7623.  The following line would import the fields in order (into a completely default 
  7624.  table layout): 
  7625.  
  7626.       #import IMPORTME.FIX FIX- '' "{1,1-18}First Name" "{2,20-38}Last Name" "{3,40-}Job"
  7627.  
  7628.  
  7629. ΓòÉΓòÉΓòÉ 7.21.4. #import - Multi Line Records ΓòÉΓòÉΓòÉ
  7630.  
  7631. #import - Multi Line Records 
  7632.  
  7633. This type of #Imports have clearly defined fields which you label.  You would 
  7634. frequently wish to display these in a table (say in a HTML page) however 
  7635. nothing says that you need to do so. 
  7636.  
  7637. Field Information Parameters 
  7638.  
  7639. On these types of imports "FieldInfo" followings the "DefineName" parameter. 
  7640.  
  7641. For each field you have defined in your database you must specify field 
  7642. information.  The field information is of the format: 
  7643.  
  7644.   {*,FieldName[,FieldOptions]}TitleText 
  7645.  
  7646. In place of the '*' you could specify the column number you wish to place the 
  7647. field but its usually easier to simply reorder the fields. 
  7648.  
  7649. The "field name" specifies the name you use in your database.  It can contain 
  7650. virtually any characters but must of course not contain the delimiter character 
  7651. ('=' by default).  Like all PPWIZARD names the name can contain international 
  7652. characters. 
  7653.  
  7654. You can optionally specify some field options which vary the way individual 
  7655. fields are processed.  Each field option is separated by a comma, valid options 
  7656. are: 
  7657.  
  7658.          REQUIRED 
  7659.           This field is required. You can supply a blank value. This validation 
  7660.           occurs whether or not the field is dropped. 
  7661.  
  7662.          NONBLANK 
  7663.           This field if supplied must be non blank. If not supplied its value 
  7664.           will become blank unless "REQUIRED" option was also specified. This 
  7665.           validation occurs whether or not the field is dropped. 
  7666.  
  7667.          NOASIS 
  7668.           By default all files go through AsIs() replacements, this option 
  7669.           allows you to prevent this occuring on particular fields if required. 
  7670.  
  7671.  The "title text" specifies the value for the field in the header record. Since 
  7672.  all fields must be defined we use a blank "title" to indicate that we don't 
  7673.  require a field and it should be dropped. 
  7674.  
  7675.  DEFINITIONS/OPTIONS 
  7676.  
  7677.  If you can't understand how these options work then I suggest you try using 
  7678.  /debug or #debug to watch what variables the import uses etc. 
  7679.  
  7680.          DefineName_BLANK_FIELD 
  7681.           Normally a blank field will be displayed as blank. You may wish to 
  7682.           display '-' instead. Another possiblity is to display a 1 by 1 
  7683.           transparent gif so as to have table borders around blank fields look 
  7684.           better. 
  7685.  
  7686.           For even more control (probably rare requirement): 
  7687.  
  7688.             -  DefineName_BLANK_COLUMN_? 
  7689.                This allows you to specify different blank replacement values 
  7690.                for each column. 
  7691.  
  7692.          DefineName_TAB_CHAR 
  7693.           Normally tabs are ignored by the import process.  This variable 
  7694.           allows you to replace them with something else. 
  7695.  
  7696.          DefineName_ASIS_TAGGING 
  7697.           This option can be used to adjust the conversion of what may be 
  7698.           problem characters (such as '<' in HTML). By default importing does 
  7699.           not handle/convert international characters such as umlauts to html 
  7700.           symbols but there is nothing preventing you from doing so. 
  7701.  
  7702.           Note that you will probably need to override this value (maybe others 
  7703.           as well) if you wished to expand any macros that the imported data 
  7704.           might contain (by default this is not done). 
  7705.  
  7706.          DefineName_BEFORE 
  7707.           You would probably only use this define if you didn't want to 
  7708.           generate a table at all. You may specify the string "{$Columns}" 
  7709.           which will get replaced with the number of fields to be displayed. If 
  7710.           this define is not used then you can use the following: 
  7711.  
  7712.             -  DefineName_TABLE_ATTRIBS 
  7713.                This value allows you to specify all HTML attributes of the 
  7714.                table apart from the number of columns. 
  7715.  
  7716.          DefineName_HEADER 
  7717.           This is used to control the "code" which handles the "heading" 
  7718.           record, <B>this does not have to be a html table</B>. You can specify 
  7719.           the string {$Column?} to represent a fields value (? = number of 
  7720.           field where 1 is the first). 
  7721.  
  7722.           If this define is not used then you can use the following: 
  7723.  
  7724.             -  DefineName_HEADING_COLUMNS 
  7725.                This value allows you to specify the column (HTML "<TH>" tags) 
  7726.                information to change alignment or colours of columns. This 
  7727.                value becomes the default for all columns. 
  7728.  
  7729.             -  DefineName_HEADING_COLUMN_? 
  7730.                This value allows you to specify the column (HTML "<TH>" tags) 
  7731.                information to change alignment or colours of specific columns. 
  7732.                Another use for this would be to specify the width of a column. 
  7733.                This value is only used for column number '?'. 
  7734.  
  7735.             -  DefineName_HEADING_BEFORE_DATA 
  7736.                This value allows you to specify some text to be placed in front 
  7737.                of the fields data, for example if you wish to change the font 
  7738.                size for each column you might used the value "<FONT SIZE=-1>". 
  7739.                This value becomes the default for all columns. 
  7740.  
  7741.             -  DefineName_HEADING_BEFORE_DATA_? 
  7742.                This value allows you to specify leading data on a column by 
  7743.                column basis. 
  7744.  
  7745.             -  DefineName_HEADING_AFTER_DATA 
  7746.                This value allows you to specify some text to be placed after 
  7747.                the fields data, for example if you wish to change the font size 
  7748.                for each column you might used the value "</FONT>" to close the 
  7749.                previous font tag. This value becomes the default for all 
  7750.                columns. 
  7751.  
  7752.             -  DefineName_HEADING_AFTER_DATA_? 
  7753.                This value allows you to specify trailing data on a column by 
  7754.                column basis. 
  7755.  
  7756.          DefineName_RECORD 
  7757.           This is used to control the "code" for each record, <B>this does not 
  7758.           have to be a html table</B>. You would definately define this option 
  7759.           if you didn't want a html table, you might wish to create s series of 
  7760.           #defines or maybe you are not generating html at all and need to 
  7761.           generate an IPF table. You can specify the string {$Column?} to 
  7762.           represent a fields value (? = number of field where 1 is the first). 
  7763.  
  7764.           If this define is not used then you can use the following: 
  7765.  
  7766.             -  DefineName_RECORD_COLUMNS 
  7767.                This value allows you to specify the column (HTML "<TD>" tags) 
  7768.                information to change alignment or colours of columns. This 
  7769.                value becomes the default for all columns. 
  7770.  
  7771.             -  DefineName_RECORD_COLUMN_? 
  7772.                This value allows you to specify the column (HTML "<TD>" tags) 
  7773.                information to change alignment or colours of specific columns. 
  7774.                Another use for this would be to specify the width of a column. 
  7775.                This value is only used for column number '?'. 
  7776.  
  7777.             -  DefineName_RECORD_BEFORE_DATA 
  7778.                This value allows you to specify some text to be placed in front 
  7779.                of the fields data, for example if you wish to change the font 
  7780.                size for each column you might used the value "<FONT SIZE=-1>". 
  7781.                This value becomes the default for all columns. 
  7782.  
  7783.             -  DefineName_RECORD_BEFORE_DATA_? 
  7784.                This value allows you to specify leading data on a column by 
  7785.                column basis. 
  7786.  
  7787.             -  DefineName_RECORD_AFTER_DATA 
  7788.                This value allows you to specify some text to be placed after 
  7789.                the fields data, for example if you wish to change the font size 
  7790.                for each column you might used the value "</FONT>" to close the 
  7791.                previous font tag. This value becomes the default for all 
  7792.                columns. 
  7793.  
  7794.             -  DefineName_RECORD_AFTER_DATA_? 
  7795.                This value allows you to specify trailing data on a column by 
  7796.                column basis. 
  7797.  
  7798.          DefineName_AFTER 
  7799.           Unless you are not creating a table you are unlikely to want to 
  7800.           change the codes that end the table. 
  7801.  
  7802.          DefineName_RECORD_FILTER 
  7803.           The contents of this variable should be one or more rexx expressions. 
  7804.  
  7805.           Normally all records are displayed. A filter can examine all column 
  7806.           variables and modify them or tell PPWIZARD to ignore the record.  The 
  7807.           filter is not called for the heading record. 
  7808.  
  7809.           The following rexx variables and functions are relevant: 
  7810.  
  7811.             -  Remove 
  7812.                If this variable is set to any non blank value then the record 
  7813.                will be dropped, the variables value is shown when debugging so 
  7814.                it is recommended that the value be the reason for dropping the 
  7815.                record. 
  7816.  
  7817.                If the contents starts with 'EOF:' then the current record and 
  7818.                ALL following are dropped. 
  7819.  
  7820.             -  Column.? 
  7821.                The "Column" array holds the data for each field (that you are 
  7822.                interested in) of the current record in the order you provided. 
  7823.                For example "Column.2" holds the 2nd column's data. 
  7824.  
  7825.             -  Dropped.? 
  7826.                The "Dropped" array holds the data for each field (that you 
  7827.                dropped) of the current record in the order that they were 
  7828.                dropped. For example "Dropped.1" holds the first dropped field. 
  7829.  
  7830.             -  ThisRecordsCodes 
  7831.                This variable gets initialized for each record with the value 
  7832.                that you defined (or allowed to default) for the 
  7833.                "DefineName_RECORD" option.  You can add to or modify this 
  7834.                record in any way. The value of "{$Column1}" gets replaced with 
  7835.                the contents of the rexx variable "Column.1" etc. 
  7836.  
  7837.                If all your records are processed the same way then you should 
  7838.                not need to modify this variable.  It is useful where you might 
  7839.                want the output (row of table) to look different depending on 
  7840.                the records data.  In some cases this can be better done by 
  7841.                updating the rexx "Column.?" array. 
  7842.  
  7843.                If you need multiple lines you can of course use "<?NewLine>" 
  7844.                where required. 
  7845.  
  7846.             -  WriteLineToTmpImportFile() 
  7847.                The passed data is written to the output file, any line feed 
  7848.                characters will indicate the end of a line. 
  7849.  
  7850.             -  GetMlField() 
  7851.                This routine can be called to obtain the value of a field (the 
  7852.                name of which is passed). You can access the fields data in a 
  7853.                more efficient manner using the "Column" and "Dropped" arrays 
  7854.                however this routine allows you to access a variable knowing its 
  7855.                name. 
  7856.  
  7857.             -  RecordFilter 
  7858.                If you don't need to do any more filtering then you can clear 
  7859.                this variable.  This will improve performance. 
  7860.  
  7861.          DefineName_DELIMITER 
  7862.           This is the character(s) that separate the name of a field from its 
  7863.           value. 
  7864.  
  7865.          DefineName_LINE_COMMENT_CHAR 
  7866.           This is the character that can be used to start a line for commenting 
  7867.           your file.  It defaults to the current PPWIZARD line comment 
  7868.           character. 
  7869.  
  7870.          DefineName_LINE_FILTER 
  7871.           The contents of this variable should be one or more rexx expressions. 
  7872.  
  7873.           If an expression is supplied for this option then the filter code 
  7874.           will be called for each non comment line found.  This allows you to 
  7875.           build extra smarts into the processing of records if you wish (for 
  7876.           example breaking a table into sections. 
  7877.  
  7878.           The following rexx variables are relevant: 
  7879.  
  7880.             -  MultiLine 
  7881.                This is the current line without leading and trailing 
  7882.                whitespace.  You may modify the contents if you need to. 
  7883.  
  7884.             -  Remove 
  7885.                If this variable is set to any non blank value then the line 
  7886.                will be dropped, the variables value is shown when debugging so 
  7887.                it is recommended that the value be the reason for dropping the 
  7888.                line. 
  7889.  
  7890.                If the contents starts with 'EOF:' then the current line and ALL 
  7891.                following are dropped. 
  7892.  
  7893.             -  LineFilter 
  7894.                If you don't need to do any more filtering then you can clear 
  7895.                this variable.  This will improve performance. 
  7896.  
  7897.          DefineName_PROTECT_START 
  7898.           By default will be set to the value <?ProtectFromPpwStart>. If you 
  7899.           have filter code that wants to generate PPWIZARD commands then you 
  7900.           will need to override this value. Have a look at the multiple HTML 
  7901.           pages example. 
  7902.  
  7903.          DefineName_PROTECT_END 
  7904.            By default will be set to the value <?ProtectFromPpwEnd>. 
  7905.  
  7906.  You should also check out an example of importing a file into multiple HTML 
  7907.  pages based on the contents of one of the fields. 
  7908.  
  7909.  Example - Multi Line Import 
  7910.  
  7911.  Lets assume you have created a database (called "WEBLINKS.ML") similar to: 
  7912.  
  7913.   ;--- First record ------------------------
  7914.      Name     :  Dennis Bareis
  7915.      Email    :  db0@anz.com
  7916.      Web Page :  www.labyrinth.net.au
  7917.      Comment  :  Really good site!
  7918.  
  7919.   ;--- Second record -----------------------
  7920.       Name:  Fredric Bald
  7921.    Comment:  This comment contains LT=< & GT=> characters
  7922.   Web Page:  www.somewhere.com
  7923.      Email:  fred@anz.com
  7924.  
  7925.  Then you can import the data and convert the email and web addresses into 
  7926.  hypertext links with: 
  7927.  
  7928.   <HTML><BODY>
  7929.   #DefineRexx ML_RECORD_FILTER
  7930.               Column.2 = "<A HREF='mailto:" || Column.2 || "'>" || Column.2 || "</A>"
  7931.               Column.3 = "<A HREF='http://" || Column.3 || "'>" || Column.3 || "</A>"
  7932.   #DefineRexx
  7933.   #define ML_DELIMITER      :
  7934.   #import WEBLINKS.ML ML  "" "{*,Name}Name" "{*,EMail}Email<BR>Address" "{*,Web Page}http://" "{*,Comment}Comment"
  7935.   </BODY></HTML>
  7936.  
  7937.  The following code imports the same database but demonstrates field reordering 
  7938.  (unusual requirement), field dropping (email address is not required) and 
  7939.  requiring all fields to be specified and non-blank: 
  7940.  
  7941.   <HTML><BODY>
  7942.   #define THIS1_RECORD_FILTER                                                         \
  7943.           Column.2 = "<A HREF='http://" || Column.2 || "'>" || Column.2 || "</A>"
  7944.   #define THIS1_DELIMITER      :
  7945.   #import WEBLINKS.ML ML  "THIS1"  "{2,Web Page,required,nonblank}http://"  \
  7946.                                    "{3,Comment,required,nonblank}Comment"   \
  7947.                                    "{1,Name,required,nonblank}Name"         \
  7948.                                    "{*,email}"
  7949.   </BODY></HTML>
  7950.  
  7951.  
  7952. ΓòÉΓòÉΓòÉ 7.21.5. #import - T2H ΓòÉΓòÉΓòÉ
  7953.  
  7954. #import - T2H 
  7955.  
  7956. This is a text to HTML #import mode (please read the #import documentation 
  7957. before trying to understand this section. This is a recent addition so please 
  7958. consider this import type "beta code" 
  7959.  
  7960. Sometimes you will wish to simply convert a a number of text files to a equal 
  7961. number of html files.  In this case you will probably wish to use the /Template 
  7962. switch and create a template for your background colors, titles, headers and 
  7963. footers that you require. 
  7964.  
  7965. TEXT SPECIFIC DEFINITIONS/OPTIONS 
  7966.  
  7967. These definitions are specific to the "T2H" import mode.  If you can't 
  7968. understand how they work then I suggest you try using /debug or #debug to watch 
  7969. what variables the import uses etc. 
  7970.  
  7971.          DefineName_BEFORE 
  7972.           These tags are used to set up any tags before the file is included. 
  7973.           By default the font size is decreased and "<PRE>" (preformated text) 
  7974.           mode is set up.  Modify or set to blank (to do nothing) if you wish. 
  7975.  
  7976.          DefineName_AFTER 
  7977.           These tags are used to set up any tags that are required after the 
  7978.           file is included.  This normally undoes anything you started using 
  7979.           the previous define. 
  7980.  
  7981.          DefineName_BLANK_LINES_TO 
  7982.           When text is processed in "PRE" mode (see above) you want to leave 
  7983.           blank lines as they are.  If however you set up the before tags to be 
  7984.           "<P>" and cleared the after tags then you could convert blank lines 
  7985.           to "<P>, in this way a blank line indicates the end of a paragraph. 
  7986.  
  7987.          DefineName_ASIS_TAGGING 
  7988.           This option can be used to adjust the conversion of what may be 
  7989.           problem characters (such as '<' in HTML). By default importing does 
  7990.           not handle/convert international characters such as umlauts to html 
  7991.           symbols but there is nothing preventing you from doing so. 
  7992.  
  7993.           Note that you will probably need to override this value (maybe others 
  7994.           as well) if you wished to expand any macros that the imported data 
  7995.           might contain (by default this is not done). 
  7996.  
  7997.          DefineName_TAB_CHAR 
  7998.           Normally tabs are ignored by the import process.  This variable 
  7999.           allows you to replace them with something else. 
  8000.  
  8001.          DefineName_HTTP_LINK 
  8002.           The import mode looks for "http:" type web addresses and by default 
  8003.           converts the URL into a hypertext link.  You may not wish this so you 
  8004.           could clear this variable.  You might wish to simply highlight the 
  8005.           URL. 
  8006.  
  8007.          DefineName_FTP_LINK 
  8008.           The import mode looks for "ftp:" type ftp addresses and by default 
  8009.           converts the URL into a hypertext link.  Otherwise as per the 
  8010.           "_HTTP_LINK" option. 
  8011.  
  8012.          DefineName_RECORD_FILTER 
  8013.           This option allows you to modify records before they are written to 
  8014.           the intermediate file for processing.  The value you supply for this 
  8015.           option is a rexx expression that can be interpreted.  You could use 
  8016.           this to simply drop lines or the data can be modified by you. 
  8017.  
  8018.           The following rexx variables are relevant: 
  8019.  
  8020.             -  Remove 
  8021.                If this variable is set to any non blank value then the line 
  8022.                will be dropped, the variables value is shown when debugging so 
  8023.                it is recommended that the value be the reason for dropping the 
  8024.                record. 
  8025.  
  8026.                If the contents starts with 'EOF:' then the current record and 
  8027.                ALL following are dropped. 
  8028.  
  8029.             -  T2hLineNumber 
  8030.                This is the line number of the current line. Do not modify this 
  8031.                variable. 
  8032.  
  8033.             -  T2hFileLine 
  8034.                This is the line as read from the file. Do not modify this 
  8035.                variable. 
  8036.  
  8037.             -  T2hNewLine 
  8038.                This is the read in line converted to something that will 
  8039.                display well in HTML. May have had email addresses etc tagged. 
  8040.                This variable may be modified. 
  8041.  
  8042.             -  T2hFilter 
  8043.                If you don't need to do any more filtering then you can clear 
  8044.                this variable.  This will improve performance. 
  8045.  
  8046.          DefineName_PROTECT_START 
  8047.           By default will be set to the value <?ProtectFromPpwStart>. If you 
  8048.           have filter code that wants to generate PPWIZARD commands then you 
  8049.           will need to override this value. Have a look at the multiple HTML 
  8050.           pages example. 
  8051.  
  8052.          DefineName_PROTECT_END 
  8053.            By default will be set to the value <?ProtectFromPpwEnd>. 
  8054.  
  8055.  EXAMPLE 
  8056.  
  8057.  This example imports a file and also extends the translation it will perform 
  8058.  to include 2 international characters. For no real reason we will also prevent 
  8059.  email addresses becoming "mailto" links and simply highlight email addresses 
  8060.  in a different color. 
  8061.  
  8062.       ;--- Save current Autotag state, set up international conversion, restore state ---
  8063.       #AutoTagState +
  8064.       #AutoTag      '╨ö'    'ä'
  8065.       #AutoTag      '╨Ö'    'ë'              ;;Only 2 for this example
  8066.       #AsIs         SETUP  INTERNATIONAL_SYMBOLS
  8067.       #AutoTagState -
  8068.  
  8069.       ;--- Update option so as to use the international chars as well as usual conversions -
  8070.       #define T2H_ASIS_TAGGING     IMPORT_HTML_BASIC                   \
  8071.                                    IMPORT_HTML_BOXGRAPHIC_TO_BOXTEXT   \
  8072.                                    INTERNATIONAL_SYMBOLS
  8073.  
  8074.       ;--- Simply for demonstrate puroses, remove email links and make "olive" ---
  8075.       #define T2H_MAILTO_LINK      <FONT COLOR=OLIVE>{$Url}</FONT>
  8076.  
  8077.       ;--- Import the text file ---
  8078.       #import README.TXT T2H       ""
  8079.  
  8080.  
  8081. ΓòÉΓòÉΓòÉ 7.21.6. #import - WRAP ΓòÉΓòÉΓòÉ
  8082.  
  8083. #import - WRAP 
  8084.  
  8085. This is a specialised #import facility. 
  8086.  
  8087. WRAP DEFINITIONS/OPTIONS 
  8088.  
  8089. These definitions are specific to the "WRAP" import mode.  If you can't 
  8090. understand how they work then I suggest you try using /debug or #debug to watch 
  8091. what variables the import uses etc. 
  8092.  
  8093.          DefineName_DROP_BLANK_LINES 
  8094.           You can specify whether or not blank lines (or lines where all fields 
  8095.           are blank) are significant.  The default is 'Y' to drop blank lines, 
  8096.           specify 'N' to prevent this. 
  8097.  
  8098.          DefineName_TAB_CHAR 
  8099.           Normally tabs are ignored by the import process.  This variable 
  8100.           allows you to replace them with something else. 
  8101.  
  8102.          DefineName_ASIS_TAGGING 
  8103.           This option can be used to adjust the conversion of what may be 
  8104.           problem characters (such as '<' in HTML). By default importing does 
  8105.           not handle/convert international characters such as umlauts to html 
  8106.           symbols but there is nothing preventing you from doing so. 
  8107.  
  8108.           Note that you will probably need to override this value (maybe others 
  8109.           as well) if you wished to expand any macros that the imported data 
  8110.           might contain (by default this is not done). 
  8111.  
  8112.          DefineName_RECORD_FILTER 
  8113.           This option switches between 2 alternative ways of handling each line 
  8114.           of data as follows: 
  8115.  
  8116.             1. Option Not used 
  8117.                The macro you identify with the "DefineName" parameter is passed 
  8118.                each line in turn (line passed as the macro parameter "Line"). 
  8119.  
  8120.                The line is passed as a rexx statement which when executed will 
  8121.                restore the line. 
  8122.  
  8123.                Your macro can do anything it likes as it determines what if 
  8124.                anything get generated. 
  8125.  
  8126.             2. Option used 
  8127.                The rexx code that you specify is called for each line. 
  8128.  
  8129.                The following rexx variables are relevant: 
  8130.  
  8131.                  -  Remove 
  8132.                     If this variable is set to any non blank value then the 
  8133.                     line will be dropped, the variables value is shown when 
  8134.                     debugging so it is recommended that the value be the reason 
  8135.                     for dropping the record. 
  8136.  
  8137.                     If the contents starts with 'EOF:' then the current record 
  8138.                     and ALL following are dropped. 
  8139.  
  8140.                  -  WrapLineNumber 
  8141.                     This is the line number of the current line. Do not modify 
  8142.                     this variable. 
  8143.  
  8144.                  -  WrapLine 
  8145.                     This is the line as read from the file.  You would normally 
  8146.                     modify this variable. 
  8147.  
  8148.  Example of WRAP Import 
  8149.  
  8150.  Assume "PEOPLE.TXT" contains people data of the following form (each record 
  8151.  spans 3 lines with blank lines being ignored and little validation of data): 
  8152.  
  8153.      Harry
  8154.      18
  8155.      male
  8156.  
  8157.  
  8158.      Lisa
  8159.      20
  8160.      female
  8161.  
  8162.  Then we could create a simple HTML table as follows: 
  8163.  
  8164.      ;--- Define some macros to handle the imported data ----------------------
  8165.      #define InitMultiLineFieldImport             \
  8166.              #RexxVar RxFieldCount = 0
  8167.      #define TermMultiLineFieldImport                                                     \
  8168.              #if [RxFieldCount <> 0]                                                      \
  8169.                  #error "Incorrectly specified record, have <??RxFieldCount> of 3 fields" \
  8170.              #endif
  8171.      #define EachLine                                                                     \
  8172.              ;--- "read" the line (no blank lines) -------                                \
  8173.              #evaluate+ ''  ^ThisLine = strip({$Line})^                                   \
  8174.                                                                                           \
  8175.              ;--- Save information -----------------------                                \
  8176.              #RexxVar RxFieldCount + 1                                                    \
  8177.              #RexxVar RxField_<??RxFieldCount> = ThisLine                                 \
  8178.                                                                                           \
  8179.              ;--- If end of record then output it --------                                \
  8180.              #if [RxFieldCount = 3]                                                       \
  8181.                  <TR><TD><??RxField_1> is <??RxField_3> and <??RxField_2> years old       \
  8182.                  #RexxVar RxFieldCount = 0                                                \
  8183.              #endif
  8184.  
  8185.  
  8186.      ;--- Start the table -----------------------------------------------------
  8187.      <$InitMultiLineFieldImport>
  8188.      <BR>
  8189.      <CENTER>
  8190.      <TABLE COLS=3 BORDER=1>
  8191.  
  8192.      ;--- Import the data (leaving default at dropping blank lines) -----------
  8193.      #import "PEOPLE.TXT" WRAP EachLine
  8194.  
  8195.      ;--- End The table -------------------------------------------------------
  8196.      </TABLE>
  8197.      </CENTER>
  8198.      <$TermMultiLineFieldImport>
  8199.  
  8200.  
  8201. ΓòÉΓòÉΓòÉ 7.22. #include ΓòÉΓòÉΓòÉ
  8202.  
  8203. #include 
  8204.  
  8205. A #include can be used to include another file for processing. This allows you 
  8206. to split a very large complicated html file into smaller logical pieces or more 
  8207. commonly to include standard 'header' files which contain all or most of the 
  8208. common definitions/text. 
  8209.  
  8210. You can nest to any level however each level adds to the number of open files 
  8211. (unless you use the /Inc2Cache switch) so in reality the nesting level is 
  8212. system dependant. Another problem may be that the rexx intrepreter will have 
  8213. its own limit on how far you can nest files. On OS/2 (and probably other 
  8214. operating systems) there are mechanisms for increasing the numbers of file 
  8215. handles if required. For example on OS/2 version 4 fixpack 6 onwards to 
  8216. increase the numbers of available handles by 30 add "SET SHELLHANDLESINC=30" to 
  8217. your config.sys file. 
  8218.  
  8219. The convention for extensions that I use are as follows: 
  8220.  
  8221.          .IT   - Internet Text  (source code) 
  8222.          .IH   - Internet Header (source code) 
  8223.          .HTM  - Generated HTML 
  8224.          .D    - Document Main  (source code) 
  8225.          .DH   - Document Header (source code) 
  8226.  
  8227.  It is possible for a header file to validate the release of a preprocessor if 
  8228.  it needs to use a feature which may not be available in older release, please 
  8229.  see the <?Version> example. 
  8230.  
  8231.  Note that there are times when you might wish to share a file between 'C' code 
  8232.  and PPWIZARD, you might just wish access to some of the values defined with 
  8233.  #define statements.  If you can't ensure that all commands (and their 
  8234.  parameters) that the 'C' code uses are valid in PPWIZARD then you could: 
  8235.  
  8236.        1. Conditionally include portions (example "#ifndef _PPWIZARD_"). Note 
  8237.           that "_PPWIZARD_" is automatically defined by PPWIZARD. 
  8238.  
  8239.        2. Use the #autotag commands to modify the contents on the file to 
  8240.           convert invalid statements to valid ones (bit of a hack but would 
  8241.           work). 
  8242.  
  8243.  It is also possible to include a part of the identified file if you can 
  8244.  identify some text which marks the start and end of the parts you wish. 
  8245.  
  8246.  Note that if an input file can't be located (relative to the current 
  8247.  directory), the following environment variables paths will also be searched 
  8248.  (in order): 
  8249.  
  8250.              1. PPWIZARD_INCLUDE
  8251.             2. INCLUDE
  8252.  
  8253.  After searching the above locations the directory PPWIZARD is located in is 
  8254.  also examined. 
  8255.  
  8256.  Syntax 
  8257.  
  8258.       [WhiteSpace]#include  ["|']FileName["|']  [["]Fragment["]]    OR
  8259.       [WhiteSpace]#include  <FileName>  [["]Fragment["]]
  8260.  
  8261.  The "FileName" specifies the file to be included. If the filename is or 
  8262.  contains #defined variables they will be replaced.  Note that the "<" & ">" 
  8263.  quoted form is to make it compatible with existing "C" headers so you can use 
  8264.  these if you require. 
  8265.  
  8266.  The optional "Fragment" parameter can be used to indicate the start and end of 
  8267.  the portion of an included file you wish to process.  The text must exist on 
  8268.  the line immediately before and immediately after the part you need.  Note 
  8269.  that the comparison is case sensitive on unfiltered text. This parameter 
  8270.  allows you to create a single include file from what might have been tens of 
  8271.  very small files (fragments).  I will use this parameter to contain all my 
  8272.  example code for my documentation. 
  8273.  
  8274.  Example 
  8275.  
  8276.       #include "common.ih"
  8277.  
  8278.       #include 'common.ih'     ^<CounterExample>^
  8279.  
  8280.       #include <common.h>
  8281.  
  8282.  
  8283. ΓòÉΓòÉΓòÉ 7.23. #Info ΓòÉΓòÉΓòÉ
  8284.  
  8285. #Info 
  8286.  
  8287. A #Info command allows you to display an informative message to the user. 
  8288.  
  8289. Similar commands are: 
  8290.  
  8291.        1. #Error 
  8292.        2. #Warning 
  8293.  
  8294.  Syntax 
  8295.  
  8296.       [WhiteSpace]#Info  [']InfoMessage[']
  8297.  
  8298.  The "InfoMessage" specifies the text to be displayed. 
  8299.  
  8300.  Example 
  8301.  
  8302.  Stupid example follows: 
  8303.  
  8304.       #Info "The value "fred" is fine."
  8305.  
  8306.  
  8307. ΓòÉΓòÉΓòÉ 7.24. #MacroSpace ΓòÉΓòÉΓòÉ
  8308.  
  8309. #MacroSpace 
  8310.  
  8311. A #MacroSpace command allows you to add or drop rexx procedures from the rexx 
  8312. macro space.  This can be useful if you have some rexx code which you 
  8313. frequently call in #if or #Evaluate commands as they should execute faster if 
  8314. they are available in the macro space. 
  8315.  
  8316. Syntax 
  8317.  
  8318.     [WhiteSpace]#MacroSpace  ["]Command["]  ["]RexxSourceFile["]  [["]FunctionName["] ]>
  8319.  
  8320. The "Command" should be "ADD" to add to the macro space or "DROP" to remove. 
  8321. It is not an error to ADD or DROP the same code more than once (even in a row). 
  8322. Also note that unless you perform a drop when you have finished using it it 
  8323. will take up space until you reboot OS/2. 
  8324.  
  8325. The "RexxSourceFile" is the name of a rexx source file. It should be a relative 
  8326. or absolute filename that currently exists. The path is not searched. 
  8327.  
  8328. If the optional "FunctionName" is not supplied then the function name is the 
  8329. "RexxSourceFile" without path or extension. 
  8330.  
  8331. Example 
  8332.  
  8333.     ;--- Load macro (routine called "ConfigInf" - any case) -----------------
  8334.     #MacroSpace   ADD    "CMD\CONFIGINF.CMD"
  8335.  
  8336.     #if ConfigInf('TCPIP_ADDRESS') = ''
  8337.         #Error "A TCPIP address is not available...."
  8338.     #endif
  8339.  
  8340.  
  8341. ΓòÉΓòÉΓòÉ 7.25. #OneLine ΓòÉΓòÉΓòÉ
  8342.  
  8343. #OneLine 
  8344.  
  8345. This command provides a simple way to spread a long line of over many lines 
  8346. without the need for line continuation characters at the end of each line. 
  8347.  
  8348. Basically you define a block, within this block all lines are combined with the 
  8349. character(s) you chose used to separate the lines. Note that if some lines 
  8350. within the block need different line separators, you can still use the normal 
  8351. line continuation characters for these lines! 
  8352.  
  8353. It is recommended that you do not use this command to handle rexx code, use the 
  8354. #DefineRexx command instead. 
  8355.  
  8356. Note that the restriction of on long imbedded ppwizard command mentioned in the 
  8357. line continuation section also applies here. 
  8358.  
  8359. Syntax 
  8360.  
  8361.     [WhiteSpace]#OneLine  [["]Separator["] [["]EndBlockMarker["]]>]>
  8362.  
  8363. If the Separator parameter is supplied it defines the zero or more characters 
  8364. that separate each line within the block. The default separator is a space. 
  8365.  
  8366. If the EndBlockMarker parameter is supplied this determines the text that marks 
  8367. the end of the block, this can be any text and by default is "#OneLineEnd" 
  8368. (note that the current prefix is used). Lines are combined until this text is 
  8369. located (in this exact case). 
  8370.  
  8371. EXAMPLE 
  8372.  
  8373.     #OneLine
  8374.        #define SomeWords
  8375.        The
  8376.        rain in
  8377.        sp               -\
  8378.        ain
  8379.        falls
  8380.        mainly
  8381.        on
  8382.        the
  8383.        plain
  8384.     #OneLineEnd    ;;Marks end of block!
  8385.  
  8386.     #OneLine '' '@@'
  8387.        T
  8388.        h
  8389.        e rain
  8390.     @@             ;;Marks end of block!
  8391.  
  8392.  
  8393. ΓòÉΓòÉΓòÉ 7.26. #OneLineEnd ΓòÉΓòÉΓòÉ
  8394.  
  8395. #OneLineEnd 
  8396.  
  8397. There is no such command although it may at first glance appear so. 
  8398.  
  8399. The text "#OneLineEnd" is simply the default end of #OneLine block marker if no 
  8400. alternative was specified. 
  8401.  
  8402.  
  8403. ΓòÉΓòÉΓòÉ 7.27. #OnExit ΓòÉΓòÉΓòÉ
  8404.  
  8405. #OnExit 
  8406.  
  8407. This command allows you to register some text which after all other processing 
  8408. is itself processed as if it were read from a file. 
  8409.  
  8410. This command is useful in standard header files where rather than requiring a 
  8411. user to use a macro before exiting it can be done automatically. An example of 
  8412. this might be in a common html header file where you use this command to 
  8413. automatically generate a standard footer at the end of your html. 
  8414.  
  8415. This command may be used any number of times, the "on exit" processing occurs 
  8416. in the order that the commands were executed. Note that the processing does not 
  8417. occur if a fatal error was detected. 
  8418.  
  8419. Syntax 
  8420.  
  8421.     [WhiteSpace]#OnExit  TheText
  8422.  
  8423. The text can be anything (macro reference etc). The parameter(s) are not 
  8424. expanded until exit processing occurs. 
  8425.  
  8426. The following is used in one of my header files: 
  8427.  
  8428.     ;--- Register checking macro ---
  8429.     #OnExit  <$NestingCheck>
  8430.  
  8431.  
  8432. ΓòÉΓòÉΓòÉ 7.28. #option ΓòÉΓòÉΓòÉ
  8433.  
  8434. #option 
  8435.  
  8436. This command is used to change the state of all the PPWIZARD options that you 
  8437. might wish to modify within a compile.  Other options which are global and 
  8438. can't be modified can be specified on the command line. 
  8439.  
  8440. The command allows you to save and restore the current state as well as update 
  8441. one or more options at a time. 
  8442.  
  8443. Most if not all options allow you to reset to the default value, this can 
  8444. either be a value determined by PPWIZARD or overriden by you with the /option 
  8445. switch. Note that to restore the original values you should use the 'PUSH' and 
  8446. 'POP' options. 
  8447.  
  8448. Note that since you can define options using the /option switch and default 
  8449. switches can be set up in the environment, you can simply override any PPWIZARD 
  8450. defaults you don't like without having to change your source code (or even your 
  8451. command line!). 
  8452.  
  8453. Syntax #1 - Saving + Restoring State 
  8454.  
  8455.     [WhiteSpace]#option  PUSH | POP
  8456.  
  8457. This form of the command saves or restores all options controlled by the 
  8458. #option command.  This allows you to make the required option changes and 
  8459. restore the original situation if required (for example in a header file). 
  8460.  
  8461. Syntax #2 - Setting An Option 
  8462.  
  8463.     [WhiteSpace]#option  OptionName[WhiteSpace]=[WhiteSpace]["]NewValue["]  ...
  8464.  
  8465. You may have any number of options specified on one statement. While not shown 
  8466. in the syntax diagram above you can specify "PUSH" any number of times as well. 
  8467. The following options are currently available: 
  8468.  
  8469.          AllowPack 
  8470.          AllowSpell 
  8471.          AtChangeType 
  8472.          CsReplacement 
  8473.          DebugLevel 
  8474.          DefineMacroReplace 
  8475.          ExtraIndent 
  8476.          ExpandX 
  8477.          HashPrefix 
  8478.          KeepIndent 
  8479.          LeaveBlankLines 
  8480.          LineComment 
  8481.          LineContinuation 
  8482.          MacroParmTags 
  8483.          Replace 
  8484.          ReplacementTags 
  8485.          WhiteSpace 
  8486.  
  8487.  Example 
  8488.  
  8489.       #option PUSH                 ;;Save Current state (we don't need to know what it was - EXCEPT '#' = command prefix!)
  8490.       #define FRED   ****
  8491.       <$Fred>                      ;;Fred will be subsituted here
  8492.  
  8493.       #option ReplacementTags="[]$?"
  8494.       [$Fred]                      ;;Fred will be substituted here
  8495.       <$Fred>                      ;;Fred will NOT be subsituted here
  8496.       #option POP                  ;;Restore original state
  8497.  
  8498.  
  8499. ΓòÉΓòÉΓòÉ 7.28.1. AllowPack ΓòÉΓòÉΓòÉ
  8500.  
  8501. AllowPack=OnOrOff 
  8502.  
  8503. This #option command allows you indicate lines of code which are not allowed to 
  8504. be packed. The default is that packing is allowed. 
  8505.  
  8506. This option can not be used to turn packing on, it simply identifies areas that 
  8507. should not be packed when packing is enabled. Packing can be enabled using the 
  8508. /Pack switch when generating rexx code or when you begin a #DefineRexx block. 
  8509.  
  8510. This command is useful where there are some non-obvious reasons why code should 
  8511. not be packed, for example if a bug in the rexx interpreter causes the code to 
  8512. fail when packed. 
  8513.  
  8514. If the "OnOrOff" parameter is empty then it defaults to the current default 
  8515. value, otherwise one of the following is expected:
  8516.  
  8517.                 ON
  8518.                 OFF
  8519.                 YES
  8520.               NO
  8521.  
  8522.  
  8523. ΓòÉΓòÉΓòÉ 7.28.2. AllowSpell ΓòÉΓòÉΓòÉ
  8524.  
  8525. AllowSpell=OnOrOff 
  8526.  
  8527. This #option command allows you indicate lines of code which are or are not 
  8528. allowed to be spell checked. The default is that spelling is allowed. 
  8529.  
  8530. This option would allow you to indicate that spelling should not occur when you 
  8531. generate javascript etc. 
  8532.  
  8533. Note that there are currently some inter related restrictions: 
  8534.  
  8535.        1. You can only turn spell checking on or off for whole lines. 
  8536.  
  8537.        2. This option may not work in a macro depending on your macro. 
  8538.  
  8539.  If the "OnOrOff" parameter is empty then it defaults to the current default 
  8540.  value, otherwise one of the following is expected:
  8541.  
  8542.                 ON
  8543.                 OFF
  8544.                 YES
  8545.               NO
  8546.  
  8547.  
  8548. ΓòÉΓòÉΓòÉ 7.28.3. AtChangeType ΓòÉΓòÉΓòÉ
  8549.  
  8550. AtChangeType=["]ChangeType["] 
  8551.  
  8552. This #option command lets you alter the way #AsIs and #AutoTag commands will 
  8553. perform replacements. The default method is a simple case sensitive replacement 
  8554. of text. 
  8555.  
  8556. Note that this command actually changes the way the #AutoTag stores the change 
  8557. and will only affect the replacement of those changes defined after this option 
  8558. was used. 
  8559.  
  8560. This command allows new alternative search and replace mechanisms to be slotted 
  8561. in without affecting any existing ones (clashing syntax etc). This method was 
  8562. chosen so that PPWIZARD could remain as fast as possible (it is written in rexx 
  8563. and so keeping performance reasonable sometimes takes compromises). 
  8564.  
  8565. The "ChangeType" parameter can be one of the following: 
  8566.  
  8567.        1. "" (blank) 
  8568.           This returns to the "default" mode. 
  8569.  
  8570.        2. CaseSensitive 
  8571.           The ReplaceString() routine is used. This is PPWIZARD's default mode 
  8572.           as its also the fastest. 
  8573.  
  8574.        3. CaseInsensitive 
  8575.           The ReplaceStringCI() routine is used. 
  8576.  
  8577.        4. Fixed 
  8578.           The CompareReplaceFixed() routine is used. 
  8579.  
  8580.  If you have some fantastic free PURE REXX search and replace code then I can 
  8581.  include it as a new PPWIZARD extension if you send me the code! 
  8582.  
  8583.  Example 1 
  8584.  
  8585.       #AutoTag "AAAA"   "XXXX"           ;;Change upper case "AAAA" only (assuming default mode)
  8586.  
  8587.       ;--- Use ReplaceStringCI() ---------------
  8588.       #option  PUSH AtChangeType=CaseInsensitive
  8589.       #AutoTag "BBBB"   "YyYy"           ;;Change "bbbb" in any case
  8590.       #AutoTag "CCCC"   "({*})"          ;;If "cccc" in any case is found then surround it by brackets
  8591.  
  8592.       ;--- Use CompareReplaceFixed() -----------
  8593.       #option AtChangeType="FIXED"
  8594.       #AutoTag      '@=,1=^HTML^@=,5=+x+'       'REM CS->@$1,*;'        ;;Case sensitive compare for "HTML" then "x"
  8595.       #AutoTag      '!i@=,1=^HTML^!S@=,-1=+x+'  'REM CI->@$1,*;'        ;;Case insensitive comapre for "HTML" + sensitive compare for "x"
  8596.       #AutoTag      '!L!i@=,1=^HTML^!S@=,5=+x+' 'REM CI+spaces->@$1,*;' ;;Same as above but ignoring whitespace (leading)
  8597.       #option  POP                       ;;Restore mode (PUSH/POP useful where original mode unknown etc)
  8598.  
  8599.  
  8600. ΓòÉΓòÉΓòÉ 7.28.4. CsReplacement ΓòÉΓòÉΓòÉ
  8601.  
  8602. CsReplacement=OnOrOff 
  8603.  
  8604. This #option command lets you alter the way ppwizard performs macro 
  8605. replacement. By default ppwizard macro names and macro parameter names are case 
  8606. insensitive. 
  8607.  
  8608. This command allows you to specify that case matters. This will give ppwizard 
  8609. more flexability when generating certain languages (such as XML). 
  8610.  
  8611. Note that Standard Definitions and rexx variable names are always case 
  8612. insensitive. 
  8613.  
  8614. You will need to be careful how you use this option (if not used early in the 
  8615. piece). Any macros created while this option was off were created in upper 
  8616. case, while any parameters within the definition don't matter until the 
  8617. replacement takes place. 
  8618.  
  8619. If the "OnOrOff" parameter is empty then it defaults to the current default 
  8620. value, otherwise one of the following is expected:
  8621.  
  8622.                 ON
  8623.                 OFF
  8624.                 YES
  8625.               NO
  8626.  
  8627.  Example 
  8628.  
  8629.       #option CsReplacement=ON
  8630.       #define AAAA   1111
  8631.       #define aaaa   2222
  8632.  
  8633.       ;--- Test Macro Replacement ---
  8634.       1. <$AAAA>     ;;Expect "1111"
  8635.       2. <$aaaa>     ;;Expect "2222"
  8636.       3. <$AAaa>     ;;Expect ppwizard to fail here
  8637.  
  8638.  
  8639. ΓòÉΓòÉΓòÉ 7.28.5. DebugLevel ΓòÉΓòÉΓòÉ
  8640.  
  8641. DebugLevel=["]Command1,Command2,...["] 
  8642.  
  8643. This #option command allows you to modify the output generated by /debug and 
  8644. #debug. 
  8645.  
  8646. PPWIZARD generates quite a bit of debug information when debug is on, this is 
  8647. fine for small source files but could easily become hundreds of thousands of 
  8648. lines in more complex situations.  If you are debugging a specific issue you 
  8649. may want to turn off debugging of unrelated events (this could also speed 
  8650. things up).  Of course being more selective about placement of #debug commands 
  8651. is another very good option (why debug the whole process?). 
  8652.  
  8653. Note that you can turn off almost all debugging output, doing so could make it 
  8654. very difficult to determine what is going on as statements such as #AutoTag 
  8655. could transform lines in what appears to be a magical manner.  Its up to you to 
  8656. determine what level you require. 
  8657.  
  8658. The Commands 
  8659.  
  8660. You may specify any numbers of commands, each separated by a comma. A command 
  8661. may begin with a '-' (to turn off) or '+' (turn on - default) the debug 
  8662. facility.  By default all debug output is generated. 
  8663.  
  8664. Valid debug facilities are: 
  8665.  
  8666.          ALL 
  8667.           This represents all debug options. This less "USER?" is the default 
  8668.           situation when PPWIZARD starts. 
  8669.  
  8670.          CONDITIONAL 
  8671.           #if, #endif output etc. 
  8672.  
  8673.          FOUNDVAR 
  8674.           Output to do with individual processing of your macros. 
  8675.  
  8676.          FOUNDVARPARMS 
  8677.           Output to do with individual processing of your macro's parameters. 
  8678.  
  8679.          FOUNDSTDVAR 
  8680.           Output to do with processing of individual Standard Macros. 
  8681.  
  8682.          AFTERREPLACE 
  8683.           All display of lines after some sort of replacement such as that by 
  8684.           #AsIs commands or your macros. 
  8685.  
  8686.          OPTIONS 
  8687.           Any output related to #option command. 
  8688.  
  8689.          OPSYS 
  8690.           Debug commands executed by operating system. 
  8691.  
  8692.          DEFINING 
  8693.           Output related to defining variables/macros. 
  8694.  
  8695.          MACROVALORDEF 
  8696.           PPWIZARD allows some things to be defined via a macro, there is 
  8697.           usually a default value.  This debugs these situations. 
  8698.  
  8699.          SPELLING 
  8700.           Show all spelling related output? 
  8701.  
  8702.          ASIS 
  8703.           Debug the #AsIs command. 
  8704.  
  8705.          AUTOTAG 
  8706.           Debug the #AutoTag command. 
  8707.  
  8708.          IMPORT 
  8709.           Debug any IMPORT statements PPWIZARD performs.  This will also 
  8710.           automatically adjust "MACROVALORDEF". 
  8711.  
  8712.          INTERPRET 
  8713.           Debug any INTERPRET statements PPWIZARD performs.  PPWIZARD does not 
  8714.           trace all but will show ones from #if and #evaluate commands. 
  8715.  
  8716.          EVALUATE 
  8717.           This debugs PPWIZARD functions that can be used in #evaluate or #if 
  8718.           commands etc. 
  8719.  
  8720.          REXXVAR 
  8721.           Debug the #RexxVar command. 
  8722.  
  8723.          REXXTRACE 
  8724.           Turn on rexx's inbuilt tracing for the execution of any rexx code 
  8725.           that gets executed by commands such as #if, #evaluate and #import. 
  8726.           This can be quite extensive so you might want to turn it off or lower 
  8727.           its level (see below) for general debugging. The format of the output 
  8728.           is described below. 
  8729.  
  8730.           The PPWIZARD macro "REXXTRACE" can be used to control the level of 
  8731.           rexx debugging.  The default level is "INTERMEDIATES" with "RESULTS" 
  8732.           generating less output while still being useful. The value you 
  8733.           specified is used in the rexx "TRACE ???" command. 
  8734.  
  8735.           Preceeding the value with '?' (as in "?Results") turns on interactive 
  8736.           trace.  You can execute any rexx commands to display or modify 
  8737.           values. 
  8738.  
  8739.          USER1 & USER2 
  8740.           Nothing in ppwizard itself makes use of these debug states, you can 
  8741.           make use these for your own purposes. You can use these two flags 
  8742.           either as a number (ranging from 0 to 3) for as 2 options (on or 
  8743.           off). To test the current state you need to call IsDebugOn(). 
  8744.  
  8745.           The value of USER bit one is 1 and USER bit two is 2. 
  8746.  
  8747.           Note that you could define your own debug "flags" using "/define 
  8748.           depending on the type of debug. The disadvantage on using these bits 
  8749.           is the mimimum extra debug output is the contents of each line as it 
  8750.           is processed. 
  8751.  
  8752.  REXXTRACE Output 
  8753.  
  8754.  This debug output is supplied by the rexx interpreter. The output from Regina 
  8755.  is much inferior to that of OS/2 however its still very useful. The following 
  8756.  can be used as a guide to understanding the output: 
  8757.  
  8758.          Every clause traced will be displayed with automatic formatting 
  8759.           (indentation) according to its logical depth of nesting and so on, 
  8760.           and the results (if requested) are indented an extra two spaces and 
  8761.           are enclosed in double quotation marks so that leading and trailing 
  8762.           blanks are apparent. 
  8763.  
  8764.          All lines displayed during tracing have a three-character prefix to 
  8765.           identify the type of data being traced.  The prefixes and their 
  8766.           definitions are the following: 
  8767.  
  8768.             -  *-* 
  8769.                Identifies the source of a single clause, that is, the data 
  8770.                actually in the program. 
  8771.  
  8772.             -  +++ 
  8773.                Identifies a trace message.  This can be the nonzero return code 
  8774.                from a command, the prompt message when interactive debug is 
  8775.                entered, an indication of a syntax error when in interactive 
  8776.                debug, or the traceback clauses after a syntax error in the 
  8777.                program. 
  8778.  
  8779.             -  >>> 
  8780.                Identifies the result of an expression (for TRACE R) or the 
  8781.                value assigned to a variable during parsing, or the value 
  8782.                returned from a subroutine call. 
  8783.  
  8784.             -  >.> 
  8785.                Identifies the value assigned to a placeholder during parsing. 
  8786.  
  8787.             -  >C> 
  8788.                The data traced is the name of a compound variable, traced after 
  8789.                substitution and before use, provided that the name had the 
  8790.                value of a variable substituted into it. 
  8791.  
  8792.             -  >F> 
  8793.                The data traced is the result of a function call. 
  8794.  
  8795.             -  >L> 
  8796.                The data traced is a literal (string or constant symbol). 
  8797.  
  8798.             -  >O> 
  8799.                The data traced is the result of an operation on two terms. 
  8800.  
  8801.             -  >P> 
  8802.                The data traced is the result of a prefix operation. 
  8803.  
  8804.             -  >V> 
  8805.                The data traced is the contents of a variable. 
  8806.  
  8807.  Example 
  8808.  
  8809.  Lets turn off all optional debugging except CONDITIONAL and OPTIONS: 
  8810.  
  8811.       #option DebugLevel=~-ALL,+CONDITIONAL,OPTIONS~
  8812.  
  8813.  
  8814. ΓòÉΓòÉΓòÉ 7.28.6. DefineMacroReplace ΓòÉΓòÉΓòÉ
  8815.  
  8816. DefineMacroReplace=OnOrOff 
  8817.  
  8818. This #option command allows you to modify the way #define and #DefineRexx 
  8819. commands are processed. 
  8820.  
  8821. Normally no replacement of any macros within it's parameters are performed. 
  8822. This has its good points (which is why its the default) but at times you may 
  8823. wish to override this behavior.  Apart from anything else in some cases this 
  8824. may speed things up. 
  8825.  
  8826. If the "OnOrOff" parameter is empty then it defaults to the current default 
  8827. value, otherwise one of the following is expected:
  8828.  
  8829.                 ON
  8830.                 OFF
  8831.                 YES
  8832.               NO
  8833.  
  8834.  Example 
  8835.  
  8836.  
  8837.       #define  AAAA   ValueAAAAOld
  8838.       #define  BBBB   <$AAAA>          ;;Macro AAAA was not replaced
  8839.       #option  DefineMacroReplace=ON   ;;When #define command executes replace any references to macros straight away.
  8840.       #define  CCCC   <$AAAA>          ;;Macro AAAA was replaced
  8841.       #define+ AAAA   ValueAAAANew     ;;Change Value of "AAAA"
  8842.       #option DefineMacroReplace=''    ;;Set to the default value
  8843.  
  8844.       ;--- Use macros defined above -----------------------------------------------
  8845.       <$BBBB>                          ;;Will generate "ValueAAAANew"
  8846.       <$CCCC>                          ;;Will generate "ValueAAAAOld"
  8847.  
  8848.  Example - Overcoming PPWIZARD Hang 
  8849.  
  8850.  The following is a fragment of a rexx program that supports a number of 
  8851.  standard rexx operators (but not all). It is trying to build up a list of 
  8852.  valid operators to display if the user chooses an unsupported one. 
  8853.  
  8854.  Because of the fact that by default a #define does not replace macros the 
  8855.  following example would fail with an infinite loop (if the #option commands 
  8856.  were removed). 
  8857.  
  8858.       /*--- Now compare --------------------------------------------*/
  8859.       #define CompRepOperator                                    \
  8860.               when   sr_Operator = '{$Operator}' then           %\
  8861.                      srCompRc = sr_bit {$Operator} sr_CompWith; -\
  8862.               #ifndef CSR_ValidList                             -\
  8863.                       #define  CSR_ValidList  {$Operator}       -\
  8864.               #elseif                                           -\
  8865.                       ;--- Careful or this line causes infinite loop ---    -\
  8866.                       #define+ CSR_ValidList  <$CSR_ValidList>, {$Operator} -\
  8867.               #endif
  8868.       select
  8869.           /*--- Test for supported compare operators ---------------------------*/
  8870.           #option PUSH DefineMacroReplace="ON"   ;;Used push/pop - Making no assumptions about current state
  8871.           <$CompRepOperator Operator='='>
  8872.           <$CompRepOperator Operator='<>'>
  8873.           <$CompRepOperator Operator='=='>
  8874.           <$CompRepOperator Operator='\=='>
  8875.           #option POP
  8876.  
  8877.           /*--- Not Valid ------------------------------------------------------*/
  8878.           otherwise
  8879.               Die("Unsupported operator of '" || sr_Operator || "' used", 'ONLY "<$CSR_ValidList>" are valid');
  8880.       end;
  8881.  
  8882.  
  8883. ΓòÉΓòÉΓòÉ 7.28.7. ExtraIndent ΓòÉΓòÉΓòÉ
  8884.  
  8885. ExtraIndent=["]IndentCmd["] 
  8886.  
  8887. Whenever "KeepIndent" mode is on the current indent value is added to the start 
  8888. of each line. The default extra indent is none. 
  8889.  
  8890. The "IndentCmd" parameter is a rexx command which produces a string value which 
  8891. will be used for extra indenting. 
  8892.  
  8893. Example 
  8894.  
  8895. The following command would increase any indenting by 10 spaces for following 
  8896. lines: 
  8897.  
  8898.     #option ExtraIndent=^copies(' ', 10)^  KeepIndent=ON
  8899.  
  8900.  
  8901. ΓòÉΓòÉΓòÉ 7.28.8. ExpandX ΓòÉΓòÉΓòÉ
  8902.  
  8903. ExpandX=["]CompleteList["] 
  8904.  
  8905. Normally <?xXX> codes are only expanded just before the data is written to the 
  8906. file (ie "LATE"). 
  8907.  
  8908. You may wish to vary when the replacement occurs. You can choose "COMMAND" to 
  8909. have replacements occur when a PPWIZARD command's parameters are expanded or 
  8910. "EARLY" to expand early on lines that are not PPWIZARD commands. 
  8911.  
  8912. The CompleteList parameter is a complete list of all the locations you wish 
  8913. expandion to occur on (COMMAND,EARLY,LATE) or "NONE" to completely turn off the 
  8914. expansion or "" to use default state. 
  8915.  
  8916. Example 
  8917.  
  8918.     ;--- Turn off all expansion ---
  8919.     #option ExpandX="NONE"
  8920.  
  8921.     ;--- Expand everywhere --------
  8922.     #option ExpandX="EARLY,LATE,COMMAND"
  8923.  
  8924.     ;--- Just expand early --------
  8925.     #option ExpandX="EARLY"
  8926.  
  8927.  
  8928. ΓòÉΓòÉΓòÉ 7.28.9. HashPrefix ΓòÉΓòÉΓòÉ
  8929.  
  8930. HashPrefix=["]NewPrefix["] 
  8931.  
  8932. This #option command allows you to modify the characters which tell PPWIZARD 
  8933. that a line contains a ppwizard command.  The default is that PPWIZARD commands 
  8934. begin with '#'. 
  8935.  
  8936. The NewPrefix parameter if empty sets the default value or specifies the new 
  8937. character or characters that preceed all commands. 
  8938.  
  8939. This command is useful if the language or file you are processing already uses 
  8940. the '#' character for its own reasons.  Rather than using many <?HashPrefix> 
  8941. codes it is much easier to move PPWIZARD out of the way. 
  8942.  
  8943. Example 
  8944.  
  8945.     #include "FILE1.IH"
  8946.     #option   hashprefix='!'        ;;Set prefix to '!'
  8947.     !include "FILE2.IH"
  8948.     !option   hashprefix=''         ;;Set prefix to default value
  8949.     #include "FILE3.IH"
  8950.  
  8951.  
  8952. ΓòÉΓòÉΓòÉ 7.28.10. KeepIndent ΓòÉΓòÉΓòÉ
  8953.  
  8954. KeepIndent=OnOrOff 
  8955.  
  8956. This #option command lets you determine whether or not leading whitespace is 
  8957. removed from lines that are read from a file. 
  8958.  
  8959. If you wish to keep whitespace you can also use the ExtraIndent option to 
  8960. indent each line if you wish. 
  8961.  
  8962. An alternative to this command is to use "<?Space>" to create whitespace as 
  8963. required. 
  8964.  
  8965. If the "OnOrOff" parameter is empty then it defaults to the current default 
  8966. value, otherwise one of the following is expected:
  8967.  
  8968.                 ON
  8969.                 OFF
  8970.                 YES
  8971.               NO
  8972.  
  8973.  Example 
  8974.  
  8975.       #Option  keepindent=ON
  8976.          Want Indent on this line
  8977.          As well as this line
  8978.       #Option  keepindent=OFF
  8979.  
  8980.  Example - Alternative way 
  8981.  
  8982.  The way demonstrated here can make it easier to format your source code so its 
  8983.  easy to read.  The following example will generate the same 2 lines as the 
  8984.  previous example: 
  8985.  
  8986.          <?Space>  Want Indent on this line
  8987.              <?Space>  As well as this line
  8988.  
  8989.  
  8990. ΓòÉΓòÉΓòÉ 7.28.11. LeaveBlankLines ΓòÉΓòÉΓòÉ
  8991.  
  8992. LeaveBlankLines=OnOrOff 
  8993.  
  8994. This #option command lets you determine whether or not blank lines are ignored. 
  8995. By default they are. 
  8996.  
  8997. If the "OnOrOff" parameter is empty then it defaults to the current default 
  8998. value, otherwise one of the following is expected:
  8999.  
  9000.                 ON
  9001.                 OFF
  9002.                 YES
  9003.               NO
  9004.  
  9005.  Example 
  9006.  
  9007.       #Option  LeaveBlankLines=ON      ;;Don't drop blank lines
  9008.  
  9009.  
  9010. ΓòÉΓòÉΓòÉ 7.28.12. LineComment ΓòÉΓòÉΓòÉ
  9011.  
  9012. LineComment=["]ASingleChar["] 
  9013.  
  9014. This #option command allows you to specify an alternative character (to ';') 
  9015. for starting comments. 
  9016.  
  9017. If NULL is specified for ASingleChar then comment removal is disabled. An empty 
  9018. value will set it back to the default, otherwise the character becomes the new 
  9019. comment character. The same character doubled up becomes the inline comment 
  9020. indicator. 
  9021.  
  9022. Example 
  9023.  
  9024.     ;--- This is a comment ---
  9025.     <B>         ;;Make the following text appear bold
  9026.     #option linecomment='@'
  9027.     </B>        @@Remove the bold attribute
  9028.  
  9029.     @--- This is a comment ---
  9030.  
  9031.     ;--- This is NO LONGER a comment ---
  9032.  
  9033.     @--- Restore default value (without hard coding it) ---
  9034.     #option linecomment=''             @@Better way is to use push/pop
  9035.  
  9036.     ;--- This is a comment (no comments after the following line executed) ---
  9037.     #option linecomment='NULL'         ;;Better way is to use push/pop
  9038.  
  9039.     ;--- This IS NOT a comment as comments disabled above --------------------
  9040.  
  9041.  
  9042. ΓòÉΓòÉΓòÉ 7.28.13. LineContinuation ΓòÉΓòÉΓòÉ
  9043.  
  9044. LineContinuation=["]FullOrPartialSpecification["] 
  9045.  
  9046. This #option command allows you to alter the current Line Continuation 
  9047. characters or indeed turn it off altogether. 
  9048.  
  9049. The "FullOrPartialSpecification" parameter can be one of the following: 
  9050.  
  9051.        1. NULL 
  9052.           In this case line continuation is turned off. 
  9053.  
  9054.        2. "" 
  9055.           An empty value means use the default value. 
  9056.  
  9057.        3. exactly one character 
  9058.           A single character value replaces the meaning of the '\' character. 
  9059.  
  9060.        4. exactly five characters 
  9061.           This replaces all special characters used for line continuation as 
  9062.           follows: 
  9063.  
  9064.             a. Replacement for '\'. 
  9065.             b. Replacement for down arrow character. 
  9066.             c. Replacement for '-'. 
  9067.             d. Replacement for '+'. 
  9068.             e. Replacement for space. 
  9069.  
  9070.  See the Line Continuation section of this document for more details. Your 
  9071.  editor may not like the low ascii down arrow character (or you may hate it!), 
  9072.  this option allows you to easily change it to another character of your 
  9073.  choice. 
  9074.  
  9075.  Example 1 
  9076.  
  9077.  We just wish to change the '\' so that we use '~' instead, so that we would 
  9078.  use '-~' etc: 
  9079.  
  9080.       #option LineContinuation="~"
  9081.  
  9082.  Example 2 
  9083.  
  9084.  Get rid of the down arrow variation, otherwise stick with defaults: 
  9085.  
  9086.       #option LineContinuation="\@-+ "   ;;'@\' now used for "newline" continuation
  9087.  
  9088.  Example 3 
  9089.  
  9090.  This example changes the down arrow character to the ASCII character decimal 
  9091.  20, no real reason however it does demonstrate a more complex possibility: 
  9092.  
  9093.       #evaluate  NewDownArrow  'd2c(20)'
  9094.       #option    LineContinuation=%\<$NewDownArrow>-+ ^
  9095.  
  9096.  
  9097. ΓòÉΓòÉΓòÉ 7.28.14. MacroParmTags ΓòÉΓòÉΓòÉ
  9098.  
  9099. MacroParmTags=["]NewTags["] 
  9100.  
  9101. This #option command is used to control the tags used within a macro definition 
  9102. to specify the location where a parameter replacement occurs.  Use with care. 
  9103. You would normally only use once at the start of your code - think about the 
  9104. impact on any existing macros. 
  9105.  
  9106. If an empty parameter is supplied then the default is restored otherwise the 
  9107. parameter must have exactly 3 characters in it.  The characters are in order: 
  9108.  
  9109.        1. Replacement for '{'. 
  9110.        2. Replacement for '}'. 
  9111.        3. Replacement for '$'. 
  9112.  
  9113.  Example 
  9114.  
  9115.       #option MacroParmTags="()%"   ;;Parameters now start with '(%' and end with ')'
  9116.       #option MacroParmTags=""      ;;Set to default values
  9117.  
  9118.  
  9119. ΓòÉΓòÉΓòÉ 7.28.15. Replace ΓòÉΓòÉΓòÉ
  9120.  
  9121. Replace=OnOrOff 
  9122.  
  9123. This #option command lets you to temporarily suspend replacement of definitions 
  9124. (and <?xXX> symbols).  This allows you to pass through some complex lines 
  9125. without having to spend ages working out how you can tag it so as not to expand 
  9126. out (or fail trying). 
  9127.  
  9128. It is recommended that you turn off substitution for as short a time as you 
  9129. require it.  Use with care. 
  9130.  
  9131. This command could be very handy if you needed to create a variable with a 
  9132. "#evaluate" command but you didn't want all the variables in the contents 
  9133. replaced straight away. 
  9134.  
  9135. If the "OnOrOff" parameter is empty then it defaults to the current default 
  9136. value, otherwise one of the following is expected:
  9137.  
  9138.                 ON
  9139.                 OFF
  9140.                 YES
  9141.               NO
  9142.  
  9143.  Example 
  9144.  
  9145.  The following is extracted out of a real macro that I had to set up, I was 
  9146.  having trouble with '<$endExample>' expanding out when what I really want is 
  9147.  the literal text: 
  9148.  
  9149.       #Option        REPLACE=OFF                        \
  9150.       #AutoTag       '<$endExample>'  '~$endExample>'   \
  9151.       #AutoTag       '<'              '<?xLT>'          \
  9152.       #AutoTag       '#'              '#'               \
  9153.       #AutoTag       '~$endExample>'  '<$endExample>'   \
  9154.       #Option        REPLACE=ON                         \
  9155.  
  9156.  
  9157. ΓòÉΓòÉΓòÉ 7.28.16. ReplacementTags ΓòÉΓòÉΓòÉ
  9158.  
  9159. ReplacementTags=["]NewTags["] 
  9160.  
  9161. This #option command is used to control the tags that are required to tell 
  9162. PPWIZARD that you wish macro substitution to occur.  Use with care. You would 
  9163. normally only use once at the start of your code - think about the impact on 
  9164. any existing macros. 
  9165.  
  9166. If an empty parameter is supplied then the default is used otherwise the 
  9167. parameter must have exactly 4 characters in it.  The characters are in order: 
  9168.  
  9169.        1. Replacement for '<'. 
  9170.        2. Replacement for '>'. 
  9171.        3. Replacement for '$'. 
  9172.        4. Replacement for '?'. 
  9173.  
  9174.  Example 
  9175.  
  9176.       #define FRED   ****
  9177.       <$Fred>                      ;;Fred will be subsituted here
  9178.  
  9179.       #option ReplacementTags="[]$?"
  9180.       [$Fred]                      ;;Fred will be subsituted here
  9181.       <$Fred>                      ;;Fred will NOT be subsituted here
  9182.       #option ReplacementTags=""   ;;Set to default values
  9183.  
  9184.  
  9185. ΓòÉΓòÉΓòÉ 7.28.17. WhiteSpace ΓòÉΓòÉΓòÉ
  9186.  
  9187. WhiteSpace=["]ExtraWhiteSpaceCharacters["] 
  9188.  
  9189. This #option command can be used to adjust the characters that PPWIZARD treats 
  9190. as whitespace.  A space is always treated as whitespace.  Each extra character 
  9191. you define will be converted to a real space as lines are read from files. 
  9192.  
  9193. The default whitespace for unix will ensure that PC based files whose lines end 
  9194. with carriage return then linefeed and may have end of file characters embedded 
  9195. in the file can be read without conversion. 
  9196.  
  9197. Example 
  9198.  
  9199. The following example shows how to define the "~" and form feed (hex code '0C') 
  9200. characters as whitespace.  In a unix environment we have removed the default 
  9201. whitespace conversions. 
  9202.  
  9203.     PPWIZARD INPUT.IT /Option:WhiteSpace="{x0C}~"
  9204.  
  9205.  
  9206. ΓòÉΓòÉΓòÉ 7.29. #output ΓòÉΓòÉΓòÉ
  9207.  
  9208. #output 
  9209.  
  9210. In most situations you would read one or more input files to generate a single 
  9211. output file.  There are situations where you'd like more control so that you 
  9212. can generate multiple files. 
  9213.  
  9214. You can nest to any level as only one output file is open at any time so file 
  9215. resources are not wasted. 
  9216.  
  9217. Syntax 
  9218.  
  9219.     [WhiteSpace]#output  ["]OutputName["]  [AsIs] [Append] [HTML|REXX|OTHER]
  9220.  
  9221. If "AsIs" was specified then the "OutputName" specifies the name of the output 
  9222. file otherwise the value is passed through the output specification provided 
  9223. with the "/Output" switch.  If the "OutputName" parameter is not specified at 
  9224. all then the previous output file is restored. 
  9225.  
  9226. Note that files specified for use "AsIs" do not have their case adjusted as 
  9227. specified on the /FileNames switch, if you require the case to be adjusted you 
  9228. will need to make use of the EnsureFileHasCorrectCase routine. 
  9229.  
  9230. If "Append" was specified then the output file is not deleted if it already 
  9231. exists. 
  9232.  
  9233. In some circumstances you may wish to generate a new file in a different 
  9234. processing mode to the current one, if this applies to you then choose on of 
  9235. "HTML", "REXX" or "OTHER". 
  9236.  
  9237. When a previous file is restored (no parameters) then new data is appended, 
  9238. otherwise the file is erased before writing the first line. 
  9239.  
  9240. Example 
  9241.  
  9242.     Line 1 of file 1
  9243.     Line 2 of file 1
  9244.     #output  '2nd'
  9245.        Line 1 of file 2
  9246.        Line 2 of file 2
  9247.        #output  'c:\path\3nd.ext' AsIs
  9248.            Line 1 of file 3
  9249.        #output
  9250.        Line 3 of file 2
  9251.     #output
  9252.     Line 3 of file 1
  9253.  
  9254. Example - Relative Filenames 
  9255.  
  9256. The following example show how you can calculate filenames which are relative 
  9257. to the directory where output normally goes (as determined by the /OUTPUT 
  9258. switch: 
  9259.  
  9260.     ;--- Macro to calculate filename relative to output directory ---------------
  9261.     #evaluate ""                       ^OutputDir = EnsureFileHasCorrectCase(_filespec('location', '<?OutputFile>'))^  ;;Only need to determine once!
  9262.     #define   FileRelativeToOutputDir  <??OutputDir>{$File}
  9263.  
  9264.     ;--- Test macro -------------------------------------------------------------
  9265.     InOutput.OUT         = <$FileRelativeToOutputDir FILE="InOutput.OUT">
  9266.     SubDir\InOutput.OUT  = <$FileRelativeToOutputDir FILE="SubDir\InOutput.OUT">
  9267.     ..\Parents.OUT       = <$FileRelativeToOutputDir FILE="..\Parents.OUT">
  9268.  
  9269. Example - Dropping output 
  9270.  
  9271. There may be time when you wish to drop some lines, for example you might be 
  9272. processing a file in a number of passes, this shows how you can do this under 
  9273. windows and OS/2: 
  9274.  
  9275.     #output "NUL" ASIS APPEND   ;;Drop output!
  9276.     This line gets dropped
  9277.     #output                     ;;Stop dropping output!
  9278.  
  9279.  
  9280. ΓòÉΓòÉΓòÉ 7.30. #Require ΓòÉΓòÉΓòÉ
  9281.  
  9282. #Require 
  9283.  
  9284. This is a simple command (Y2000 safe) which checks that the PPWIZARD 
  9285. preprocessor is capable of processing your code.  You would probably put this 
  9286. command in a header file that you distribute to users.  It will validate that 
  9287. the preprocessor they are using is new enough to handle your header file. 
  9288.  
  9289. Syntax 
  9290.  
  9291.     [WhiteSpace]#Require  ["]MinVersion["]
  9292.  
  9293. The "MinVersion" specifies the minumum version number of PPWIZARD.  The 
  9294. preprocessing will abort if the preprocessor is too old. 
  9295.  
  9296. Example 
  9297.  
  9298.     #require  98.216               ;;Want PPWIZARD version 98.216 or greater
  9299.  
  9300.  
  9301. ΓòÉΓòÉΓòÉ 7.31. #RexxVar ΓòÉΓòÉΓòÉ
  9302.  
  9303. #RexxVar 
  9304.  
  9305. This command allows you to manipulate rexx variables.  You can assign values to 
  9306. rexx variables, save them on a stack or give them the result of simple 
  9307. expressions which can be calculated much faster than with a #evaluate command. 
  9308.  
  9309. Note that you should try to pick unusual rexx variable names otherwise you 
  9310. might overwrite one that PPWIZARD uses.  It could cause very strange behaviour. 
  9311.  
  9312. Syntax #1 - Set Up "X" Variable 
  9313.  
  9314.     [WhiteSpace]#RexxVar  ["]VariableName["]  =x=   [']ItsValue[']
  9315.  
  9316. This is the only supported way to define "<?xXX>" codes. 
  9317.  
  9318. The "VariableName" parameter is the name of the 'x' variable and can contain 
  9319. virtually any character. 
  9320.  
  9321. The "ItsValue" parameter is the value which the rexx variable is to contain. 
  9322. Unlike the "#evaluate" command the new value is not first interpreted.  It is 
  9323. taken as is.  In practice I recommend using a quote character such as "^" as 
  9324. its unlikely to appear in the text, this may make it easier to follow in debug 
  9325. mode etc. This parameter can be a variables name (if unquoted). 
  9326.  
  9327. Syntax #2 - Assign to Rexx Variable 
  9328.  
  9329.     [WhiteSpace]#RexxVar  ["]VariableName["]  =   [']ItsValue[']
  9330.  
  9331. This form of the command lets you assign text directly to a rexx variable.  It 
  9332. is very useful in macros as you don't have to worry about quote issues while 
  9333. manipulating the data.  For example you would find it very difficult to 
  9334. uppercase some text (probably passed as a macro parameter) if it contained both 
  9335. a single quote and a double quote and in fact how would you know which if any 
  9336. it contained? 
  9337.  
  9338. The "VariableName" parameter is the full name of the rexx variable to be set. 
  9339.  
  9340. The "ItsValue" parameter is the value which the rexx variable is to contain. 
  9341. Unlike the "#evaluate" command the new value is not first interpreted.  It is 
  9342. taken as is.  In practice I recommend using a quote character such as "^" as 
  9343. its unlikely to appear in the text, this may make it easier to follow in debug 
  9344. mode etc.  This parameter can be a variables name (if unquoted). 
  9345.  
  9346. Syntax #3 - Save/Restore Variable on Stack 
  9347.  
  9348.     [WhiteSpace]#RexxVar  Operator ["]VariableName1["] ...   ;;New Format
  9349.     [WhiteSpace]#RexxVar  ["]VariableName["] Operator        ;;Old Format
  9350.  
  9351. The "VariableName" parameter(s) are the names of all variables being pushed or 
  9352. popped (saved or restored). 
  9353.  
  9354. The "Operator" parameter should be one of the following: 
  9355.  
  9356.        1. PUSH, Save rexx variable on stack. 
  9357.        2. POP, get last saved value from stack. 
  9358.  
  9359.  For each variable pushed there must be a corresponding pop.  It allows you to 
  9360.  use the same variable names in multiple places without danger of the value 
  9361.  getting modified (say by a #included file). 
  9362.  
  9363.  The variable parameters of the pop command are processed in reverse order so 
  9364.  that if you have push and pop commands with the more than one variable the 
  9365.  variable lists do not need to be reversed by you! 
  9366.  
  9367.  Syntax #3 - Simple Variable Manipulation 
  9368.  
  9369.       [WhiteSpace]#RexxVar  ["]VariableName["] Operator  Value2  [SourceValue1]>
  9370.  
  9371.  This form of the command lets you perform some simple operations.  These will 
  9372.  be much faster than performing the same operation using #evaluate. 
  9373.  
  9374.  The "VariableName" parameter is the full name of the rexx variable.  In this 
  9375.  format the variable will be given the result of a simple expression.  The 
  9376.  value is calculated as follows: 
  9377.  
  9378.       VariableName = SourceValue1 {Operator} Value2;
  9379.  
  9380.  The "Operator" parameter should be one of the following: 
  9381.  
  9382.        1. +, Addition. 
  9383.        2. -, Subtraction. 
  9384.        3. *, Multiply. 
  9385.        4. /, Divide. 
  9386.        5. //, Divide, want remainder. 
  9387.        6. %, Divide, want whole number. 
  9388.        7. || Concatenate. 
  9389.  
  9390.  The "Value2" is the value which would be added, subtracted etc from the source 
  9391.  value. 
  9392.  
  9393.  The "SourceValue1" parameter is the the source value.  By default the value 
  9394.  comes from "VariableName". 
  9395.  
  9396.  Both Value2 & SourceValue1 can be one of the following: 
  9397.  
  9398.          A rexx number. 
  9399.          A rexx variable. 
  9400.          A rexx literal. 
  9401.  
  9402.  Example 
  9403.  
  9404.  The following is sets the rexx variable "MyVar" to the literal "ABC" (as its 
  9405.  quoted): 
  9406.  
  9407.       #RexxVar       'MyVar'  =  /ABC/
  9408.  
  9409.  The following is sets the rexx variable "MyVar" to the contents of the 
  9410.  variable "ABC" (as its unquoted): 
  9411.  
  9412.       #RexxVar       'MyVar'  =  ABC
  9413.  
  9414.  The following two lines both set the rexx variable "MyVar" to the value 0: 
  9415.  
  9416.       #RexxVar       'MyVar'  =  0
  9417.       #RexxVar       MyVar    =  '0'
  9418.  
  9419.  The following is sets the rexx variable "MyVar" to the 3 chars (single quote, 
  9420.  space then double quote): 
  9421.  
  9422.       #RexxVar       'MyVar'  =  "' ""
  9423.  
  9424.  Notice that in the above example double quotes are used to contain a value 
  9425.  that contains a double quote.  This is a common reason for using the 
  9426.  "#RexxVar" command when accepting parameters in a macro. 
  9427.  
  9428.  The following is one line out of a larger macro, note that we have absolutely 
  9429.  no idea what text the parameter may expand to (for example it could easily 
  9430.  contain single quotes): 
  9431.  
  9432.       #RexxVar       'MyVar'  =  '{$Text}'
  9433.  
  9434.  The following lines all add one to the "Counter": 
  9435.  
  9436.       #RexxVar       Counter  +  1               ;;Counter = Counter +  1
  9437.       #RexxVar       Counter  +  1 Counter       ;;Counter = Counter +  1
  9438.       #RexxVar       Counter  -  "-1"            ;;Counter = Counter - -1
  9439.  
  9440.  A stupid example: 
  9441.  
  9442.       #RexxVar       Three    +  1 2             ;;Three = 2 + 1
  9443.  
  9444.  The following lines append to the end of the rexx variable "Grow": 
  9445.  
  9446.       #RexxVar       Grow  ||  ", a string"     ;;Grow = Grow || ", a string"
  9447.       #RexxVar       Grow  ||  AVariable        ;;Grow = Grow || AVariable
  9448.  
  9449.  The following lines could be used in a rexx header file to skip over any 
  9450.  subroutines the header contains after all header initialization has taken 
  9451.  place: 
  9452.  
  9453.       ;--- Initialization ---------------------------------------------------------
  9454.       HeaderVar1 = "Value1";
  9455.       HeaderVar2 = "Value2";
  9456.  
  9457.       ;--- Jump around code -------------------------------------------------------
  9458.       #RexxVar   "SkipName"   =     "SkipSubroutine_<?IncludeLevel>_<?Unique>"
  9459.       signal     <??SkipName>;                    ;;Jump past functions
  9460.       #RexxVar   PUSH "SkipName"                  ;;Save name of label
  9461.  
  9462.       HeaderFunction1:
  9463.          return('Value');
  9464.  
  9465.       ;----------------------------------------------------------------------------
  9466.       ;--- End of code ------------------------------------------------------------
  9467.       ;----------------------------------------------------------------------------
  9468.       #RexxVar   POP  "SkipName"                  ;;Restore saved value
  9469.       <??SkipName>:                               ;;Create label to mark end of code
  9470.  
  9471.  
  9472. ΓòÉΓòÉΓòÉ 7.32. #undef ΓòÉΓòÉΓòÉ
  9473.  
  9474. #undef 
  9475.  
  9476. A #undef command allows you to remove a definition so that it can be redefined 
  9477. without producing the warning message it normally will generate. 
  9478.  
  9479. Syntax 
  9480.  
  9481.     [WhiteSpace]#define  Variable
  9482.  
  9483. The "Variable" indicates which variable is to be removed. 
  9484.  
  9485. Example 
  9486.  
  9487.     #define Fred   Its value
  9488.     #undef  Fred;
  9489.     #define Fred   Its new value
  9490.  
  9491.  
  9492. ΓòÉΓòÉΓòÉ 7.33. #Warning ΓòÉΓòÉΓòÉ
  9493.  
  9494. #Warning 
  9495.  
  9496. A #Warning command is used to inform the user of an unusual situation. You 
  9497. would probably have extracted information (maybe from an environment variable) 
  9498. and found that all is not right.  This command allows you to warn the user but 
  9499. continue processing (you will get a return code of 1). 
  9500.  
  9501. The #Error command is similar but halts processing. 
  9502.  
  9503. Syntax 
  9504.  
  9505.     [WhiteSpace]#Warning  [']WarningId[']  [']WarningMessage[']
  9506.  
  9507. The "WarningId" parameter specifies a warning ID which can be used to help 
  9508. identify message (for example if you wished to use the /WarningsIgnore switch). 
  9509. You can supply an empty ID in case no ID is used. An ID can be as short or long 
  9510. as you wish. 
  9511.  
  9512. The "WarningMessage" parameter specifies the text of the warning to be 
  9513. displayed. 
  9514.  
  9515. Example 
  9516.  
  9517.     #if GetEnv('FRED') <> 1 & GetEnv('FRED') <> 2
  9518.         #Warning ^IV00^ "Invalid value for variable 'FRED', processing will continue"
  9519.     #endif
  9520.  
  9521.  
  9522. ΓòÉΓòÉΓòÉ 8. Standard Definitions ΓòÉΓòÉΓòÉ
  9523.  
  9524. Standard Definitions 
  9525.  
  9526. There are a number of "standard" definitions which have been predefined and can 
  9527. be placed almost anywhere in your source code.  The variables can be in any 
  9528. case, they are: 
  9529.  
  9530.          <??RexxVariable> 
  9531.          <?=RexxExpression> 
  9532.          <?CgiStart> 
  9533.          <?CompileTime> 
  9534.          <?DebugOn> 
  9535.          <?DirSlash> 
  9536.          <?Dollar> 
  9537.          <?Hash> 
  9538.          <?HashPrefix> 
  9539.          <?IncludeLevel> 
  9540.          <?InputComponent> 
  9541.          <?InputComponentLine> 
  9542.          <?InputFile> 
  9543.          <?NewestFileDateTime> 
  9544.          <?NewLine> 
  9545.          <?OpSys> 
  9546.          <?OutputFile> 
  9547.          <?OutputLevel> 
  9548.          <?OutputLine> 
  9549.          <?PpwizardAuthor> 
  9550.          <?PpwizardAuthorEmail> 
  9551.          <?PpwizardAuthorHomePage> 
  9552.          <?PpwizardGeneratorMetaTags> 
  9553.          <?PpwizardHomePage> 
  9554.          <?ProcessingMode> 
  9555.          <?ProtectFromPpwStart> 
  9556.          <?ProtectFromPpwEnd> 
  9557.          <?RestartLine> 
  9558.          <?RexxSkip> 
  9559.          <?RexxSkipTo> 
  9560.          <?SemiColon> 
  9561.          <?Space> 
  9562.          <?TemplateDataFile> 
  9563.          <?TotalOutputLines> 
  9564.          <?Unique> 
  9565.          <?Version> 
  9566.          <?xXX> 
  9567.  
  9568.  Note that you can define your own variations of "standard" variables with the 
  9569.  "#evaluate" command, for example to create an alternative way to display the 
  9570.  Compile Time. 
  9571.  
  9572.  EXAMPLES OF CREATING VARIABLES 
  9573.  
  9574.       ;--- Capture some HTML information ------------------------------------------
  9575.       #evaluate ShortNameHtml            "_filespec('name', '<?OutputFile>')"
  9576.       #evaluate ShortNameHtmlLowerCase   "translate('<$ShortNameHtml>', 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"
  9577.  
  9578.       ;--- Capture date/time information (<$DateTime> --> Friday March 27 1998 at 7<$colon>46pm ---
  9579.       #evaluate DateTime @date('WeekDay') || ' ' || date('Month') || ' ' || substr(date('Sorted'), 7, 2) || ' ' || left(date('Sorted'), 4) || ' at ' || time('Civil')@
  9580.  
  9581.       ;--- Create YY.DDD Version # (example "98.107") --------------------------------------
  9582.       #evaluate YYDDD    ~substr(date('Sorted'),3,2) || '.' || date('Days')~
  9583.  
  9584.      ;--- Outputs the size of a file (takes parameter "File") --------------------
  9585.      #define SizeOfFile                                                                                                         \
  9586.              #evaluate+  LocalFileName    ^ReplaceString("../{$File}", "/", "\")^                                               \
  9587.              #DependsOn  INPUT            "<$LocalFileName>"                                                                    \
  9588.              #evaluate+  TmpFileSize      ^AddCommasToDecimalNumber(stream("<$LocalFileName>", "c", "query size"))^             \
  9589.              #if "<$TmpFileSize>" = ""                                                                                          \
  9590.                  #error $Failed getting size of "<$LocalFileName>"$                                                             \
  9591.              #endif                                                                                                             \
  9592.              <$TmpFileSize>
  9593.      #define SizeOfFileInSmallFont   <FONT SIZE=-1>{$Before=""}<$SizeOfFile File=*{$File}*> bytes{$After=""}</FONT>
  9594.      #define (SizeOfFileInSmallFont) <$SizeOfFileInSmallFont File=*{$File}* Before='(' After=')'>
  9595.  
  9596.      ;--- Outputs the date (Ausi format... YES!) (takes parameter "File") --------
  9597.      #define DateOfFile                                                                                                                                \
  9598.              #evaluate+  LocalFileName    ^ReplaceString("../{$File}", "/", "\")^                                                                      \
  9599.              #DependsOn  INPUT            "<$LocalFileName>"                                                                                           \
  9600.              #evaluate+  TmpFileTime      ^stream("<$LocalFileName>", "c", "query datetime")^                                                          \
  9601.              #if "<$TmpFileTime>" = ""                                                                                                                 \
  9602.                  #error $Failed getting date/time of "<$LocalFileName>"$                                                                               \
  9603.              #endif                                                                                                                                    \
  9604.              #evaluate+ TmpFileDate       ~substr('<$TmpFileTime>', 4, 2) || '/' || left('<$TmpFileTime>', 2) || '/' || substr('<$TmpFileTime>', 7,2)~ \
  9605.              <$TmpFileDate>
  9606.      #define DateOfFileInSmallFont   <FONT SIZE=-1>{$Before=""}<$DateOfFile File=*{$File}*>{$After=""}</FONT>
  9607.  
  9608.  
  9609. ΓòÉΓòÉΓòÉ 8.1. <??RexxVariable> ΓòÉΓòÉΓòÉ
  9610.  
  9611. <??RexxVariable> 
  9612.  
  9613. It is possible to access rexx variables without first obtaining a copy of their 
  9614. value with the "#evaluate command.  Any symbol that starts with <?? and ends 
  9615. with > is a command to get the value of the rexx variable between. 
  9616.  
  9617. This is a Standard Definition which always exists (you don't need to #define 
  9618. it).  Note that you can create your own variations or completely new ones (see 
  9619. the examples). 
  9620.  
  9621. Example 
  9622.  
  9623. The following is an example which creates <H1>, <H2> HTML tagging etc: 
  9624.  
  9625.     #RexxVar    HeadingLevel = 1                      ;;Create a rexx variable (set to 1)
  9626.     #RexxVar    HeadingLevel + 1                      ;;Increase value by 1
  9627.  
  9628.     <H<??HeadingLevel>>A heading</H<??HeadingLevel>>  ;;Use it
  9629.  
  9630.  
  9631. ΓòÉΓòÉΓòÉ 8.2. <?=RexxExpression> ΓòÉΓòÉΓòÉ
  9632.  
  9633. <?=RexxExpression> 
  9634.  
  9635. A "variable" of this type allows you to evaluate a rexx expression, without 
  9636. using a separate #evaluate command.  Each time you use it a relatively slow 
  9637. rexx "interpret" command is required, so for performance reasons it is 
  9638. recommended that you: 
  9639.  
  9640.          Use "<??RexxVariable>" to obtain the contents of a single rexx 
  9641.           variable. 
  9642.  
  9643.          Use a single "#evaluate" command and store result for reuse rather 
  9644.           than using the same rexx "variable" expression multiple times. 
  9645.  
  9646.  The rexx expression has the limitation that it must not contain the ">" 
  9647.  character! 
  9648.  
  9649.  This is a Standard Definition which always exists (you don't need to #define 
  9650.  it).  Note that you can create your own variations or completely new ones (see 
  9651.  the examples). 
  9652.  
  9653.  Example 
  9654.  
  9655.       ;--- 5 '*' chars ----
  9656.       <?=copies('*',2)||copies('*',3)>
  9657.  
  9658.       ;--- Next line is invalid (compile will fail) ---
  9659.       <?=copies('*',2)||copies('>',3)>
  9660.  
  9661.  
  9662. ΓòÉΓòÉΓòÉ 8.3. <?CgiStart> ΓòÉΓòÉΓòÉ
  9663.  
  9664. <?CgiStart> 
  9665.  
  9666. This variable expands to the following 2 lines: 
  9667.  
  9668.        1. Content-type: text/html 
  9669.  
  9670.        2. Blank line 
  9671.  
  9672.  This is required at the start of all CGI output. 
  9673.  
  9674.  This is a Standard Definition which always exists (you don't need to #define 
  9675.  it).  Note that you can create your own variations or completely new ones (see 
  9676.  the examples). 
  9677.  
  9678.  
  9679. ΓòÉΓòÉΓòÉ 8.4. <?CompileTime> ΓòÉΓòÉΓòÉ
  9680.  
  9681. <?CompileTime> 
  9682.  
  9683. This variable contains the date and time the compile started. 
  9684.  
  9685. This is a Standard Definition which always exists (you don't need to #define 
  9686. it).  Note that you can create your own variations or completely new ones (see 
  9687. the examples). 
  9688.  
  9689.  
  9690. ΓòÉΓòÉΓòÉ 8.5. <?DebugOn> ΓòÉΓòÉΓòÉ
  9691.  
  9692. <?DebugOn> 
  9693.  
  9694. This variable will tell you whether debug is currently on or off by returning 
  9695. 'Y' (it's on) or 'N'. 
  9696.  
  9697. You could use this to add comments to generated output when debug is on etc. 
  9698.  
  9699. You could also use the IsDebugOn() to obtain similar information. 
  9700.  
  9701. This is a Standard Definition which always exists (you don't need to #define 
  9702. it).  Note that you can create your own variations or completely new ones (see 
  9703. the examples). 
  9704.  
  9705.  
  9706. ΓòÉΓòÉΓòÉ 8.6. <?DirSlash> ΓòÉΓòÉΓòÉ
  9707.  
  9708. <?DirSlash> 
  9709.  
  9710. This variable will indicate the character used to separate components of a 
  9711. path.  For most operating systems this will be '\' however UNIX uses '/' 
  9712. instead. 
  9713.  
  9714. This is a Standard Definition which always exists (you don't need to #define 
  9715. it).  Note that you can create your own variations or completely new ones (see 
  9716. the examples). 
  9717.  
  9718.  
  9719. ΓòÉΓòÉΓòÉ 8.7. <?Dollar> ΓòÉΓòÉΓòÉ
  9720.  
  9721. <?Dollar> 
  9722.  
  9723. This variable will be replaced by a '$' character. You may need to use it in 
  9724. some situations, for example in some cases where you wish to place '<$'. 
  9725.  
  9726. This symbol actually expands to a <?xXX> code and not the '$' character 
  9727. directly. In some cases this may not be what you wish and you should either 
  9728. define your own alternative or use some other method (#define may be suitable 
  9729. in a lot of cases) depending on your need. 
  9730.  
  9731. This is a Standard Definition which always exists (you don't need to #define 
  9732. it).  Note that you can create your own variations or completely new ones (see 
  9733. the examples). 
  9734.  
  9735.  
  9736. ΓòÉΓòÉΓòÉ 8.8. <?Hash> ΓòÉΓòÉΓòÉ
  9737.  
  9738. <?Hash> 
  9739.  
  9740. This variable will be replaced by a '#' character. 
  9741.  
  9742. This symbol actually expands to a <?xXX> code and not the '#' character 
  9743. directly. In some cases this may not be what you wish and you should either 
  9744. define your own alternative or use some other method (#define may be suitable 
  9745. in a lot of cases) depending on your need. 
  9746.  
  9747. This is a Standard Definition which always exists (you don't need to #define 
  9748. it).  Note that you can create your own variations or completely new ones (see 
  9749. the examples). 
  9750.  
  9751.  
  9752. ΓòÉΓòÉΓòÉ 8.9. <?HashPrefix> ΓòÉΓòÉΓòÉ
  9753.  
  9754. <?HashPrefix> 
  9755.  
  9756. This variable will be replaced by a current hash prefix character(s). This is 
  9757. whatever was set with the 'HashPrefix' option. 
  9758.  
  9759. This is a Standard Definition which always exists (you don't need to #define 
  9760. it).  Note that you can create your own variations or completely new ones (see 
  9761. the examples). 
  9762.  
  9763.  
  9764. ΓòÉΓòÉΓòÉ 8.10. <?IncludeLevel> ΓòÉΓòÉΓòÉ
  9765.  
  9766. <?IncludeLevel> 
  9767.  
  9768. This variable contains the level of file inclusion starting at 1.  For each 
  9769. #include it goes up by one and goes back down by 1 when processing of that file 
  9770. completes. 
  9771.  
  9772. This is a Standard Definition which always exists (you don't need to #define 
  9773. it).  Note that you can create your own variations or completely new ones (see 
  9774. the examples). 
  9775.  
  9776.  
  9777. ΓòÉΓòÉΓòÉ 8.11. <?InputComponent> ΓòÉΓòÉΓòÉ
  9778.  
  9779. <?InputComponent> 
  9780.  
  9781. This variable contains the full filename of the input file currently being 
  9782. processed. 
  9783.  
  9784. If you need to access the name of an input file other than the current one, 
  9785. then you will need to use the InputComponentLevel() routine. 
  9786.  
  9787. If you need the name of the base source file (determined from the InputMask 
  9788. specified on the command line) and you are obtaining the information within 
  9789. your standard header files you will need to use "<?InputFile>" instead. 
  9790.  
  9791. If you require the path or short name component then use the "#evaluate" 
  9792. command to subdivide the full name. 
  9793.  
  9794. This is a Standard Definition which always exists (you don't need to #define 
  9795. it).  Note that you can create your own variations or completely new ones (see 
  9796. the examples). 
  9797.  
  9798.  
  9799. ΓòÉΓòÉΓòÉ 8.12. <?InputComponentLine> ΓòÉΓòÉΓòÉ
  9800.  
  9801. <?InputComponentLine> 
  9802.  
  9803. This variable contains the current line number of the input file currently 
  9804. being processed. 
  9805.  
  9806. If you need to access the line number of other included files, then you will 
  9807. need to use the InputComponentLineLevel() routine. 
  9808.  
  9809. This is a Standard Definition which always exists (you don't need to #define 
  9810. it).  Note that you can create your own variations or completely new ones (see 
  9811. the examples). 
  9812.  
  9813.  
  9814. ΓòÉΓòÉΓòÉ 8.13. <?InputFile> ΓòÉΓòÉΓòÉ
  9815.  
  9816. <?InputFile> 
  9817.  
  9818. This variable contains the full filename of the base input file that was 
  9819. specified on the command line. 
  9820.  
  9821. This definition is useful to extract this information in your standard header 
  9822. files as "<?InputComponent>" could return the name of the header file! 
  9823.  
  9824. If you require the path or short name component then use the "#evaluate" 
  9825. command to subdivide the full name. 
  9826.  
  9827. This is a Standard Definition which always exists (you don't need to #define 
  9828. it).  Note that you can create your own variations or completely new ones (see 
  9829. the examples). 
  9830.  
  9831.  
  9832. ΓòÉΓòÉΓòÉ 8.14. <?NewestFileDateTime> ΓòÉΓòÉΓòÉ
  9833.  
  9834. <?NewestFileDateTime> 
  9835.  
  9836. This variable will return the newest source files date/time (so far) allowing 
  9837. you to date/timestamp your output with this information and not the date/time 
  9838. of the compile. 
  9839.  
  9840. Note that the "compiler" (PPWIZARD) is considered to be a source file as it 
  9841. also determines the format of the output. If the variable is used after the 
  9842. last #include to be processed then the value returned must be the date/time of 
  9843. the latest file (so unless you are added the timestamp information near the end 
  9844. of your output you may not be able to make use of this variable). 
  9845.  
  9846. The information is returned in the same format as that returned by the 
  9847. "GetFileTimeStamp()" routine (except that -1 is not possible).  Also have a 
  9848. look at it's example as the macro it shows could be used with very minor 
  9849. modification.  It is possible to work out the day of the week if you use the 
  9850. basedate routine. 
  9851.  
  9852. This is a Standard Definition which always exists (you don't need to #define 
  9853. it).  Note that you can create your own variations or completely new ones (see 
  9854. the examples). 
  9855.  
  9856.  
  9857. ΓòÉΓòÉΓòÉ 8.15. <?NewLine> ΓòÉΓòÉΓòÉ
  9858.  
  9859. <?NewLine> 
  9860.  
  9861. This variable forces following text onto the next line.  It can be useful if 
  9862. you need to pass the generated html through other tools which can't handle long 
  9863. lines.  In macros (created with "#define") this is the only way to ensure that 
  9864. multiple lines are generated. 
  9865.  
  9866. Note that this variable is the only way to ensure that the line is terminated 
  9867. correctly as the "/CrLf" switch (and others) may vary the appropriate codes 
  9868. that need to be generated. 
  9869.  
  9870. This symbol actually expands to a <?xXX> code and not the 'newline' character 
  9871. directly. In some cases this may not be what you wish and you should either 
  9872. define your own alternative or use some other method (#define may be suitable 
  9873. in a lot of cases) depending on your need. 
  9874.  
  9875. This is a Standard Definition which always exists (you don't need to #define 
  9876. it).  Note that you can create your own variations or completely new ones (see 
  9877. the examples). 
  9878.  
  9879.  
  9880. ΓòÉΓòÉΓòÉ 8.16. <?OpSys> ΓòÉΓòÉΓòÉ
  9881.  
  9882. <?OpSys> 
  9883.  
  9884. This variable indicates the operating system you are running on and is one of 
  9885. the following values: 
  9886.  
  9887.          OS/2 
  9888.          DOS 
  9889.          WINNT 
  9890.          WIN98 
  9891.          WIN95 
  9892.          UNIX 
  9893.  
  9894.  If you need to know which version of a platform you will need to do more work 
  9895.  yourself. 
  9896.  
  9897.  This is a Standard Definition which always exists (you don't need to #define 
  9898.  it).  Note that you can create your own variations or completely new ones (see 
  9899.  the examples). 
  9900.  
  9901.  
  9902. ΓòÉΓòÉΓòÉ 8.17. <?OutputFile> ΓòÉΓòÉΓòÉ
  9903.  
  9904. <?OutputFile> 
  9905.  
  9906. This variable contains the full filename of the current output file. 
  9907.  
  9908. If you require the path or short name component then use the "#evaluate" 
  9909. command to subdivide the full name. 
  9910.  
  9911. This is a Standard Definition which always exists (you don't need to #define 
  9912. it).  Note that you can create your own variations or completely new ones (see 
  9913. the examples). 
  9914.  
  9915.  
  9916. ΓòÉΓòÉΓòÉ 8.18. <?OutputLevel> ΓòÉΓòÉΓòÉ
  9917.  
  9918. <?OutputLevel> 
  9919.  
  9920. This variable contains the output nesting level.  When its '1', the output goes 
  9921. to the default output file, each #Output with filename adds one while a #output 
  9922. without file subtracts one. 
  9923.  
  9924. This variable would be handy in complex macro sets where #output commands are 
  9925. automatically generated. 
  9926.  
  9927. This is a Standard Definition which always exists (you don't need to #define 
  9928. it).  Note that you can create your own variations or completely new ones (see 
  9929. the examples). 
  9930.  
  9931. Example 
  9932.  
  9933.     This line is at Output Level 1
  9934.     #output  '2nd'
  9935.        This line is at Output Level 2
  9936.        #output 'c<$colon>\path\3nd.ext' AsIs
  9937.                This line is at Output Level 3
  9938.        #output
  9939.        This line is at Output Level 2
  9940.     #output
  9941.     This line is at Output Level 1
  9942.  
  9943.  
  9944. ΓòÉΓòÉΓòÉ 8.19. <?OutputLine> ΓòÉΓòÉΓòÉ
  9945.  
  9946. <?OutputLine> 
  9947.  
  9948. This variable contains the line number of the next line to be generated ("this 
  9949. line") into the current output file. 
  9950.  
  9951. This is a Standard Definition which always exists (you don't need to #define 
  9952. it).  Note that you can create your own variations or completely new ones (see 
  9953. the examples). 
  9954.  
  9955.  
  9956. ΓòÉΓòÉΓòÉ 8.20. <?PpwizardAuthor> ΓòÉΓòÉΓòÉ
  9957.  
  9958. <?PpwizardAuthor> 
  9959.  
  9960. This variable contains the name of the developer of the PPWIZARD program. Use 
  9961. if you wish to make mention of PPWIZARD on your homepages. 
  9962.  
  9963. This is a Standard Definition which always exists (you don't need to #define 
  9964. it).  Note that you can create your own variations or completely new ones (see 
  9965. the examples). 
  9966.  
  9967.  
  9968. ΓòÉΓòÉΓòÉ 8.21. <?PpwizardAuthorEmail> ΓòÉΓòÉΓòÉ
  9969.  
  9970. <?PpwizardAuthorEmail> 
  9971.  
  9972. This variable contains the email address of the developer of the PPWIZARD 
  9973. program. Use if you wish to make mention of PPWIZARD on your homepages. 
  9974.  
  9975. This is a Standard Definition which always exists (you don't need to #define 
  9976. it).  Note that you can create your own variations or completely new ones (see 
  9977. the examples). 
  9978.  
  9979.  
  9980. ΓòÉΓòÉΓòÉ 8.22. <?PpwizardAuthorHomePage> ΓòÉΓòÉΓòÉ
  9981.  
  9982. <?PpwizardAuthorHomePage> 
  9983.  
  9984. This variable contains the internet address of the computer home page of the 
  9985. developer of the PPWIZARD program. Use if you wish to make mention of PPWIZARD 
  9986. on your homepages. 
  9987.  
  9988. Note that I recommend that if you point to other pages of mine that you either 
  9989. use a #evaluate on this variable to obtain the base path or validate that it 
  9990. contains what you expect (and fail with #error if it doesn't).  This way if I 
  9991. change my homepage you will be informed via a new version of PPWIZARD. 
  9992.  
  9993. This is a Standard Definition which always exists (you don't need to #define 
  9994. it).  Note that you can create your own variations or completely new ones (see 
  9995. the examples). 
  9996.  
  9997.  
  9998. ΓòÉΓòÉΓòÉ 8.23. <?PpwizardGeneratorMetaTags> ΓòÉΓòÉΓòÉ
  9999.  
  10000. <?PpwizardGeneratorMetaTags> 
  10001.  
  10002. This variable contains the default HTML meta tags for this program. 
  10003.  
  10004. This is a Standard Definition which always exists (you don't need to #define 
  10005. it).  Note that you can create your own variations or completely new ones (see 
  10006. the examples). 
  10007.  
  10008.  
  10009. ΓòÉΓòÉΓòÉ 8.24. <?ProcessingMode> ΓòÉΓòÉΓòÉ
  10010.  
  10011. <?ProcessingMode> 
  10012.  
  10013. This variable contains the current processing mode, that is one of the 
  10014. following: 
  10015.  
  10016.        1. HTML 
  10017.        2. REXX 
  10018.        3. OTHER 
  10019.  
  10020.  The mode can be set or specified in these situations: 
  10021.  
  10022.        1. /REXX 
  10023.        2. /HTML 
  10024.        3. /OTHER 
  10025.        4. #output 
  10026.  
  10027.  This is a Standard Definition which always exists (you don't need to #define 
  10028.  it).  Note that you can create your own variations or completely new ones (see 
  10029.  the examples). 
  10030.  
  10031.  
  10032. ΓòÉΓòÉΓòÉ 8.25. <?PpwizardHomePage> ΓòÉΓòÉΓòÉ
  10033.  
  10034. <?PpwizardHomePage> 
  10035.  
  10036. This variable contains the address of this programs HTML home page. Use if you 
  10037. wish to make mention of PPWIZARD on your homepages. 
  10038.  
  10039. This is a Standard Definition which always exists (you don't need to #define 
  10040. it).  Note that you can create your own variations or completely new ones (see 
  10041. the examples). 
  10042.  
  10043.  
  10044. ΓòÉΓòÉΓòÉ 8.26. <?ProtectFromPpwStart> ΓòÉΓòÉΓòÉ
  10045.  
  10046. <?ProtectFromPpwStart> 
  10047.  
  10048. This variable expands to one or more commands that ensure that following lines 
  10049. are protected from change by PPWIZARD.  As examples, this prevents leading 
  10050. whitespace removal and text such as "#define" as being treated as commands. 
  10051. This is similar to the "#AsIs" command except that no "as is" tagging is 
  10052. performed and that PPWIZARD commands are not precessed. 
  10053.  
  10054. Note that this does not do any extra tagging such as that required to ensure 
  10055. that the text appears the same in a browser or ipf viewer etc.  This must be 
  10056. taken care of by you ("#AutoTag"). 
  10057.  
  10058. You must use "<?ProtectFromPpwEnd>" at the end of the lines you wish to 
  10059. protect. 
  10060.  
  10061. This is a Standard Definition which always exists (you don't need to #define 
  10062. it).  Note that you can create your own variations or completely new ones (see 
  10063. the examples). 
  10064.  
  10065.  
  10066. ΓòÉΓòÉΓòÉ 8.27. <?ProtectFromPpwEnd> ΓòÉΓòÉΓòÉ
  10067.  
  10068. <?ProtectFromPpwEnd> 
  10069.  
  10070. Please see "<?ProtectFromPpwStart>" for details. 
  10071.  
  10072. This is a Standard Definition which always exists (you don't need to #define 
  10073. it).  Note that you can create your own variations or completely new ones (see 
  10074. the examples). 
  10075.  
  10076.  
  10077. ΓòÉΓòÉΓòÉ 8.28. <?RestartLine> ΓòÉΓòÉΓòÉ
  10078.  
  10079. <?RestartLine> 
  10080.  
  10081. By the time PPWIZARD macro replacement has taken place its already decided that 
  10082. the line does not contain a PPWIZARD command.  If you wish to dynamically 
  10083. generate PPWIZARD commands you need to use this variable at the start of every 
  10084. command (you could have more than one). 
  10085.  
  10086. Another possible reason for using this define is that PPWIZARD expands 
  10087. definitions in a single pass from left to right.  This means that you could not 
  10088. build up a reference to a variable from components unless you include this 
  10089. define. 
  10090.  
  10091. PPWIZARD will stop replacement of macros etc as soon as it has expanded the 
  10092. first define of this type on the line so its position on a line can greatly 
  10093. affect the way expansion occurs. The use of this variable could cause other 
  10094. unwanted affects, it is up to you to test to ensure you are obtaining the 
  10095. results you require. 
  10096.  
  10097. This is a Standard Definition which always exists (you don't need to #define 
  10098. it).  Note that you can create your own variations or completely new ones (see 
  10099. the examples). 
  10100.  
  10101. Example 
  10102.  
  10103. In this example the intention is to create the macro variable "X": 
  10104.  
  10105.     ;--- "Command" contains the command we want executed ---
  10106.     #define Command  #define X XXXXXXXXXXXXXXXXXXXXX
  10107.  
  10108.     Attempt 1 - Fails
  10109.     ~~~~~~~~~~~~~~~~~
  10110.     <$Command>
  10111.  
  10112.     Attempt 2 - Works
  10113.     ~~~~~~~~~~~~~~~~~
  10114.     <?RestartLine><$Command>
  10115.  
  10116.     Test Definition
  10117.     ~~~~~~~~~~~~~~~
  10118.     Number of x's ==> <$X>
  10119.  
  10120.  
  10121. ΓòÉΓòÉΓòÉ 8.29. <?RexxSkip> ΓòÉΓòÉΓòÉ
  10122.  
  10123. <?RexxSkip> 
  10124.  
  10125. This symbol is used in conjunction with the "<?RexxSkipTo>" symbol to simplify 
  10126. the "skipping" of subroutines within a rexx header file. 
  10127.  
  10128. A header file will frequently include some initialization code followed by some 
  10129. routines.  The recommended place to include header files is at the start of 
  10130. your mainline code module.  To be able to hold common procedures in the header 
  10131. file you must skip over them after you have performed any required 
  10132. initialization. 
  10133.  
  10134. You could simply use a "signal EndRexxHeader" before the procedures and 
  10135. "EndRexxHeader:" after, however then you need to create a new label every time 
  10136. and it becomes difficult to include a header file more than once. 
  10137.  
  10138. This is a Standard Definition which always exists (you don't need to #define 
  10139. it).  Note that you can create your own variations or completely new ones (see 
  10140. the examples). 
  10141.  
  10142. Example - EXAMPLE.XH 
  10143.  
  10144.     /*--- Initialization for "EXAMPLE.XH" ---*/
  10145.     call InitStuff;
  10146.     <?RexxSkip>
  10147.  
  10148.     InitStuff:
  10149.        ...
  10150.        return;
  10151.  
  10152.     MoreCode:
  10153.        ...
  10154.        return;
  10155.  
  10156.     /*--- End of rexx header ---*/
  10157.     <?RexxSkipTo>
  10158.  
  10159.  
  10160. ΓòÉΓòÉΓòÉ 8.30. <?RexxSkipTo> ΓòÉΓòÉΓòÉ
  10161.  
  10162. <?RexxSkipTo> 
  10163.  
  10164. This symbol is used in conjunction with the "<?RexxSkip>" symbol to simplify 
  10165. the "skipping" of subroutines within a rexx header file. 
  10166.  
  10167. Every use of "<?RexxSkip>" must be followed by the use of the "<?RexxSkipTo>" 
  10168. symbol. 
  10169.  
  10170. This is a Standard Definition which always exists (you don't need to #define 
  10171. it).  Note that you can create your own variations or completely new ones (see 
  10172. the examples). 
  10173.  
  10174. Example 
  10175.  
  10176. See <?RexxSkip>. 
  10177.  
  10178.  
  10179. ΓòÉΓòÉΓòÉ 8.31. <?SemiColon> ΓòÉΓòÉΓòÉ
  10180.  
  10181. <?SemiColon> 
  10182.  
  10183. This variable will be replaced by a single semicolon (;) character.  It could 
  10184. be useful if you have the odd line that must begin with a semicolon.  The 
  10185. semicolon is the default character to begin a line comment. 
  10186.  
  10187. This is a Standard Definition which always exists (you don't need to #define 
  10188. it).  Note that you can create your own variations or completely new ones (see 
  10189. the examples). 
  10190.  
  10191.  
  10192. ΓòÉΓòÉΓòÉ 8.32. <?Space> ΓòÉΓòÉΓòÉ
  10193.  
  10194. <?Space> 
  10195.  
  10196. This variable will be replaced by a single space, it is most useful for 
  10197. ensuring that you have required spaces on lines that were continued using the 
  10198. '\' character. 
  10199.  
  10200. This symbol actually expands to a <?xXX> code and not the ' ' character 
  10201. directly. In some cases this may not be what you wish and you should either 
  10202. define your own alternative or use some other method (#define may be suitable 
  10203. in a lot of cases) depending on your need. 
  10204.  
  10205. This is a Standard Definition which always exists (you don't need to #define 
  10206. it).  Note that you can create your own variations or completely new ones (see 
  10207. the examples). 
  10208.  
  10209.  
  10210. ΓòÉΓòÉΓòÉ 8.33. <?TemplateDataFile> ΓòÉΓòÉΓòÉ
  10211.  
  10212. <?TemplateDataFile> 
  10213.  
  10214. If the "/Template" switch was not specified then this variable will return an 
  10215. empty value, otherwise the name of the data file is returned (the template 
  10216. typically processes this file). 
  10217.  
  10218. By using this variable a header file could determine whether or not template 
  10219. processing is occurring. 
  10220.  
  10221. This is a Standard Definition which always exists (you don't need to #define 
  10222. it).  Note that you can create your own variations or completely new ones (see 
  10223. the examples). 
  10224.  
  10225.  
  10226. ΓòÉΓòÉΓòÉ 8.34. <?TotalOutputLines> ΓòÉΓòÉΓòÉ
  10227.  
  10228. <?TotalOutputLines> 
  10229.  
  10230. This variable contains the total line number of lines generated into all output 
  10231. files. 
  10232.  
  10233. This is a Standard Definition which always exists (you don't need to #define 
  10234. it).  Note that you can create your own variations or completely new ones (see 
  10235. the examples). 
  10236.  
  10237.  
  10238. ΓòÉΓòÉΓòÉ 8.35. <?Unique> ΓòÉΓòÉΓòÉ
  10239.  
  10240. <?Unique> 
  10241.  
  10242. This variable will be replaced by a Unique number every time it is used. 
  10243.  
  10244. This is a Standard Definition which always exists (you don't need to #define 
  10245. it).  Note that you can create your own variations or completely new ones (see 
  10246. the examples). 
  10247.  
  10248.  
  10249. ΓòÉΓòÉΓòÉ 8.36. <?Version> ΓòÉΓòÉΓòÉ
  10250.  
  10251. <?Version> 
  10252.  
  10253. This variable will be replaced by the version number of the program.  The 
  10254. version number is in the form "YY.DDD", examples are "98.001" (first day of 
  10255. 1998) and "00.123" (123rd day of 2000). 
  10256.  
  10257. This is a Standard Definition which always exists (you don't need to #define 
  10258. it).  Note that you can create your own variations or completely new ones (see 
  10259. the examples). 
  10260.  
  10261. Example 
  10262.  
  10263. The following code shows how you could ensure that a general purpose header 
  10264. file can only be used if the preprocessors version number is greater than a 
  10265. particular value.  You would do this if the header file requires a particular 
  10266. feature which only became available in a specific release. 
  10267.  
  10268.     /*--- Get PPWIZARD version # as YYYY.DDD ------------------------------------*/
  10269.     #if    <?Version> < 98.000
  10270.             #evaluate PPWizardVersion  "2000.00 + <?Version>";
  10271.     #elseif
  10272.             #evaluate PPWizardVersion  "1900.00 + <?Version>";
  10273.     #endif
  10274.  
  10275.     /*--- Validate PPWIZARD VERSION (Y2K safe) ----------------------------------*/
  10276.     #define DEFINEIT_MIN_PPWIZARD_VERSION    1998.188       ;;Rely on changes made in specific PPWIZARD release
  10277.     #if    <$PPWizardVersion> < <$DEFINEIT_MIN_PPWIZARD_VERSION>
  10278.             #error 'PPWIZARD.CMD version of at least <$DEFINEIT_MIN_PPWIZARD_VERSION> is required, you have <$PPWizardVersion>'
  10279.     #endif
  10280.  
  10281.  
  10282. ΓòÉΓòÉΓòÉ 8.37. <?xXX> ΓòÉΓòÉΓòÉ
  10283.  
  10284. <?xXX> 
  10285.  
  10286. Any variable which starts with 'x' has a special characteristic in that they 
  10287. are not replaced until just before a line is written to the output file.  The 
  10288. only invalid character in the name of the variable is '>'. 
  10289.  
  10290. The replacements are made in a single pass from left to right.  The replacement 
  10291. contents may not itself contain codes you wish to be interpreted in any way as 
  10292. the text will be output as specified. You have some control over when the 
  10293. replacement occurs, see the ExpandX option. 
  10294.  
  10295. The name of the symbol represents a variable whose contents was previously 
  10296. defined with the '=x=' operator of the #RexxVar command.  For complex values 
  10297. you may need to first use #evaluate to calculate the value. 
  10298.  
  10299. Variables of this type are useful if you wish to use characters that can't be 
  10300. entered by the editing tool you are using.  They also provide an emergency way 
  10301. out which might get you past instances where the character might otherwise be 
  10302. interpreted in a manner other than you wish.  For example if you must have the 
  10303. string "<?Version>" in your output (and not have it replaced by the version 
  10304. number)!  Another example is that "<?x09>" is the only way to get a tab into 
  10305. the generated output. 
  10306.  
  10307. This is a Standard Definition which always exists (you don't need to #define 
  10308. it).  Note that you can create your own variations or completely new ones (see 
  10309. the examples). 
  10310.  
  10311. Codes <?x00> to <?xFF> 
  10312.  
  10313. The 256 rexx variables "x00" to "xFF" have been preset to represent their ASCII 
  10314. character codes.  This means that "<?x09>" would get replaced with a tab 
  10315. character and "<?x41>" would get replaced with "A". 
  10316.  
  10317. You could if you wished change the appropriate rexx variables to change the 
  10318. replacement value.  For example you could decide the code for "<" gets replaced 
  10319. by "<" instead. 
  10320.  
  10321. Note that it would generally be better to "name" your ASCII codes as they would 
  10322. then be easier to understand, for example "xTAB" is a lot easier to understand 
  10323. than "x09"! 
  10324.  
  10325. It is highly recommended that you do not use "<?x0A>" codes to generated 
  10326. newlines, you should use "<?NewLine>". 
  10327.  
  10328. Example - Using Predefined ASCII Codes 
  10329.  
  10330.     #define Tab    <?x09>
  10331.  
  10332.     Col1<$Tab>Col2<$Tab>Col3
  10333.  
  10334. Example - Creating Your Own Codes 
  10335.  
  10336.     #evaluate 'Tab'       "d2c(9)"
  10337.     #RexxVar  "TAB"  =x=  "<$Tab>"             ;;TAB Char
  10338.     #RexxVar  "LA"   =x=  "<"               ;;'<' Char
  10339.     #RexxVar  "RA"   =x=  ">"               ;;'>' Char
  10340.  
  10341.     Col1<?xTab>Col2<?xTab>Col3
  10342.     <?xLA> = Less    than
  10343.     <?xRA> = Greater than
  10344.  
  10345.  
  10346. ΓòÉΓòÉΓòÉ 9. PPWIZARD Extensions ΓòÉΓòÉΓòÉ
  10347.  
  10348. PPWIZARD Extensions 
  10349.  
  10350. You may not wish to use some of these headers but it would pay you to look at 
  10351. them purely from the point of view of examples. 
  10352.  
  10353.  
  10354. ΓòÉΓòÉΓòÉ 9.1. FTPLIKE.IH - Make "FTP" Like Listings ΓòÉΓòÉΓòÉ
  10355.  
  10356. FTPLIKE.IH - Make "FTP" Like Listings 
  10357.  
  10358. This header file will scan the specified directory (and optionally its 
  10359. subdirectories) and by default produce a FTP like set of html pages. 
  10360.  
  10361. It is very simple for you to modify any part of the look and feel, so for 
  10362. example it would be simple to add your own headers, footers, backgrounds and 
  10363. display all information in whatever format or font you wish. 
  10364.  
  10365. This header could also be used to automatically process photo directories 
  10366. producing thumbnails (with extra software) etc automatically. 
  10367.  
  10368. Example - Creating Directory Listing 
  10369.  
  10370. The following code is all that is required to generate a complete HTML page of 
  10371. all files in a single directory. Note that file descriptions are read out of 
  10372. ".DIZ" files if available (the DIZ files themselves are not displayed). 
  10373.  
  10374.     ;--- Complete code to generate a HTML page for the directory "C:\TMP" ---
  10375.     #define   FTPLIKE_DIRECTORY             C:\TMP
  10376.     #define   FTPLIKE_DIRECTORY_WEB         file:///C|TMP  ;;Note: for web "downloads/tmp" might normally be more appropriate
  10377.     #define   FTPLIKE_FOLLOW_SUBDIRECTORIES
  10378.     #define   FTPLIKE_USE_LONG_FILENAMES                   ;;When generating web pages for subdirectories (default is 8.3)
  10379.     #define   FTPLIKE_HTML_EXTN             html           ;;When generating web pages for subdirectories (".htm" is default)
  10380.     #include  "FTPLIKE.IH"
  10381.  
  10382. Example - WPS URL Objects to HTML 
  10383.  
  10384. I keep all my WPS URL objects off a main URL folder, I then create HTML pages 
  10385. from this so I can effectively access my URL objects from anywhere via the 
  10386. internet (pages at http://www.labyrinth.net.au/~dbareis/bookmark.htm). 
  10387.  
  10388. This is the code I use: 
  10389.  
  10390.     #define  Title             "Dennis' Personal Bookmarks"
  10391.     #define  AddToDescription  Dennis' Personal Bookmarks, straight from OS/2 WPS URL Objects
  10392.     #include "computer.ih"
  10393.  
  10394.     ;--- Initialization ---------------------------------------------------------
  10395.     #if    ['<?OpSys>' <> 'OS/2']
  10396.            #error  "Sorry but you will need to modify this file to work on operating systems other than OS/2!"
  10397.     #endif
  10398.     #evaluate   ""  "call RxFuncAdd  'SysGetEA', 'RexxUtil', 'SysGetEA'"
  10399.  
  10400.     ;--- Title ------------------------------------------------------------------
  10401.     <$BackgroundMainWindows>
  10402.     <$PageTitle TITLE="Dennis' Personal Bookmarks">
  10403.  
  10404.  
  10405.     ;--- Routine used to format "thin" URL --------------------------------------
  10406.     #define ThinUrl                                               \
  10407.             #evaluate @@  @ThinUrl = BreakAt(14, '{$HTTPURL}')@  -\
  10408.             <A HREF="{$HTTPURL}"><??ThinUrl></A>
  10409.  
  10410.  
  10411.     ;--- Save values of this pages info (they get modified below!) --------------
  10412.     #ifndef VERSION_PUSHPOPM_H
  10413.             #include "PushPopM.H"
  10414.     #endif
  10415.     <$MacroPush Macro='ShortNameHtml'>
  10416.     <$MacroPush Macro='ShortNameHtmlLowerCase'>
  10417.  
  10418.     ;--- Override images my footer macro normally uses for these pages ----------
  10419.     #define+ LinkImgFooter  <A HREF="ppwizard.htm">                                                           -\
  10420.                                <$ImgMadeWithPpwizardAndreaResmini ALT="Made with PPWIZARD using FTPLIKE.IH">  -\
  10421.                             </A>
  10422.  
  10423.     ;--- Override "normal" FTPLIKE options (no need to change header!!!!) -------
  10424.     #DefineRexx REXX_GETURL
  10425.                 ;--- First line of WPS URL file contains the URL ----------------
  10426.                 CloseRc = stream(FtpFile, 'c', 'close');
  10427.                 eUrl    = linein(FtpFile);
  10428.                 CloseRc = stream(FtpFile, 'c', 'close');
  10429.     #DefineRexx
  10430.     #DefineRexx REXX_GETCOMMENT
  10431.                 ;--- Comment is stored in OS/2 Extended Attributes --------------
  10432.                 if SysGetEA(FtpFile, ".COMMENTS", "eComment") <> 0 then
  10433.                    eComment = '';
  10434.                 else
  10435.                    eComment = substr(eComment, 11); ;;Drop EA Type info
  10436.                 eComment = ReplaceString(eComment, '0D0A'x, '<BR>');
  10437.     #DefineRexx
  10438.     #DefineRexx REXX_REALNAME
  10439.                 ;--- Long name is stored in OS/2 Extended Attributes ------------
  10440.                 if SysGetEA(FtpFile, ".LONGNAME", "eShort") <> 0 then
  10441.                    eShort = '';
  10442.                 else
  10443.                    eShort = substr(eShort, 5);    ;;Drop EA Type info
  10444.                 if eShort = '' then               ;;Play safe!
  10445.                    eShort = FtpOutput;            ;;Use what we have!
  10446.                 else
  10447.                    eShort = ReplaceString(eShort, '0D0A'x, '<BR>');
  10448.     #DefineRexx
  10449.     #define FTPLIKE_DIR_HANDLER                                             \
  10450.             #evaluate+ '' ^FtpFile=FtpDir;<$REXX_REALNAME>;<$REXX_GETCOMMENT>^  -\
  10451.             <TR>                                                           -\
  10452.             <TD>                                                           -\
  10453.                 ;--- Link to HTML page we will create ---                  -\
  10454.                 <$FTPLIKE_LINK2DIR Url="<$FtpDirId>.<$FTPLIKE_HTML_EXTN>"> -\
  10455.                 <??eShort>   ;;Just output short name                      -\
  10456.                 </A>                                                       -\
  10457.             </TD>                                                          -\
  10458.             <TD>                                                           -\
  10459.                 <TABLE BORDER=0 CELLPADDING=5>                             -\
  10460.                 <TR>                                                       -\
  10461.                 <TD ALIGN=RIGHT><??FtpSubdirTotalFileCnt> url(s)</TD>      -\
  10462.                 #if FtpSubdirTotalDirCnt <> 0                              -\
  10463.                     <TD ALIGN=LEFT><??FtpSubdirTotalDirCnt> folder(s)</TD> -\
  10464.                 #endif                                                     -\
  10465.                 </TR>                                                      -\
  10466.                 </TABLE>                                                   -\
  10467.                 #if [eComment <> '']                                       -\
  10468.                     <HR><??eComment>    ;;Comment from EAs                 -\
  10469.                 #endif                                                     -\
  10470.             </TD>                                                          -\
  10471.             </TR>
  10472.     #define FTPLIKE_FILE_HANDLER                                        \
  10473.             #evaluate+  "" "FtpOutput = _filespec('name', FtpFile)"    -\
  10474.             #evaluate+  ''          ^<$REXX_GETURL>;<$REXX_REALNAME>^  -\
  10475.             <TR>                 ;;Start New File row                  %\
  10476.             <TD ALIGN=CENTER>    ;;Start filename cell                 %\
  10477.                 <A HREF="<??eURL>" TARGET=_top>                        -\
  10478.                    <??eShort>    ;;Just output short name              -\
  10479.                 </A>                                                   %\
  10480.             </TD>               ;;End cell                              \
  10481.             <TD ALIGN=CENTER>    ;;Start filename cell                 %\
  10482.                 <$ThinUrl HTTPURL="<??eURL>">                          -\
  10483.             </TD>               ;;End cell
  10484.     #define FTPLIKE_FILE_DETAILS_HANDLER                             \
  10485.             #evaluate '' ^<$FTPLIKE_FILE_ATTRIBUTE_HANDLER_REXX>^   -\
  10486.             <TD ALIGN=LEFT>     ;;Start file details cell           %\
  10487.                 <??FtpDay> <??FtpMon> <??FtpYear>                    \
  10488.                 <??FtpHour>:<??FtpMinute>:<??FtpSecond>              \
  10489.                 #evaluate ""  ^<$REXX_GETCOMMENT>^                  -\
  10490.                 #if [eComment <> '']                                -\
  10491.                     <HR><??eComment>    ;;Comment from EAs          -\
  10492.                 #endif                                              -\
  10493.             </TD>               ;;End cell                          %\
  10494.             </TR>               ;;End this File row
  10495.     #define FTPLIKE_END_PAGE_ABOVE_FOOTER                            \
  10496.             <$ImgBarbedWire>                                        -\
  10497.             <CENTER>                                                -\
  10498.                <H2>Creating These Book Mark Pages</H2>              -\
  10499.             </CENTER>                                               -\
  10500.                                                                     -\
  10501.             <P>This page was automatically created from              \
  10502.             OS/2 WPS URL objects created with Netscape 4.04          \
  10503.             onwards.                                                 \
  10504.             The free tool used was                                   \
  10505.             <A HREF="ppwizard.htm">PPWIZARD</A> using                \
  10506.             <A HREF="ppwizard/ftplike.htm#WPS_URL_EXAMPLE">         -\
  10507.                this source code                                      \
  10508.             </A>.                                                   -\
  10509.                                                                     -\
  10510.             <P>All URLs are checked periodically using the           \
  10511.             URL checking tool that comes with PPWIZARD.
  10512.     #define FTPLIKE_NO_HEADER_FOOTER_ON_1ST_PAGE
  10513.     #define FTPLIKE_FOLLOW_SUBDIRECTORIES
  10514.     #define FTPLIKE_USE_LONG_FILENAMES
  10515.     #define FTPLIKE_BODY_TAG              <$BackgroundMainWindows>
  10516.     #if    <$AtHome>
  10517.            #define FTPLIKE_DIRECTORY      E:\DB\URLS     ;;HOME: Location of Base WPS URL folder
  10518.     #else
  10519.            #define FTPLIKE_DIRECTORY      ..\HOME_URL    ;;WORK: Copied here from home
  10520.     #endif
  10521.     #define FTPLIKE_DIRECTORY_WEB
  10522.     #define FTPLIKE_NEWHTML_PREFIX        bookmark_
  10523.     #define FTPLIKE_HEADER                <$PageTitle TITLE="{$Title}">
  10524.     #define FTPLIKE_FOOTER                                                                                                                   \
  10525.             #evaluate+ ShortNameHtml            "_filespec('name', '<?OutputFile>')"                                                        -\
  10526.             #evaluate+ ShortNameHtmlLowerCase   "translate('<$ShortNameHtml>', 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" -\
  10527.             <$EndHtmlWithStandardFooter>
  10528.  
  10529.  
  10530.     ;--- Include FTPLIKE support (creates all HTML pages based on options above) ---
  10531.     #include  "FTPLIKE.IH"
  10532.  
  10533.  
  10534.     ;--- Restore this pages information and output footer and end of HTML -------
  10535.     <$MacroPop Macro='ShortNameHtmlLowerCase'>
  10536.     <$MacroPop Macro='ShortNameHtml'>
  10537.     <$EndHtmlWithStandardFooter>
  10538.  
  10539. FTPLIKE.IH 
  10540.  
  10541. This shows the contents of the header file (supplied with PPWIZARD) that 
  10542. provides the generic "FTP like" support: 
  10543.  
  10544. ;----------------------------------------------------------------------------
  10545. ;     MODULE NAME:   FTPLIKE.IH
  10546. ;
  10547. ;         $Author:   Dennis_Bareis  $
  10548. ;       $Revision:   1.8  $
  10549. ;           $Date:   25 Nov 1999 17:57:06  $
  10550. ;        $Logfile:   E:/DB/PVCS.IT/OS2/PPWIZARD/FTPLIKE.IHV  $
  10551. ;
  10552. ;     DESCRIPTION:   This allows you to create FTP like pages without
  10553. ;                    having to do a lot of work.  Simply add the file
  10554. ;                    to a directory will get it onto the correct HTML
  10555. ;                    page.
  10556. ;
  10557. ;                    It would be wise to generate pages into their own
  10558. ;                    directory on the off chance that this header file
  10559. ;                    picks a name for a directories file which matches
  10560. ;                    one of yours!
  10561. ;
  10562. ;                    Note that most of the code below is tricky only
  10563. ;                    because I made it generic (ie very configurable),
  10564. ;                    a specific implementation would be much smaller
  10565. ;                    and much much easier to write as well!
  10566. ;
  10567. ;                    The whole look and feel of the generated data may
  10568. ;                    be modified.
  10569. ;
  10570. ;                    It would be simple to have your normal look and feel
  10571. ;                    items such as headers, footers backgrounds etc
  10572. ;                    integrated into the generated output.
  10573. ;
  10574. ;                    Description file support (.diz) is available for both
  10575. ;                    files and directories. The directory DIZ file should
  10576. ;                    reside in the directory its describing. Note that the
  10577. ;                    file can (and probably should) contain normal HTML
  10578. ;                    formatting tags - by default anyway. If you have a
  10579. ;                    file called "stuff.zip" this header will look for
  10580. ;                    "stuff.zip.diz" and "stuff.diz".
  10581. ;
  10582. ;                    You should not modify the value of any definition
  10583. ;                    that begins with an "_", you can modify virtually
  10584. ;                    anything else.
  10585. ;
  10586. ;                    Note that dependancy checking does not make sense
  10587. ;                    in this type of situation as files can appear simply
  10588. ;                    by matching the wildcard. For this reason I do not
  10589. ;                    bother with using the "#dependsOn INPUT" command for
  10590. ;                    each file I process.
  10591. ;
  10592. ;
  10593. ;                    NOT COMPLETE
  10594. ;                    ~~~~~~~~~~~~
  10595. ;                    I don't really like the way file date, time and size
  10596. ;                    are displayed, if you have any better ideas please
  10597. ;                    let me know.
  10598. ;
  10599. ;
  10600. ;                    SUPPORTED OPERATING SYSTEMS
  10601. ;                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  10602. ;                    It is intended that all operating systems that PPWIZARD
  10603. ;                    supports can also use this header, if you find that
  10604. ;                    it does not work then please send me the output when
  10605. ;                    you have used the "/debug" command line switch. Please
  10606. ;                    also include a directory listing of the directory(s) you
  10607. ;                    are processing.
  10608. ;
  10609. ;
  10610. ;                    EXAMPLE - LINUX
  10611. ;                    ~~~~~~~~~~~~~~~
  10612. ;                    #define   FTPLIKE_FOLLOW_SUBDIRECTORIES
  10613. ;                    #define   FTPLIKE_USE_LONG_FILENAMES
  10614. ;                    #define   FTPLIKE_DIRECTORY           /home/dennis/
  10615. ;                    #define   FTPLIKE_DIRECTORY_WEB       http://ftp
  10616. ;                    #include  "ftplike.ih"
  10617. ;
  10618. ;
  10619. ;                    EXAMPLE - OS/2, WINDOWS
  10620. ;                    ~~~~~~~~~~~~~~~~~~~~~~~
  10621. ;                    #define   FTPLIKE_FOLLOW_SUBDIRECTORIES
  10622. ;                    #define   FTPLIKE_USE_LONG_FILENAMES   ;;Remove this definition for 8.3 names
  10623. ;                    #define   FTPLIKE_DIRECTORY            C:\TMP\ASM_MAC
  10624. ;                    #define   FTPLIKE_DIRECTORY_WEB        file:///C|TMP/ASM_MAC ;;Local testing
  10625. ;                    #include  "FTPLIKE.IH"
  10626. ;
  10627. ;
  10628. ;                    HELP WANTED
  10629. ;                    ~~~~~~~~~~~
  10630. ;                    I use "find" under linux, is there a expression that
  10631. ;                    I can pass to "-name" to display all files/directories?
  10632. ;
  10633. ;----------------------------------------------------------------------------
  10634.  
  10635. ;--- First time through? ----------------------------------------------------
  10636. #ifndef _FTPLIKE_INITIALIZED
  10637.    ;--- Define the version number of this header file -----------------------
  10638.    #define+  VERSION_FTPLIKE_IH    99.325
  10639.    #require  99.325
  10640.  
  10641.    ;--- Check prerequisites -------------------------------------------------
  10642.    #ifndef FTPLIKE_DIRECTORY
  10643.            #error ^You must define the "FTPLIKE_DIRECTORY" value (local directory)!^
  10644.    #endif
  10645.    #ifndef FTPLIKE_DIRECTORY_WEB
  10646.            #error ^You must define the "FTPLIKE_DIRECTORY_WEB" value (web location)!^
  10647.    #endif
  10648.  
  10649.    ;--- Include macro push/pop support --------------------------------------
  10650.    #ifndef VERSION_PUSHPOPM_H
  10651.            #include "PushPopM.H"
  10652.    #endif
  10653.  
  10654.    ;--- Use same date time on all generated pages ---------------------------
  10655.    #ifndef FTPLIKE_DATETIME
  10656.            #evaluate FTPLIKE_DATETIME @date('WeekDay') || ' ' || date('Month') || ' ' || substr(date('Sorted'), 7, 2) || ' ' || left(date('Sorted'), 4) || ' at ' || time('Civil')@
  10657.    #endif
  10658.  
  10659.    ;--- Total numbers accross FTP pages -------------------------------------
  10660.    #RexxVar FtpTotalDirCnt  = 0          ;;Number of directories
  10661.    #RexxVar FtpTotalFileCnt = 0          ;;Number of files
  10662.  
  10663.    ;--- Remember the output level where it all began! -----------------------
  10664.    #Rexxvar FtpStartLevel = <?OutputLevel>
  10665.  
  10666.    ;--- Work out what filemasks users wants ---------------------------------
  10667.    #ifndef FTPLIKE_FILE_MASKS
  10668.            ;--- Default is to process all files -----------------------------
  10669.            #if ['<?OpSys>' = 'UNIX']
  10670.                #define FTPLIKE_FILE_MASKS
  10671.            #else
  10672.                #define FTPLIKE_FILE_MASKS *.*
  10673.            #endif
  10674.    #endif
  10675.    #ifndef FTPLIKE_DIR_MASKS
  10676.            ;--- Default is to process all directories -----------------------
  10677.            #if ['<?OpSys>' = 'UNIX']
  10678.                #define FTPLIKE_DIR_MASKS
  10679.            #else
  10680.                #define FTPLIKE_DIR_MASKS *.*
  10681.            #endif
  10682.    #endif
  10683.  
  10684.    ;--- Do best we can for input dependancies -------------------------------
  10685.    #ifdef  FTPLIKE_FOLLOW_SUBDIRECTORIES
  10686.            #DependsOn  INPUT  ^*FILES=+<$FTPLIKE_DIRECTORY><?DirSlash><$FTPLIKE_DIR_MASKS>^
  10687.    #elseif
  10688.            #DependsOn  INPUT  ^*FILES=<$FTPLIKE_DIRECTORY><?DirSlash><$FTPLIKE_DIR_MASKS>^
  10689.    #endif
  10690.  
  10691.    ;--- Allow user to easily support frames etc -----------------------------
  10692.    #ifndef FTPLIKE_LINK2DIR
  10693.            #define FTPLIKE_LINK2DIR   <A HREF="{$URL}">
  10694.    #endif
  10695.    #ifndef FTPLIKE_LINK2FILE
  10696.            #define FTPLIKE_LINK2FILE  <A HREF="{$URL}">   ;;Probably would not want to override this
  10697.    #endif
  10698.  
  10699.    ;--- Prepare for generating HTML page names ------------------------------
  10700.    #ifdef  FTPLIKE_FOLLOW_SUBDIRECTORIES
  10701.            ;--- Prepare for generating html page names (unique names!) ------
  10702.            #evaluate '' ^call GetIdPrepare 'FTPLIKE', 'Y'^
  10703.  
  10704.            ;--- Don't generate filename same as current "base" file! --------
  10705.            #evaluate '' ^call SetId        'FTPLIKE', '',  EnsureFileHasCorrectCase(_filespec('W', _filespec('Name', '<?OutputFile>')))^
  10706.    #endif
  10707.  
  10708.    ;--- Now work out the output directory -----------------------------------
  10709.    #evaluate+  'FtpGenDir' ^_filespec('location', '<?OutputFile>')^
  10710.  
  10711.    ;--- Work out the full name of this header file --------------------------
  10712.    #RexxVar  FtpLikeFile = '<?InputComponent>'
  10713.  
  10714.    ;--- Relative web directory ----------------------------------------------
  10715.    #define _FTPLIKE_DIRECTORY_WEB_RELATIVE
  10716.  
  10717.    ;--- Work out what user wants to call the "root" dir ---------------------
  10718.    #ifndef FTPLIKE_DISPLAY_DIR
  10719.            #define FTPLIKE_DISPLAY_DIR /
  10720.    #endif
  10721.  
  10722.    ;--- Work out extension to use -------------------------------------------
  10723.    #ifndef   FTPLIKE_HTML_EXTN
  10724.              #define   FTPLIKE_HTML_EXTN   htm
  10725.    #endif
  10726.  
  10727.    ;--- User want specific prefix for generated filenames -------------------
  10728.    #ifndef   FTPLIKE_NEWHTML_PREFIX
  10729.              #ifdef    FTPLIKE_USE_LONG_FILENAMES
  10730.                        #define   FTPLIKE_NEWHTML_PREFIX     FtpLike_
  10731.              #elseif
  10732.                        #define   FTPLIKE_NEWHTML_PREFIX     ;;No prefix
  10733.              #endif
  10734.    #endif
  10735.  
  10736.  
  10737.    ;--- Define Simple HEADERS & FOOTERS -------------------------------------
  10738.    #ifndef FTPLIKE_HEADER
  10739.            #define FTPLIKE_HEADER    <CENTER><H1>{$Title}</H1></CENTER>
  10740.    #endif
  10741.    #ifndef FTPLIKE_FOOTER
  10742.            #define FTPLIKE_FOOTER          \
  10743.                    <HR>                   %\
  10744.                    <CENTER>               %\
  10745.                    <FONT SIZE=-1>         %\
  10746.                       <$FTPLIKE_DATETIME> %\
  10747.                    </FONT>                %\
  10748.                    </CENTER>              %\
  10749.                    </BODY></HTML>
  10750.    #endif
  10751.  
  10752.    ;--- Define START OF HTML page -------------------------------------------
  10753.    #ifndef FTPLIKE_EXTRA_HEAD_TAGS
  10754.            #define FTPLIKE_EXTRA_HEAD_TAGS
  10755.    #endif
  10756.    #ifndef FTPLIKE_BODY_TAG
  10757.            #define FTPLIKE_BODY_TAG <BODY>
  10758.    #endif
  10759.    #ifndef FTPLIKE_START_HTML_PAGE
  10760.            #define FTPLIKE_START_HTML_PAGE                           \
  10761.                    <!-- Real Directory "<$FTPLIKE_DIRECTORY>" -->   %\
  10762.                    <HTML>                                           %\
  10763.                    <HEAD>                                           %\
  10764.                       <META NAME="GENERATOR" CONTENT="FTPLIKE.IH <$VERSION_FTPLIKE_IH> macros for PPWIZARD <?Version>, free tool by <?PpwizardAuthor> (<?PpwizardHomePage>)"> %\
  10765.                       <TITLE><$FTPLIKE_DISPLAY_DIR></TITLE>         %\
  10766.                       <$FTPLIKE_EXTRA_HEAD_TAGS>                    -\
  10767.                    </HEAD>                                          %\
  10768.                    <$FTPLIKE_BODY_TAG>                              %\
  10769.                    <$FTPLIKE_HEADER Title=^<$FTPLIKE_DISPLAY_DIR>^> %\
  10770.                    <?NewLine>
  10771.    #endif
  10772.  
  10773.    ;--- Define some stubs (you can add comments like "no directories found" etc) ---
  10774.    #ifndef FTPLIKE_START_PAGE_AFTER_TITLE
  10775.            #define FTPLIKE_START_PAGE_AFTER_TITLE  <$FTPLIKE_DIR_DIZ_HANDLER>
  10776.    #endif
  10777.    #ifndef FTPLIKE_BETWEEN_DIRS_AND_FILES
  10778.            #define FTPLIKE_BETWEEN_DIRS_AND_FILES
  10779.    #endif
  10780.    #ifndef FTPLIKE_END_PAGE_ABOVE_FOOTER
  10781.            #define FTPLIKE_END_PAGE_ABOVE_FOOTER
  10782.    #endif
  10783.  
  10784.    ;--- Define START OF files -----------------------------------------------
  10785.    #ifndef FTPLIKE_BEFORE_ALL_FILES
  10786.            #define FTPLIKE_BEFORE_ALL_FILES                 \
  10787.                    <CENTER>                                %\
  10788.                    <TABLE BORDER=5 CELLPADDING=10>
  10789.    #endif
  10790.    #ifndef FTPLIKE_BEFORE_ALL_DIRS
  10791.            #define FTPLIKE_BEFORE_ALL_DIRS                  \
  10792.                    <CENTER>                                %\
  10793.                    <TABLE BORDER=0 CELLPADDING=0>
  10794.    #endif
  10795.  
  10796.  
  10797.    ;--- How to handle a directory's name ------------------------------------
  10798.    #ifndef FTPLIKE_GENERATE_HTML_FOR_DIR_TREE
  10799.            #define FTPLIKE_GENERATE_HTML_FOR_DIR_TREE                       \
  10800.                    #evaluate+  '' "FtpOutput = _filespec('name', FtpDir)"  -\
  10801.                                                                            -\
  10802.                    ;--- Work out HTML base name ------------               -\
  10803.                    #ifdef     FTPLIKE_USE_LONG_FILENAMES                   -\
  10804.                               #evaluate+ "FtpDirId"  ^EnsureFileHasCorrectCase( GetId('FTPLIKE', '2_',       '<$FTPLIKE_NEWHTML_PREFIX><$_FTPLIKE_DIRECTORY_WEB_RELATIVE $$SQx2>/' || FtpOutput) )^ -\
  10805.                    #elseif                                                 -\
  10806.                               #evaluate+ "FtpDirId"  ^EnsureFileHasCorrectCase( GetId('FTPLIKE', 'MAXCHARS', '<$FTPLIKE_NEWHTML_PREFIX>' || FtpOutput) )^ -\
  10807.                    #endif                                                  -\
  10808.                                                                            -\
  10809.                    ;--- Start HTML page for new dir ---                    -\
  10810.                    #output "<$FtpDirId>.<$FTPLIKE_HTML_EXTN>"              -\
  10811.                       ;--- "PUSH" some values ---                          -\
  10812.                       <$MacroPush Macro='FTPLIKE_DIRECTORY'>               -\
  10813.                       <$MacroPush Macro='FTPLIKE_DIRECTORY_WEB'>           -\
  10814.                       <$MacroPush Macro='FTPLIKE_DISPLAY_DIR'>             -\
  10815.                       <$MacroPush Macro='_FTPLIKE_DIRECTORY_WEB_RELATIVE'> -\
  10816.                       <$MacroPush Macro='FtpDirId'>                        -\
  10817.                       #RexxVar    PUSH  FtpOutput FtpDir                   -\
  10818.                                                                            -\
  10819.                       ;--- Create HTML contents ---                        -\
  10820.                       #option    PUSH DefineMacroReplace=ON                -\
  10821.                       #define+   FTPLIKE_DIRECTORY              <$FTPLIKE_DIRECTORY><?DirSlash><??FtpOutput>      -\
  10822.                       #evaluate+ FTPLIKE_DISPLAY_DIR            ^ReplaceString('<$FTPLIKE_DISPLAY_DIR $$SQx2>/' || FtpOutput, '//', '/')^ -\
  10823.                       #define+   FTPLIKE_DIRECTORY_WEB          <$FTPLIKE_DIRECTORY_WEB>/<??FtpOutput>            -\
  10824.                       #define+   _FTPLIKE_DIRECTORY_WEB_RELATIVE <$_FTPLIKE_DIRECTORY_WEB_RELATIVE>/<??FtpOutput> -\
  10825.                       #option    POP                                       -\
  10826.                       #include   "ftplike.ih"                              -\
  10827.                                                                            -\
  10828.                       ;--- "POP"  some values ---                          -\
  10829.                       #RexxVar   POP  FtpOutput FtpDir                     -\
  10830.                       <$MacroPop Macro='FtpDirId'>                         -\
  10831.                       <$MacroPop Macro='_FTPLIKE_DIRECTORY_WEB_RELATIVE'>  -\
  10832.                       <$MacroPop Macro='FTPLIKE_DISPLAY_DIR'>              -\
  10833.                       <$MacroPop Macro='FTPLIKE_DIRECTORY_WEB'>            -\
  10834.                       <$MacroPop Macro='FTPLIKE_DIRECTORY'>                -\
  10835.                    #output
  10836.    #endif
  10837.  
  10838.    ;--- How to handle (display) directory details ---------------------------
  10839.    #ifndef FTPLIKE_DIR_HANDLER
  10840.            #define FTPLIKE_DIR_HANDLER                                         \
  10841.                    <TR>                                                       -\
  10842.                    <TD>                                                       -\
  10843.                       ;--- Link to HTML page we will create ---               -\
  10844.                       <$FTPLIKE_LINK2DIR Url="<$FtpDirId>.<$FTPLIKE_HTML_EXTN>"> -\
  10845.                          <??FtpOutput> ;;Just output short name                -\
  10846.                       </A>                                                    -\
  10847.                    </TD>                                                      -\
  10848.                    <TD>                                                       -\
  10849.                       <TABLE BORDER=0 CELLPADDING=5>                          -\
  10850.                       <TR>                                                    -\
  10851.                          <TD ALIGN=LEFT><??FtpSubdirTotalDirCnt> dirs</TD>    -\
  10852.                          <TD ALIGN=RIGHT><??FtpSubdirTotalFileCnt> files</TD> -\
  10853.                       </TR>                                                   -\
  10854.                       </TABLE>                                                -\
  10855.                    </TD>                                                      -\
  10856.                    </TR>
  10857.    #endif
  10858.  
  10859.  
  10860.    ;--- How to handle a file's name -----------------------------------------
  10861.    #ifndef FTPLIKE_FILE_HANDLER
  10862.            #define FTPLIKE_FILE_HANDLER                                     \
  10863.                    #evaluate '' ^FtpOutput = _filespec('name', FtpFile)^   -\
  10864.                    #evaluate '' ^eURL = UrlEncode('<$FTPLIKE_DIRECTORY_WEB>/' || FtpOutput, 'TO%', ' ')^ -\
  10865.                    <TR>                ;;Start New File row                %\
  10866.                    <TD ALIGN=RIGHT>    ;;Start filename cell               %\
  10867.                        <$FTPLIKE_LINK2FILE Url="<??eURL>">                 -\
  10868.                           <??FtpOutput> ;;Just output short name           -\
  10869.                        </A>                                                %\
  10870.                    </TD>               ;;End cell
  10871.    #endif
  10872.  
  10873.    ;--- How to handle a file's details --------------------------------------
  10874.    #ifndef FTPLIKE_FILE_DETAILS_HANDLER
  10875.            #define FTPLIKE_FILE_DETAILS_HANDLER                             \
  10876.                    #evaluate '' ^<$FTPLIKE_FILE_ATTRIBUTE_HANDLER_REXX>^   -\
  10877.                    <TD ALIGN=LEFT>     ;;Start file details cell           %\
  10878.                        <??FtpDay> <??FtpMon> <??FtpYear>                    \
  10879.                        <??FtpHour>:<??FtpMinute>:<??FtpSecond>,             \
  10880.                        <?Space>                                             \
  10881.                        <??FtpSize> bytes                                   %\
  10882.                        <$FTPLIKE_FILE_DIZ_HANDLER>                         -\
  10883.                    </TD>               ;;End cell                          %\
  10884.                    </TR>               ;;End this File row
  10885.    #endif
  10886.  
  10887.  
  10888.    ;--- Define END OF files -------------------------------------------------
  10889.    #ifndef FTPLIKE_AFTER_ALL_FILES
  10890.            #define FTPLIKE_AFTER_ALL_FILES  </TABLE></CENTER>
  10891.    #endif
  10892.    #ifndef FTPLIKE_AFTER_ALL_DIRS
  10893.            #define FTPLIKE_AFTER_ALL_DIRS   </TABLE></CENTER><P>
  10894.    #endif
  10895.  
  10896.    ;--- Define ATTRIBUTE Handler (date, time, size etc) ---------------------
  10897.    #ifndef FTPLIKE_FILE_ATTRIBUTE_HANDLER_REXX
  10898.            #define FTPLIKE_FILE_ATTRIBUTE_HANDLER_REXX                     \
  10899.                    FtpTimeStamp = GetFileTimeStamp(FtpFile);              -\
  10900.                    FtpSize      = stream(FtpFile, 'c', 'query size');     -\
  10901.                    FtpSize      = AddCommasToDecimalNumber(FtpSize);      -\
  10902.                    parse var FtpTimeStamp FtpYear +4 FtpMonth +2 FtpDay +2 FtpHour +2 FtpMinute +2 FtpSecond;      -\
  10903.                    FtpMon       = substr('JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC', ((FtpMonth-1)*4)+1, 3);
  10904.    #endif
  10905.  
  10906.  
  10907.    ;--- Process this directory? (no filter by default) ----------------------
  10908.    #ifndef FTPLIKE_DO_THIS_DIR
  10909.            #define FTPLIKE_DO_THIS_DIR       ;;Generate for all directories
  10910.    #endif
  10911.  
  10912.    ;--- Process this file? (by default no ".diz" files!) --------------------
  10913.    #ifndef FTPLIKE_DO_THIS_FILE
  10914.            #define FTPLIKE_DO_THIS_FILE_REXX                           \
  10915.                    if  translate(right(FtpFile, 4)) = '.diz' then;    -\
  10916.                        FtpDoThisFile = 'N';    ;;Description file!
  10917.            #define FTPLIKE_DO_THIS_FILE                                \
  10918.                    #evaluate '' ^<$FTPLIKE_DO_THIS_FILE_REXX>^
  10919.    #endif
  10920.  
  10921.    ;--- Define "DIZ" handler ------------------------------------------------
  10922.    #ifndef FTPLIKE_FILE_DIZ_HANDLER
  10923.            #define FTPLIKE_FILE_DIZ_HANDLER_REXX                        \
  10924.                    FtpDizFile     = stream(FtpFile || '.diz', 'c', 'query exists'); -\
  10925.                    if  FtpDizFile = '' then;                           -\
  10926.                    do;                                                 -\
  10927.                        ;--- Try changing extension to ".diz" ---       -\
  10928.                        FtpPos = lastpos('.', FtpFile);                 -\
  10929.                        if  FtpPos <> 0 then;                           -\
  10930.                            FtpDizFile = stream(left(FtpFile,FtpPos) || 'DIZ', 'c', 'query exists'); -\
  10931.                    end;                                                -\
  10932.                    if  FtpDizFile = '' then;                           -\
  10933.                        FtpDiz = '';                                    -\
  10934.                    else;                                               -\
  10935.                    do;                                                 -\
  10936.                        FtpDiz  = charin(FtpDizFile, 1, 99999);         -\
  10937.                        call DieIfIoErrorOccurred FtpDizFile;           -\
  10938.                        CloseRc = stream(FtpDizFile, 'c', 'close');     -\
  10939.                        <$FTPLIKE_DIZ_TRANSLATION_REXX>                 -\
  10940.                        FtpDiz = {$Prefix=^''^} || FtpDiz || {$Suffix=^''^}; -\
  10941.                    end;
  10942.            #define FTPLIKE_FILE_DIZ_HANDLER                             \
  10943.                    #evaluate '' ^<$FTPLIKE_FILE_DIZ_HANDLER_REXX PREFIX=~'<HR>'~>^  -\
  10944.                    <??FtpDiz>
  10945.    #endif
  10946.    #ifndef FTPLIKE_DIR_DIZ_HANDLER
  10947.            #define FTPLIKE_DIR_DIZ_HANDLER                              \
  10948.                    #evaluate '' ^FtpFile = '<$FTPLIKE_DIRECTORY $$SQx2><?DirSlash>' || _filespec('name', '<$FTPLIKE_DIRECTORY $$SQx2>')^ -\
  10949.                    #evaluate '' ^<$FTPLIKE_FILE_DIZ_HANDLER_REXX SUFFIX=~'<HR>'~>^  -\
  10950.                    <??FtpDiz>
  10951.    #endif
  10952.  
  10953.  
  10954.    ;--- Define "DIZ" translations -------------------------------------------
  10955.    #ifndef FTPLIKE_DIZ_TRANSLATION_REXX
  10956.            #define FTPLIKE_DIZ_TRANSLATION_REXX                                 \
  10957.                    FtpDiz = ReplaceString(FtpDiz, '1A'x,       '');  ;;EOF char
  10958.    ;;;;;;          FtpDiz = ReplaceString(FtpDiz, '0D0A0D0A'x, '0D0A'x || '<P>');
  10959.    #endif
  10960.  
  10961.  
  10962.    ;--- Define how files are SORTED -----------------------------------------
  10963.    #ifndef FTPLIKE_FILE_SORT
  10964.            #ifndef FTPLIKE_FILE_SORT_REXX
  10965.                    #define FTPLIKE_FILE_SORT_REXX             \
  10966.                            call SortArray '{$ArrayName}'
  10967.            #endif
  10968.            #define FTPLIKE_FILE_SORT                          \
  10969.                    #evaluate '' ^<$FTPLIKE_FILE_SORT_REXX ArrayName=~{$ArrayName}~>^
  10970.    #endif
  10971.    #ifndef FTPLIKE_DIRECTORY_SORT
  10972.            #define FTPLIKE_DIRECTORY_SORT  <$FTPLIKE_FILE_SORT ArrayName=~{$ArrayName}~>  ;;Same as file sort by default
  10973.    #endif
  10974.  
  10975.    ;--- Make sure not done again (when a directory being processed etc) -----
  10976.    #define _FTPLIKE_INITIALIZED
  10977. #endif
  10978.  
  10979.  
  10980. ;--- Simple processing message ----------------------------------------------
  10981. #evaluate '' ^ShortOutName = _filespec('Name', '<?OutputFile>')^
  10982. #info ^Generating <??ShortOutName> <= <$FTPLIKE_DIRECTORY>^
  10983.  
  10984.  
  10985. ;--- Initialization for this FTP page ---------------------------------------
  10986. #RexxVar FtpDirCnt  = 0          ;;Number of directories on this html page
  10987. #RexxVar FtpFileCnt = 0          ;;Number of files       on this html page
  10988.  
  10989.  
  10990. ;--- Generate start of HTML -------------------------------------------------
  10991. #if    <?OutputLevel> <> FtpStartLevel | defined('FTPLIKE_NO_HEADER_FOOTER_ON_1ST_PAGE') = 'N'
  10992.        <$FTPLIKE_START_HTML_PAGE>
  10993. #endif
  10994. <$FTPLIKE_START_PAGE_AFTER_TITLE>
  10995.  
  10996. ;--- Process directories? (need to be careful as we include ourself) --------
  10997. #ifdef  FTPLIKE_FOLLOW_SUBDIRECTORIES
  10998.         ;--- Get list of directories ----------------------------------------
  10999.         #evaluate '' ^call _SysFileTree '<$FTPLIKE_DIRECTORY $$SQx2><?DirSlash><$FTPLIKE_DIR_MASKS>', 'FtpArray<?OutputLevel>', 'DO'^
  11000.  
  11001.         ;--- Any directories to display? ------------------------------------
  11002.         #if  [FtpArray<?OutputLevel>.0 <> 0]
  11003.            ;--- Sort the list (if thats what user wants) --------------------
  11004.            <$FTPLIKE_DIRECTORY_SORT ArrayName="FtpArray<?OutputLevel>">
  11005.  
  11006.            ;--- Process DIRECTORIES -----------------------------------------
  11007.            #RexxVar FtpIndex<?OutputLevel> = 1
  11008.            #{
  11009.                ;--- Finished? -----------------------------------------------
  11010.                #if [FtpIndex<?OutputLevel> > FtpArray<?OutputLevel>.0]
  11011.                    #break
  11012.                #endif
  11013.  
  11014.                ;--- Get name of this directory ------------------------------
  11015.                #RexxVar FtpDir = FtpArray<?OutputLevel>.FtpIndex<?OutputLevel>
  11016.  
  11017.                ;--- Generate the files --------------------------------------
  11018.                #RexxVar FtpDoThisDir = 'Y'
  11019.                <$FTPLIKE_DO_THIS_DIR>              ;;User want this dir to be seen?
  11020.                #if [FtpDoThisDir = 'Y']
  11021.                    ;--- User does want this dir to be seen ------------------
  11022.                    #RexxVar FtpDirCnt + 1
  11023.                    #if [FtpDirCnt = 1]
  11024.                        ;--- Start DIRECTORY output --------------------------
  11025.                        <$FTPLIKE_BEFORE_ALL_DIRS>
  11026.                    #endif
  11027.  
  11028.                    ;--- Save some variables ---------------------------------
  11029.                    #RexxVar PUSH  FtpDirCnt FtpFileCnt FtpTotalDirCnt FtpTotalFileCnt
  11030.  
  11031.                    ;--- Reset totals ----------------------------------------
  11032.                    #RexxVar FtpTotalDirCnt  = 0
  11033.                    #RexxVar FtpTotalFileCnt = 0
  11034.  
  11035.                    ;--- Process all subdirectories (generating HTML as we go)
  11036.                    <$FTPLIKE_GENERATE_HTML_FOR_DIR_TREE>
  11037.  
  11038.                    ;--- Remember subdirectory counts ------------------------
  11039.                    #RexxVar FtpSubdirTotalFileCnt = FtpTotalFileCnt
  11040.                    #RexxVar FtpSubdirTotalDirCnt  = FtpTotalDirCnt
  11041.  
  11042.                    ;--- Display directory details on this page --------------
  11043.                    <$FTPLIKE_DIR_HANDLER>
  11044.  
  11045.                    ;--- Restore other variables -----------------------------
  11046.                    #RexxVar POP  FtpDirCnt FtpFileCnt FtpTotalDirCnt FtpTotalFileCnt
  11047.  
  11048.                    ;--- Add to totals ---------------------------------------
  11049.                    #RexxVar FtpTotalFileCnt + FtpSubdirTotalFileCnt
  11050.                    #RexxVar FtpTotalDirCnt  + FtpSubdirTotalDirCnt
  11051.                #endif
  11052.  
  11053.                ;--- Prepare for next file -----------------------------------
  11054.                #RexxVar FtpIndex<?OutputLevel> + 1
  11055.            #}
  11056.  
  11057.            ;--- Generate end DIRECTORY stuff --------------------------------
  11058.            #if [FtpDirCnt <> 0]
  11059.                <$FTPLIKE_AFTER_ALL_DIRS>
  11060.            #endif
  11061.         #endif
  11062.  
  11063.         ;--- Hook for displaying stuff --------------------------------------
  11064.         <$FTPLIKE_BETWEEN_DIRS_AND_FILES>
  11065. #endif
  11066.  
  11067. ;--- Get list of files ------------------------------------------------------
  11068. #evaluate '' ^call _SysFileTree '<$FTPLIKE_DIRECTORY $$SQx2><?DirSlash><$FTPLIKE_FILE_MASKS>', 'FtpArray', 'FO'^
  11069.  
  11070. ;--- Any files in this directory? -------------------------------------------
  11071. #if [FtpArray.0 <> 0]
  11072.    ;--- Sort the list (if thats what user wants) ----------------------------
  11073.    <$FTPLIKE_FILE_SORT ArrayName="FtpArray">
  11074.  
  11075.    ;--- Process files -------------------------------------------------------
  11076.    #RexxVar FtpIndex = 1
  11077.    #{
  11078.        ;--- Finished? -------------------------------------------------------
  11079.        #if [FtpIndex > FtpArray.0]
  11080.            #break
  11081.        #endif
  11082.  
  11083.        ;--- Get Filename ----------------------------------------------------
  11084.        #RexxVar FtpFile = FtpArray.FtpIndex
  11085.  
  11086.        ;--- Generate the files ----------------------------------------------
  11087.        #RexxVar FtpDoThisFile = 'Y'
  11088.        <$FTPLIKE_DO_THIS_FILE>                 ;;User want this file to be seen?
  11089.        #if [FtpDoThisFile = 'Y']
  11090.            ;--- User does want this file to be seen -------------------------
  11091.            #RexxVar FtpFileCnt + 1
  11092.            #if [FtpFileCnt = 1]
  11093.                ;--- Start FILE output ---------------------------------------
  11094.                <$FTPLIKE_BEFORE_ALL_FILES>
  11095.            #endif
  11096.  
  11097.            ;--- Output details for this file --------------------------------
  11098.            <$FTPLIKE_FILE_HANDLER>
  11099.            <$FTPLIKE_FILE_DETAILS_HANDLER>
  11100.        #endif
  11101.  
  11102.        ;--- Prepare for next file -------------------------------------------
  11103.        #RexxVar FtpIndex + 1
  11104.    #}
  11105.  
  11106.    ;--- Generate end FILES stuff --------------------------------------------
  11107.    #if [FtpFileCnt <> 0]
  11108.        <$FTPLIKE_AFTER_ALL_FILES>
  11109.    #endif
  11110. #endif
  11111.  
  11112.  
  11113. ;--- Generate END of HTML ---------------------------------------------------
  11114. <$FTPLIKE_END_PAGE_ABOVE_FOOTER>
  11115. #if    <?OutputLevel> <> FtpStartLevel | defined('FTPLIKE_NO_HEADER_FOOTER_ON_1ST_PAGE') = 'N'
  11116.        ;--- User has not set up their own alternative -----------------------
  11117.        <$FTPLIKE_FOOTER>               ;;Footer ends body and html
  11118. #endif
  11119.  
  11120. ;--- Update totals ----------------------------------------------------------
  11121. #RexxVar FtpTotalFileCnt + FtpFileCnt
  11122. #RexxVar FtpTotalDirCnt  + FtpDirCnt
  11123.  
  11124. ;--- Output summary ---------------------------------------------------------
  11125. #if    [<?OutputLevel> = FtpStartLevel]
  11126.        #ifndef   FTPLIKE_FOLLOW_SUBDIRECTORIES
  11127.            #info ^FTPLIKE processed <??FtpTotalFileCnt> file(s)^
  11128.        #elseif
  11129.            #info ^FTPLIKE processed <??FtpTotalFileCnt> file(s) in <??FtpTotalDirCnt> directories^
  11130.        #endif
  11131. #endif
  11132.  
  11133.  
  11134. ΓòÉΓòÉΓòÉ 9.2. HTMLPRE.IH - Converts Example Code to HTML ΓòÉΓòÉΓòÉ
  11135.  
  11136. HTMLPRE.IH - Converts Example Code to HTML 
  11137.  
  11138. The following example shows how text can be included from a file. The included 
  11139. text is displayed using the html "<PRE>" tag and automates a complex, time 
  11140. consuming and error prone task. 
  11141.  
  11142. Characters such as  "<" are converted to "<" so that the lines will 
  11143. correctly display in a browser.  The example will also show how keywords can be 
  11144. linked to a glossary or page which explains a concept. Two international 
  11145. symbols are also handled for demonstration purposes: 
  11146.  
  11147.     ;--- Include header for example support -------------------------------------
  11148.     #include "HTMLPRE.IH"
  11149.  
  11150.     ;--- Set up all international characters we will handle ---------------------
  11151.     #AutoTagState +
  11152.     #AutoTag      '╨ö'    'ä'
  11153.     #AutoTag      '╨Ö'    'ë'
  11154.     #AsIs         SETUP  INTERNATIONAL_SYMBOLS
  11155.     #AutoTagState -
  11156.  
  11157.     ;--- Some HTML text ---------------------------------------------------------
  11158.     <P>The following is the  contents of my "config.sys" file:
  11159.  
  11160.     ;--- Include the example ----------------------------------------------------
  11161.     #AutoTagState +                                ;;Lets not affect any existing tagging
  11162.     #AutoTag "REM "  "<A HREF='rem.htm'>REM</A> "  ;;Define a single change
  11163.     <$ExampleFile FILE="E:\CONFIG.SYS" STATE=REMEMBER ASIS=INTERNATIONAL_SYMBOLS>
  11164.     #AutoTagState -                                ;;Restore original tagging state
  11165.  
  11166. HTMLPRE.IH 
  11167.  
  11168. This shows the contents of the header file (supplied with PPWIZARD) that 
  11169. provides HTML example support: 
  11170.  
  11171. ;----------------------------------------------------------------------------
  11172. ;     MODULE NAME:   HTMLPRE.IH
  11173. ;
  11174. ;         $Author:   Dennis_Bareis  $
  11175. ;       $Revision:   1.2  $
  11176. ;           $Date:   20 Nov 1999 08:11:24  $
  11177. ;        $Logfile:   E:/DB/PVCS.IT/OS2/PPWIZARD/HTMLPRE.IHV  $
  11178. ;
  11179. ;     DESCRIPTION:   This is a header file for handling inclusion of
  11180. ;                    "examples" into HTML.
  11181. ;
  11182. ;                    See PPWIZARD documentation for examples of this file
  11183. ;                    in use.  The sample "TryMe.IT" file also uses this
  11184. ;                    header file.
  11185. ;
  11186. ;
  11187. ;                    Macro "ExampleFile"
  11188. ;                    ~~~~~~~~~~~~~~~~~~~
  11189. ;
  11190. ;                    This macro takes the following parameters:
  11191. ;
  11192. ;                         FILE
  11193. ;                         ~~~~
  11194. ;                         Manditory. Identifies the file to be included.
  11195. ;
  11196. ;                         FRAGMENT
  11197. ;                         ~~~~~~~~
  11198. ;                         Optional. You may wish to have a single example
  11199. ;                         file hold more than one example.  The text that
  11200. ;                         you supply for this parameter marks the line before
  11201. ;                         as well as the line after the example.
  11202. ;
  11203. ;
  11204. ;                         INDENT
  11205. ;                         ~~~~~~
  11206. ;                         Optional.  By default a 4 space indent is used,
  11207. ;                         you specify the number of spaces with 0 being
  11208. ;                         valid.
  11209. ;
  11210. ;                         STATE
  11211. ;                         ~~~~~
  11212. ;                         Optional.  By default no autotagging will be
  11213. ;                         performed.  If you specify "REMEMBER" then the
  11214. ;                         currently available autotags will be used, you
  11215. ;                         may also specify which states tags should come
  11216. ;                         from (see the "#AutoTagState +" command).
  11217. ;
  11218. ;
  11219. ;                         ASIS
  11220. ;                         ~~~~
  11221. ;                         Optional.  By default only basic "AsIs" tagging
  11222. ;                         is performed.  If for example you wished to
  11223. ;                         handle international characters then you would
  11224. ;                         need to specify the names of the AsIs tags to use.
  11225. ;
  11226. ;
  11227. ;
  11228. ;                    Macro "Example / eExample"
  11229. ;                    ~~~~~~~~~~~~~~~~~~~~~~~~~~
  11230. ;
  11231. ;                    Note that your "inline" example code must not contain
  11232. ;                    a reference to the macro "eExample" as this is used
  11233. ;                    internally.
  11234. ;
  11235. ;                    This macro takes the following parameters:
  11236. ;
  11237. ;
  11238. ;                         INDENT
  11239. ;                         ~~~~~~
  11240. ;                         As above.
  11241. ;
  11242. ;                         STATE
  11243. ;                         ~~~~~
  11244. ;                         As above.
  11245. ;
  11246. ;
  11247. ;                         ASIS
  11248. ;                         ~~~~
  11249. ;                         As above.
  11250. ;
  11251. ;
  11252. ;
  11253. ;----------------------------------------------------------------------------
  11254.  
  11255.  
  11256. ;--- Define the version number of this header file --------------------------
  11257. #define   VERSION_HTMLPRE_IH    99.322
  11258. #require  99.265
  11259.  
  11260.  
  11261. ;----------------------------------------------------------------------------
  11262. ;--- Set up defaults that user can override ---------------------------------
  11263. ;----------------------------------------------------------------------------
  11264. #ifndef HTMLPRE_COLOR
  11265.         #define HTMLPRE_COLOR          purple
  11266. #endif
  11267. #ifndef HTMLPRE_STYLE_OTHER
  11268.         #define HTMLPRE_STYLE_OTHER    ;font-size:80%
  11269. #endif
  11270.  
  11271.  
  11272.  
  11273. ;--- Define some aliases for characters we need to be careful with ----------
  11274. #RexxVar  "LT"   =x= "<"               ;;'<' Char
  11275. #RexxVar  "GT"   =x= ">"               ;;'>' Char
  11276. #RexxVar  "AMP"  =x= "&"              ;;'&' Char
  11277. #RexxVar  "HASH" =x= "#"                  ;;'#' Char
  11278.  
  11279. ;--- Define look and feel of examples ---------------------------------------
  11280. #define ExampleFormatted                                                                            \
  11281.         <FONT COLOR=<$HTMLPRE_COLOR>>                              ;;Set up font (older browsers)  -\
  11282.         <PRE STYLE="color:<$HTMLPRE_COLOR><$HTMLPRE_STYLE_OTHER>">
  11283. #define eExampleFormatted                                                                           \
  11284.         </PRE>                                                                                     -\
  11285.         </FONT>                                                    ;;Restore Font (older browsers)
  11286.  
  11287. ;--- Set up AsIs Mode (minimum changes required - user can add to these) ----
  11288. #AutoTagState +
  11289.    ;--- Define characters that should be automatically modified -------------
  11290.    #AutoTag  "<"   "<?xLT>"
  11291.    #AutoTag  ">"   "<?xGT>"
  11292.    #AutoTag  "&"   "<?xAMP>"
  11293.    #AutoTag  "#"   "<?xHASH>"
  11294.  
  11295.    ;--- "PROGRAM" ASIS mode -------------------------------------------------
  11296.    #AsIs  SETUP    HTMLPRE_IH
  11297. #AutoTagState -
  11298.  
  11299. ;----------------------------------------------------------------------------
  11300. ;--- ALLOW SPELL CHECKING IN EXAMPLES? --------------------------------------
  11301. ;----------------------------------------------------------------------------
  11302. #ifndef HTMLPRE_SPELL_CHECKING
  11303.         #define HTMLPRE_SPELL_CHECKING OFF
  11304. #endif
  11305.  
  11306.  
  11307. ;----------------------------------------------------------------------------
  11308. ;--- EXAMPLE FILE INCLUSION -------------------------------------------------
  11309. ;----------------------------------------------------------------------------
  11310. #define ExampleFile                                                        \
  11311.         <$ExampleFormatted>                                               -\
  11312.         #AutoTagState  +     {$STATE=''}      ;;User can set up own tags  -\
  11313.         #option        PUSH AllowSpell={$SPELL="<$HTMLPRE_SPELL_CHECKING>"} ExtraIndent=^copies(' ', {$Indent='4'})^ -\
  11314.         #AutoTag       ON                                                 -\
  11315.         #AsIs          ON HTMLPRE_IH {$AsIs=''}                           -\
  11316.         #include       "{$File}" "{$Fragment=''}"                         -\
  11317.         #AsIs          OFF                                                -\
  11318.         #option        POP                                                -\
  11319.         #AutoTagState  -                                                  -\
  11320.         <$eExampleFormatted>
  11321.  
  11322.  
  11323.  
  11324. ;----------------------------------------------------------------------------
  11325. ;--- EXAMPLE (INLINE) -------------------------------------------------------
  11326. ;----------------------------------------------------------------------------
  11327. #define Example                             ;;Starts Example               \
  11328.         <$ExampleFormatted>                                               -\
  11329.         #AutoTagState  +     {$STATE=''}    ;;User can set up own tags    -\
  11330.         #option        PUSH AllowSpell={$SPELL="<$HTMLPRE_SPELL_CHECKING>"} ExtraIndent=^copies(' ', {$Indent='4'})^ -\
  11331.         #option        PUSH replace=OFF                                   -\
  11332.         #AutoTag       '<?xLT>$eExample<?xGT>'  '<$eExample>'   #1        -\
  11333.         #option        POP                  ;;Restore REPLACE mode        -\
  11334.         #AutoTag       ON                                                 -\
  11335.         #AsIs          ON HTMLPRE_IH {$AsIs=''}                           -\
  11336.         #define        HTMLPRE_INLINE_EXAMPLE
  11337. #define eExample                            ;;Ends Example                 \
  11338.         #ifndef        HTMLPRE_INLINE_EXAMPLE                             -\
  11339.            #error ^Incorrectly formatted inline example (can't include end of example tag)^ -\
  11340.         #endif                                                            -\
  11341.         #AsIs          OFF                                                -\
  11342.         #option        POP                                                -\
  11343.         #AutoTagState  -                                                  -\
  11344.         #undef         HTMLPRE_INLINE_EXAMPLE                             -\
  11345.         <$eExampleFormatted>
  11346.  
  11347.  
  11348. ΓòÉΓòÉΓòÉ 9.3. NESTCHK.H - Nesting Validation ΓòÉΓòÉΓòÉ
  11349.  
  11350. NESTCHK.H - Nesting Validation 
  11351.  
  11352. The following example shows how validation of the nesting of HTML (or other 
  11353. language) tags can be performed. 
  11354.  
  11355. The Netscape browser will not display a table (or other components) that does 
  11356. not have a matching end tag. This is a common cause of blank pages (or missing 
  11357. information). Rather than hope your comprehensive testing picks up this fact 
  11358. (missing information or faulty layout may not always be obvious) you can ensure 
  11359. that the problem is reported at development time. 
  11360.  
  11361. Note that "NESTCHK.H" contains generic routines so it simplifies your task to 
  11362. "front end" some of the macros with your own. To ensure that you never forget 
  11363. to perform the checking its wise to always end your html with something that is 
  11364. required on your page such as a standard footer. The following code shows how a 
  11365. standard header file of yours (lets call it "MYHEADER.IH") might incorporate 
  11366. nesting checking (example only shows "TABLE" being validated): 
  11367.  
  11368.     ;--- Include generic nesting validation header file -------------------------
  11369.     #include "nestchk.h"
  11370.  
  11371.     ;--- Define what we are checking (table tags only here) ---------------------
  11372.     <$NestingInit Id="TABLE" DESC="HTML TABLE tags">
  11373.     #define TABLE  <$NestingInc Id="TABLE">TABLE
  11374.     #define /TABLE <$NestingDec Id="TABLE"></TABLE>
  11375.  
  11376. The following is a HTML page of yours that will fail the validation: 
  11377.  
  11378.     ;--- Include Common header --------------------------------------------------
  11379.     #include "MYHEADER.IH"
  11380.  
  11381.     ;--- Start HTML (some of this might be better in common header above!) ------
  11382.     #define Title   Simple html with 2 missing end of table tags
  11383.     <HTML>
  11384.     <HEAD>
  11385.        <TITLE><$Title></TITLE>
  11386.     </HEAD>
  11387.     <BODY>
  11388.     <CENTER><H1><$Title></H1></CENTER>
  11389.  
  11390.     <P>Hi there...
  11391.  
  11392.     ;--- Incorrectly nested tables follow ---------------------------------------
  11393.     <<$TABLE> BORDER=1>
  11394.        <<$TABLE> BORDER=2>
  11395.            <<$TABLE> BORDER=3>
  11396.            <$/TABLE>               ;;Only "remember" to end 1 of the 3 tables!
  11397.  
  11398.     ;--- End of HTML ------------------------------------------------------------
  11399.     <$StandardFooter>
  11400.  
  11401. The following shows part of the error details being displayed: 
  11402.  
  11403.        * Processing: E:\DB\PROJECTS\OS2\ppwizard\1.in
  11404.  
  11405.     NESTING ERRORS
  11406.     ~~~~~~~~~~~~~~
  11407.     Missing 2 end nesting tags on "HTML TABLE tags"
  11408.       * line 46 of "E:\DB\PROJECTS\OS2\ppwizard\1.in"
  11409.         <<$TABLE> BORDER=1>
  11410.       * line 47 of "E:\DB\PROJECTS\OS2\ppwizard\1.in"
  11411.         <<$TABLE> BORDER=2>
  11412.  
  11413. NESTCHK.H 
  11414.  
  11415. This shows the contents of the header file (supplied with PPWIZARD) that 
  11416. provides the generic nesting support: 
  11417.  
  11418. ;----------------------------------------------------------------------------
  11419. ;     MODULE NAME:   NESTCHK.H
  11420. ;
  11421. ;         $Author:   Dennis_Bareis  $
  11422. ;       $Revision:   1.4  $
  11423. ;           $Date:   13 Nov 1999 13:39:22  $
  11424. ;        $Logfile:   E:/DB/PVCS.IT/OS2/PPWIZARD/NESTCHK.H_V  $
  11425. ;
  11426. ;        REQUIRES:   Regina 0.08f onwards, or you get clause length problems.
  11427. ;
  11428. ;     DESCRIPTION:   This is a header file for generic handling of
  11429. ;                    nesting checking. This is where you must have matching
  11430. ;                    "whatevers" such as a matching "</TABLE>" for a
  11431. ;                    "<TABLE>" etc.
  11432. ;
  11433. ;                    "TABLE" checking is a good example as are "FRAMESET"
  11434. ;                    statements as the Netscape browser will not display
  11435. ;                    an incorrectly nested page (common cause of "blank"
  11436. ;                    pages). This header file can be used to detect these
  11437. ;                    errors while still developing the pages rather than
  11438. ;                    HOPING that testing will show up the errors.
  11439. ;
  11440. ;                    Because these macros are generic you would usually have
  11441. ;                    your own header file to front end them, for example your
  11442. ;                    header could begin with:
  11443. ;
  11444. ;                       ;--- Prepare table nesting checking code ---
  11445. ;                       #include "NESTCHK.H"
  11446. ;                       <$NestingInit Id="HTMLTAG_TABLE" DESC="HTML TABLE tag">
  11447. ;                       #define TABLE                             \
  11448. ;                               <TABLE{$?}>                      -\
  11449. ;                               <$NestingInc Id="HTMLTAG_TABLE">
  11450. ;                       #define /TABLE                            \
  11451. ;                               </TABLE>                         -\
  11452. ;                               <$NestingDec Id="HTMLTAG_TABLE">
  11453. ;
  11454. ;                    Your code would then always use the table macros defined
  11455. ;                    above rather than the HTML table tags directly, example:
  11456. ;
  11457. ;                       <$TABLE BORDER=5 CELLPADDING=10>
  11458. ;                               <TR>         ;;Could validate TD /TD etc!
  11459. ;                                  ...
  11460. ;                               </TR>
  11461. ;                       <$/TABLE>
  11462. ;
  11463. ;                    You would probably do more that just "TABLE" tags in the
  11464. ;                    above example! Notice that the only difference in your
  11465. ;                    actual code is an extra '$'!
  11466. ;
  11467. ;                    Macro "HtmlNesting"
  11468. ;                    ~~~~~~~~~~~~~~~~~~~
  11469. ;
  11470. ;                    This header file now allows easy creation of macros such
  11471. ;                    as the "TABLE" and "/TABLE" shown above. For example to
  11472. ;                    create nest checking macros for "TABLE", "/TABLE", "TH",
  11473. ;                    "/TH", "TD" and "/TD" you would use:
  11474. ;
  11475. ;                         <$HtmlNesting TAG="TABLE">
  11476. ;                         <$HtmlNesting TAG="TH">
  11477. ;                         <$HtmlNesting TAG="TD">
  11478. ;
  11479. ;
  11480. ;                    Macro "NestingInit"
  11481. ;                    ~~~~~~~~~~~~~~~~~~~
  11482. ;
  11483. ;                    This macro takes the following parameters:
  11484. ;
  11485. ;                         ID
  11486. ;                         ~~
  11487. ;                         Manditory. Short name to describe what we wish
  11488. ;                         to check.  Must contain only characters which
  11489. ;                         are valid in rexx variable names (no checking of
  11490. ;                         this is done).
  11491. ;
  11492. ;                         DESC
  11493. ;                         ~~~~
  11494. ;                         A description which is displayed if a nesting
  11495. ;                         error is found.
  11496. ;
  11497. ;
  11498. ;                    Macro "NestingInc"
  11499. ;                    ~~~~~~~~~~~~~~~~~~
  11500. ;
  11501. ;                    This macro takes the following parameters:
  11502. ;
  11503. ;                         ID
  11504. ;                         ~~
  11505. ;                         Manditory. Matches that used on "NestingInit".
  11506. ;                         You are increasing the level of nesting.
  11507. ;
  11508. ;
  11509. ;                    Macro "NestingDec"
  11510. ;                    ~~~~~~~~~~~~~~~~~~
  11511. ;
  11512. ;                    This macro takes the following parameters:
  11513. ;
  11514. ;                         ID
  11515. ;                         ~~
  11516. ;                         Manditory. Matches that used on "NestingInit".
  11517. ;                         You are decreasing the level of nesting.
  11518. ;
  11519. ;
  11520. ;                    Macro "NestingLevel"
  11521. ;                    ~~~~~~~~~~~~~~~~~~~
  11522. ;
  11523. ;                    This macro takes the following parameters:
  11524. ;
  11525. ;                         ID
  11526. ;                         ~~
  11527. ;                         Manditory. Matches that used on "NestingInit".
  11528. ;                         Returns the name of the variable which contains
  11529. ;                         the level (0= neutral, 1 = down one etc).
  11530. ;
  11531. ;----------------------------------------------------------------------------
  11532.  
  11533. ;--- Only include this header once! -----------------------------------------
  11534. #ifndef   VERSION_NESTCHK_H
  11535.  
  11536.  
  11537. ;--- Define the version number of this header file --------------------------
  11538. #define   VERSION_NESTCHK_H    99.317
  11539. #require  99.317
  11540.  
  11541. ;--- Register checking macro ------------------------------------------------
  11542. #OnExit  <$NestingCheck>
  11543.  
  11544. ;--- Currently not tracking nesting of anything -----------------------------
  11545. #RexxVar NestingIdCount = 0
  11546.  
  11547. ;--- Define macro to keep track of items ------------------------------------
  11548. #DefineRexx NestingInit_REXX
  11549.             ;--- Ensure ID is valid (needs to be valid rexx var format) -----
  11550.             if symbol('{$ID $$SQx2}') = 'BAD' then
  11551.                Error('The ID of "{$ID $$SQx2}" contains invalid characters!', 'It must be in the format of a valid rexx variable name');
  11552.             if symbol('{$ID $$SQx2}_Level') = 'VAR' then
  11553.                Error('The ID of "{$ID $$SQx2}" has already been initialized!');
  11554.  
  11555.             ;--- Remember ID details --------------------------
  11556.             NestingIdCount = NestingIdCount + 1;
  11557.             call _valueS "NESTINGID.NestingIdCount.ID",    '{$ID $$SQx2}';
  11558.             call _valueS "NESTINGID.NestingIdCount.DESC",  '{$DESC}';
  11559.             call _valueS "{$ID $$SQx2}_DESC",              '{$DESC}';
  11560.  
  11561.             ;--- Initialize level counter ---------------------
  11562.             call _valueS '{$ID $$SQx2}_Level', 0;
  11563. #DefineRexx
  11564. #define NestingInit                                                   \
  11565.         #evaluate  '' ^<$NestingInit_REXX ID='{$ID}' DESC='{$DESC}'>^
  11566.  
  11567. ;--- We are going down one level of nesting ---------------------------------
  11568. ;                                                     [SaveSourceAndLocnInfo] (Ignore this - this bit used to include section into doco)
  11569. #DefineRexx NestingInc_REXX
  11570.             ;--- Ensure ID is valid -------
  11571.             if symbol('{$ID $$SQx2}_Level') <> 'VAR' then
  11572.                Error('The ID of "{$ID $$SQx2}" is unknown (you must use "NestingInit")!');
  11573.  
  11574.             ;--- Increase nesting level ---
  11575.             call _valueS "{$ID}_Level", {$ID}_Level + 1;
  11576.  
  11577.             ;--- Record details about current location ---
  11578.             call _valueS "{$ID}_FilePosn.{$ID}_Level", GetInputFileNameAndLine();
  11579.             call _valueS "{$ID}_CurrLine.{$ID}_Level", GetFileLineBeingProcessed();
  11580. #DefineRexx
  11581. #define NestingInc                                            \
  11582.         #evaluate  '' ^<$NestingInc_REXX ID='{$ID}'>^
  11583. ;                                                     [SaveSourceAndLocnInfo] (Ignore this - this bit used to include section into doco)
  11584.  
  11585.  
  11586. ;--- We are going up one level of nesting -----------------------------------
  11587. #DefineRexx NestingDec_REXX
  11588.             ;--- Ensure ID is valid -------
  11589.             if symbol('{$ID $$SQx2}_Level') <> 'VAR' then
  11590.                Error('The ID of "{$ID $$SQx2}" is unknown (you must use "NestingInit")!');
  11591.  
  11592.             ;--- Decrease nesting level ---
  11593.             NewLevel = {$ID}_Level - {$DecreaseBy="1"};
  11594.             if NewLevel < 0 then
  11595.                call Error "Too many end tags for " || {$ID}_DESC;
  11596.  
  11597.             ;--- Record updated details ---
  11598.             call _valueS "{$ID}_Level", NewLevel;
  11599. #DefineRexx
  11600. #define NestingDec                                            \
  11601.         #evaluate  '' ^<$NestingDec_REXX ID='{$ID}' {$?}>^
  11602.  
  11603. ;--- Allow user to access the counter variable ------------------------------
  11604. #define NestingLevel                                          \
  11605.         {$ID}_Level
  11606.  
  11607.  
  11608. ;--- Check nesting of all ID's ----------------------------------------------
  11609. #DefineRexx NestingCheck_REXX
  11610.            ;--- Loop though all registered "nesting" items ---
  11611.            NestingError = 0;       ;;No errors found yet
  11612.            do CheckIndex = 1 to NestingIdCount;
  11613.                ;--- Get basic information about item ---
  11614.               _ID    = NESTINGID.CheckIndex.ID;
  11615.               _DESC  = NESTINGID.CheckIndex.DESC;
  11616.  
  11617.               _Level = _valueG(_ID || "_Level");
  11618.               if _Level <> 0 then;
  11619.               do;
  11620.                  if NestingError = 0 then;
  11621.                  do;
  11622.                     say '';
  11623.                     say 'NESTING ERRORS';
  11624.                     say '~~~~~~~~~~~~~~';
  11625.                  end;
  11626.                  NestingError = NestingError + 1;
  11627.                  if _Level < 0 then;
  11628.                      say 'Have ' || abs(_Level) || ' too many end nesting tags on "' || _DESC || '"';
  11629.                  else;
  11630.                  do;
  11631.                      ;--- display nesting info ---
  11632.                      say 'Missing ' || _Level || ' end nesting tag(s) on "' || _DESC || '"';
  11633.                      do _ThisLevel = 1 to _Level;
  11634.                         say '  * ' || _valueG(_ID || "_FilePosn._ThisLevel");
  11635.                         say '    ' || _valueG(_ID || "_CurrLine._ThisLevel");
  11636.                      end;
  11637.                  end;
  11638.               end;
  11639.            end;
  11640. #DefineRexx
  11641. #define NestingCheck                                            \
  11642.         #evaluate  '' ^<$NestingCheck_REXX>^                    \
  11643.         #if [NestingError <> 0]                                 \
  11644.             #error ^NestingCheck(): Found <??NestingError> nesting error(s) as described above^ \
  11645.         #endif
  11646.  
  11647.  
  11648.  
  11649. ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  11650. ;%%%[ The following macros allow you to easily define HTML tag Nesting ]%%%
  11651. ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  11652.  
  11653.  
  11654. ;--- This is the only tag of the following you should use! ----------------
  11655. #define  HtmlNesting                                                   \
  11656.          ;--- Initialization for this tag ---                         -\
  11657.          <$NestingInit Id="HTML_{$TAG}"                                \
  11658.                        DESC='HTML {$TAG} tag nesting'                 -\
  11659.          >                                                            -\
  11660.                                                                       -\
  11661.          #evaluate ^^ ^<$REXX_HTML_NESTING TAG=^{$TAG}^ Type="Inc">^  -\
  11662.          #evaluate ^^ ^<$REXX_HTML_NESTING TAG=^{$TAG}^ Type="Dec">^
  11663.  
  11664. ;--- Define GENERIC macros for TAG and /TAG (use pseudo parameters) -------
  11665. #define  _HTML_NESTING_Inc                       \
  11666.          [Tag]{$?}>                            -\
  11667.          <$NestingInc Id="HTML_[Tag]">
  11668. #define  _HTML_NESTING_Dec                       \
  11669.          </[Tag]{$?}>                           -\
  11670.          <$NestingDec Id="HTML_[Tag]">
  11671.  
  11672.  
  11673. ;--- Define code which creates TAG start/end macros -----------------------
  11674. #DefineRexx REXX_HTML_NESTING
  11675.             ;--- Get GENERIC Macro (START or END) ---
  11676.             TagMacro = MacroGet('_HTML_NESTING_{$Type}');
  11677.  
  11678.             ;--- Replace pseudo parameters ---
  11679.             TagMacro = ReplaceString(TagMacro, '[Tag]',  '{$TAG $$SQx2}');
  11680.  
  11681.             ;--- Create START or END html tag macro ---
  11682.             if '{$Type}' = 'Inc' then
  11683.                HtmlTag = '{$TAG $$SQx2}';
  11684.             else
  11685.                HtmlTag = '/{$TAG $$SQx2}';
  11686.             call MacroSet HtmlTag, TagMacro;
  11687. #DefineRexx
  11688.  
  11689.  
  11690.  
  11691.  
  11692.  
  11693.  
  11694.  
  11695. ;--- Only include this header once! -----------------------------------------
  11696. #endif
  11697.  
  11698.  
  11699. ΓòÉΓòÉΓòÉ 9.4. VALRURL.H - Remote Resource Validation ΓòÉΓòÉΓòÉ
  11700.  
  11701. VALRURL.H - Remote Resource Validation 
  11702.  
  11703. This section describes how PPWIZARD can be used to validate remote resources, 
  11704. by remote I mean any resource that you could not determine if it existed or not 
  11705. purely by examining the local machines environment. 
  11706.  
  11707. The header file "VALRURL.H" can be used to validate ftp and http URLs on remote 
  11708. servers. This will for example warn you if a particular link would generate a 
  11709. 404 in a browser. 
  11710.  
  11711. Currently the header works under OS/2, http (web page) validation may work as 
  11712. is under Windows (95/98/NT) or may require small changes. If you have another 
  11713. operating system you may still wish to examine the header file as only minor 
  11714. work would probably be required to get it to work if you already have a method 
  11715. to validate a URL. 
  11716.  
  11717. EXAMPLE - Immediate Validation 
  11718.  
  11719. This example is not real life in that the URLs would normally not be used on 
  11720. their own but would be part of a hypertext link. You are expected to be online 
  11721. (to the internet) at the time you try the example as the URL checking is done 
  11722. immediately after a otherwise successful build. The example also demonstates 
  11723. setting up debugging: 
  11724.  
  11725.     ;--- Load external URL validation support ---
  11726.     ;;#define  VALRURL_NO_CHECK_HTTP
  11727.     ;;#define  VALRURL_NO_CHECK_FTP
  11728.     #define  VALRURL_FTP_EMAIL       db0@anz.com
  11729.     #define  VALRURL_DEBUG           +out\DEBUG.URL\*.DBG    ;;Append to end of any existing debug file
  11730.     #include "VALRURL.H"
  11731.  
  11732.     ;--- Check some HTTP URLS ---
  11733.     <$RemHttp url="http://anz.com">                                     ;;Does not exist
  11734.     <$RemHttp url="http://www.labyrinth.net.au/~dbareis/ppwizard.htm">  ;;Exists
  11735.     <$RemHttp url="http://www.labyrinth.net.au/~dbareis/zips_fw">       ;;Needs a '/'
  11736.     <$RemHttp url="http://www.labyrinth.net.au/~dbareis/no_such.htm">   ;;Does not exist
  11737.  
  11738.     ;--- Check some FTP URLS ---
  11739.     <$RemFtp  url="ftp://ftp.anz.com">                                  ;;Does not exist
  11740.     <$RemFtp  url="ftp://ftp.pc.ibm.com/pub/pccbbs/os2_ews">            ;;Directory
  11741.     <$RemFtp  url="ftp://ftp.pc.ibm.com/pub/pccbbs/os2_ews/aping.txt">  ;;File
  11742.  
  11743. EXAMPLE - Delayed Validation 
  11744.  
  11745. This example is more real life. It also creates a URL list so that you don't 
  11746. need to be online when the html is built. You can run the generated URL files 
  11747. through the validator (supplied with ppwizard for OS/2 - http may work under 
  11748. windows) whenever you wish. 
  11749.  
  11750. It shows one possible way of defining a common header file containing a useful 
  11751. front end macro as well as the definition of a remote URL. As the URL is only 
  11752. mentioned in one place no matter where or how many times it appears on your web 
  11753. pages it is simple to fix if it becomes out of date. 
  11754.  
  11755. The common header file "MyCommon.IH" follows: 
  11756.  
  11757.     ;--- Load external URL validation support -----------
  11758.     #define  VALRURL_FTP_EMAIL         db0@anz.com
  11759.     #define  VALRURL_CHECK_LATER_MASK  out\REMOTE.URL\*.URL
  11760.     #include "VALRURL.H"
  11761.  
  11762.     ;--- Useful macro: Validate URL and generate link ---
  11763.     #define InternetLink                         \
  11764.             <A HREF="<$RemHttp URL=^{$URL}^>">  -\
  11765.                {$VISIBLE=^{$URL}^}              -\
  11766.             </A>
  11767.  
  11768.     ;--- Define URLs (usually in common header file -----
  11769.     #define HttpPpwizardHomePage   \
  11770.             http://www.labyrinth.net.au/~dbareis/ppwizard.htm
  11771.  
  11772. What might appear in one of your pages follows: 
  11773.  
  11774.     ;--- Load common header file ---
  11775.     #include "MyCommon.IH"
  11776.  
  11777.     ;--- Check some HTTP URLS ------
  11778.     <P>Please see my <$InternetLink URL="<$HttpPpwizardHomePage>">
  11779.     for a great
  11780.     <$InternetLink URL="<$HttpPpwizardHomePage>" VISIBLE=^preprocessor^>.
  11781.  
  11782. At some future stage when you are online to the internet you might start the 
  11783. validation process with a command similar to: 
  11784.  
  11785.     ppwcurl.cmd CheckListedUrls remote.url\*.URL
  11786.  
  11787. VALRURL.H 
  11788.  
  11789. ;----------------------------------------------------------------------------
  11790. ;     MODULE NAME:   VALRURL.IH
  11791. ;
  11792. ;         $Author:   Dennis_Bareis  $
  11793. ;       $Revision:   1.7  $
  11794. ;           $Date:   20 Nov 1999 08:12:12  $
  11795. ;        $Logfile:   E:/DB/PVCS.IT/OS2/PPWIZARD/VALRURL.H_V  $
  11796. ;
  11797. ;     DESCRIPTION:   This is a header file for checking HTTP/FTP urls on
  11798. ;                    remote servers. All URLs are passed with a leading
  11799. ;                    "http://' or "ftp://".
  11800. ;
  11801. ;                    This routine does not validate that any "#Section"
  11802. ;                    on http URLs are correct. It will validate that the
  11803. ;                    html page exists on the server.
  11804. ;
  11805. ;                    It will only check a URL once. This is the case even
  11806. ;                    across builds of multiple ".IT" files if they are being
  11807. ;                    built using the one call to PPWIZARD.
  11808. ;
  11809. ;                    Note that I don't search a table to work out if a URL
  11810. ;                    has already been used, my method is much faster however
  11811. ;                    on very long URLs which appear in multiple files in the
  11812. ;                    same PPWIZARD invokation it may repeat the test.
  11813. ;
  11814. ;
  11815. ;                    OPERATING SYSTEMS
  11816. ;                    ~~~~~~~~~~~~~~~~~
  11817. ;                    This header has only been tested under OS/2. The
  11818. ;                    required DLLs appear to have been installed by OS/2
  11819. ;                    version 4 (Merlin). If these are unavailable on your
  11820. ;                    machine you may need a TCP-IP fixpack, otherwise you
  11821. ;                    will need to locate a web page containing the files.
  11822. ;
  11823. ;                    Since there is a "RxSock.DLL" available for windows
  11824. ;                    http checking will also work there (if any changes
  11825. ;                    required please let me know the details).
  11826. ;                    There is no "RxFtp.DLL" for windows (that I know of).
  11827. ;
  11828. ;                    You can get RxSock for windows from:
  11829. ;
  11830. ;                                http://home.hiwaay.net/~abbott/regina/
  11831. ;
  11832. ;
  11833. ;                    COMMENTS
  11834. ;                    ~~~~~~~~
  11835. ;                    Error messages could be improved a bit!
  11836. ;
  11837. ;                    Not sure about all error handling, please let me know
  11838. ;                    of any issues you have. If you can see that I'm doing
  11839. ;                    something wrong, please tell me!
  11840. ;
  11841. ;
  11842. ;                    EXAMPLE
  11843. ;                    ~~~~~~~
  11844. ;                    ;;#define  VALRURL_NO_CHECK_HTTP
  11845. ;                    ;;#define  VALRURL_NO_CHECK_FTP
  11846. ;                    ;;#define  VALRURL_DEBUG            out\DEBUG.URL\*.DBG
  11847. ;                    #define    VALRURL_CHECK_LATER_MASK out\REMOTE.URL\*.URL
  11848. ;                    #define    VALRURL_FTP_EMAIL        db0@anz.com
  11849. ;                    #include "VALRURL.H"
  11850. ;
  11851. ;                    <P>Please see
  11852. ;                    <A HREF="<$RemHttp url="http://www.labyrinth.net.au/~dbareis/ppwizard.htm">">
  11853. ;                       PPWIZARD's homepage
  11854. ;                    </A>.
  11855. ;
  11856. ;                    You may wish to come up with your own set of "front end"
  11857. ;                    macros to simplify the above. Also in general I recommend
  11858. ;                    defining the external URL's in a header if they are to
  11859. ;                    be used in more than one place.
  11860. ;----------------------------------------------------------------------------
  11861.  
  11862.  
  11863. ;--- Initialization (for this compile) --------------------------------------
  11864. #ifdef  VALRURL_CHECK_LATER_MASK
  11865.         #DefineRexx ''
  11866.            ;--- Create URL file name based on input name ---
  11867.            UrlListFile = GenerateFileName('<?InputFile>', '<$VALRURL_CHECK_LATER_MASK>');
  11868.  
  11869.            ;--- Delete the file for starters, will get created if any URLs ---
  11870.            call stream UrlListFile, 'c', 'close';
  11871.            call _SysFileDelete UrlListFile;
  11872.         #DefineRexx
  11873. #endif
  11874.  
  11875.  
  11876. ;--- Only do rest of header once! -------------------------------------------
  11877. #ifndef VERSION_VALRURL_IH
  11878.    ;--- Define the version number of this header file -----------------------
  11879.    #define   VERSION_VALRURL_IH    99.315
  11880.    #require  99.315
  11881.  
  11882.    ;--- Need access to sort stuff ------------------------------------------
  11883.    #include "PPWSORT.H"
  11884.  
  11885.    ;--- Allow user to prevent generation if they only wish validation ------
  11886.    #ifndef RemHttpGenerate
  11887.        #define RemHttpGenerate      {$URL}
  11888.    #endif
  11889.    #ifndef RemFtpGenerate
  11890.        #define RemFtpGenerate       {$URL}
  11891.    #endif
  11892.  
  11893.    ;--- Allow user to modify what happens on failing validation ------------
  11894.    #ifndef VALRURL_FAILED_VALIDATION_REXX
  11895.            #DefineRexx VALRURL_FAILED_VALIDATION_REXX
  11896.                    call warning "CRURL", ThisUrl || ' ==> ' || UrlChkRc;
  11897.            #DefineRexx
  11898.    #endif
  11899.  
  11900.    ;--- Allow user to modify what happens on successful validation ---------
  11901.    #ifndef VALRURL_VALIDATED_OK_REXX
  11902.            ;--- Default is display success only when debug is on -----------
  11903.            #ifdef  VALRURL_DEBUG
  11904.                    ;--- Display successful URL as debug is on --------------
  11905.                    #DefineRexx VALRURL_VALIDATED_OK_REXX
  11906.                                call info 'DEBUG: ' || ThisUrl || ' successfully validated';
  11907.                    #DefineRexx
  11908.            #elseif
  11909.                    ;--- Define empty handler if debug is off ---------------
  11910.                    #define VALRURL_VALIDATED_OK_REXX
  11911.            #endif
  11912.    #endif
  11913.  
  11914.  
  11915.    ;--- Allow user to specify email address for FTP site logon -------------
  11916.    #ifndef VALRURL_FTP_EMAIL
  11917.            #define VALRURL_FTP_EMAIL VALRURL_<$VERSION_VALRURL_IH>@real.email.address.unknown
  11918.    #endif
  11919.  
  11920.    ;--- User calls these macros to perform validation ----------------------
  11921.    #define RemHttp                                                  \
  11922.            <$ValidateHttpR    URL="{$URL}">     ;;Check Remote URL -\
  11923.            <$RemHttpGenerate  URL="{$URL}">     ;;Generate URL
  11924.    #define RemFtp                                                   \
  11925.            <$ValidateFtpR     URL="{$URL}">     ;;Check Remote URL -\
  11926.            <$RemHttpGenerate  URL="{$URL}">     ;;Generate URL
  11927.  
  11928.    ;--- Checking HTTP:// ? -------------------------------------------------
  11929.    #ifdef  VALRURL_NO_CHECK_HTTP
  11930.            #define ValidateHttpR   ;;No checking
  11931.    #elseif
  11932.            #define ValidateHttpR   <$ValidateUrlR Type="http://" URL="{$URL}">
  11933.    #endif
  11934.  
  11935.  
  11936.    ;--- Checking FTP:// ? --------------------------------------------------
  11937.    #ifdef  VALRURL_NO_CHECK_FTP
  11938.            #define ValidateFtpR    ;;No checking
  11939.    #elseif
  11940.            #define ValidateFtpR    <$ValidateUrlR Type="ftp://" URL="{$URL}">
  11941.    #endif
  11942.  
  11943.    ;--- Initialization - Once per PPWIZARD Invokation (NOT build!) ---------
  11944.    #if symbol('UrlCheckerPgm') <> 'VAR'
  11945.        ;--- No need to do anything if delaying the checking! ---------------
  11946.        #ifndef VALRURL_CHECK_LATER_MASK
  11947.            #if Defined('VALRURL_NO_CHECK_HTTP') = 'N' | Defined('VALRURL_NO_CHECK_FTP') = 'N'
  11948.                ;--- Find External program ----------------------------------
  11949.                #define VALRURL_EXT_CMD   PPWCURL.CMD
  11950.                #evaluate ''                                                                                           \
  11951.                ^                                                                                                      \
  11952.                    UrlCheckerPgm = _SysSearchPath('PATH', '<$VALRURL_EXT_CMD>');                                      \
  11953.                    if  UrlCheckerPgm = '' then;                                                                       \
  11954.                    do;                                                                                                \
  11955.                        parse source . . PpwRexxFile;                                                                  \
  11956.                        UrlCheckerPgm = _filespec('location', PpwRexxFile) || '<$VALRURL_EXT_CMD>';                    \
  11957.                            if  stream(UrlCheckerPgm, 'c', 'query exists') = '' then;                                  \
  11958.                                Error('Could not locate "<$VALRURL_EXT_CMD>" (searched PATH and PPWIZARD directory)'); \
  11959.                    end;                                                                                               \
  11960.                ^
  11961.  
  11962.                ;--- Display version numbers of DLLs we are using -----------
  11963.                #evaluate '' ^interpret 'ExtCmdVersion = "<??UrlCheckerPgm>"("VERSION?")'^
  11964.                #info        'Header file version <$VERSION_VALRURL_IH>'
  11965.                #info        'Using Check URL external command <??ExtCmdVersion>'
  11966.                #ifndef  VALRURL_NO_CHECK_HTTP
  11967.                    #evaluate '' ^interpret 'SocketVersion = "<??UrlCheckerPgm>"("SOCKETVERSION?")'^
  11968.                    #info     'Validating remote http URLs with <??SocketVersion>'
  11969.                #endif
  11970.                #ifndef  VALRURL_NO_CHECK_FTP
  11971.                    #evaluate '' ^interpret 'FtpVersion    = "<??UrlCheckerPgm>"("FTPVERSION?")'^
  11972.                    #info     'Validating remote ftp  URLs with <??FtpVersion>'
  11973.                #endif
  11974.  
  11975.                ;--- Set email address for FTP downloads --------------------
  11976.                #ifndef  VALRURL_NO_CHECK_FTP
  11977.                    #evaluate '' ^call SetEnv "PPWCURL_EMAIL", "<$VALRURL_FTP_EMAIL>"^
  11978.                #endif
  11979.            #endif
  11980.        #endif
  11981.    #endif
  11982.  
  11983.    ;--- Set up debug? ----------------------------------------------
  11984.    #ifndef  VALRURL_DEBUG
  11985.        #evaluate '' ^call SetEnv "PPWCURL_DEBUG", ''^            ;;Prevent Debug
  11986.    #elseif
  11987.        #evaluate '' ^TDbgFile = GenerateFileName('<?InputFile>', '<$VALRURL_DEBUG>')^
  11988.        #evaluate '' ^call _SysFileDelete TDbgFile^
  11989.        #evaluate '' ^call SetEnv "PPWCURL_DEBUG", TDbgFile^      ;;Turn it on
  11990.        #info        'Any debugger output goes to "<??TDbgFile>"'
  11991.    #endif
  11992.  
  11993.    ;--- Make sure we have required support for this compile -----------------
  11994.    #ifndef VALRURL_CHECK_LATER_MASK
  11995.        #ifndef  VALRURL_NO_CHECK_HTTP
  11996.            #evaluate '' ^interpret 'SupportHttp = "<??UrlCheckerPgm>"("SOCKETREADY?")'^
  11997.            #if SupportHttp <> 'OK'
  11998.                ;--- Can't validate HTTP URLs -----------------------------------
  11999.                #Warning "CRURL"  "Can't validate HTTP URLs"
  12000.                #define+ RemHttp <$RemHttpGenerate  URL="{$URL}"> ;;Can't validate URL
  12001.            #endif
  12002.        #endif
  12003.        #ifndef  VALRURL_NO_CHECK_FTP
  12004.            #evaluate '' ^interpret 'SupportFtp  = "<??UrlCheckerPgm>"("FTPREADY?")'^
  12005.            #if SupportFtp <> 'OK'
  12006.                ;--- Can't validate FTP URLs -----------------------------------
  12007.                #Warning "CRURL"  "Can't validate FTP URLs"
  12008.                #define+ RemFtp <$RemFtpGenerate  URL="{$URL}">   ;;Can't validate URL
  12009.            #endif
  12010.        #endif
  12011.    #endif
  12012.  
  12013.    ;--- Initialization for this build ---------------------------------------
  12014.    #RexxVar ValUrlCount = 0            ;;Counts elements in URL array
  12015.    #OnExit  <$ProcessRemoteUrlList>    ;;Handle the list (user could override macro)
  12016.  
  12017.    ;--- Handle URL (just add to array, don't worry about duplicates here) ---
  12018.    #define ValidateUrlR                                                      \
  12019.            ;--- Make sure we validate a full URL -------------              -\
  12020.            #evaluate '' ^<$ValidateUrlR_REXX_FullUrl Type="{$Type}" URL="{$URL}">^  -\
  12021.                                                                             -\
  12022.            ;--- Add URL (in "FullUrl" var) to end of array ---              -\
  12023.            #RexxVar ValUrlCount + 1                                         -\
  12024.            #RexxVar ValUtlList.ValUrlCount = FullUrl                        -\
  12025.                                                                             -\
  12026.            ;--- Add location ---------------------------------              -\
  12027.            #evaluate '' ^<$ValidateUrlR_REXX_Location>^                     -\
  12028.            #RexxVar ValUtlLocn.ValUrlCount = UrlSourceLocation
  12029.    #DefineRexx ValidateUrlR_REXX_FullUrl
  12030.                ;--- Make sure URL starts with "http:" etc ---
  12031.                UrlType = "{$Type}";
  12032.                FullUrl = "{$URL}";
  12033.                if  abbrev(FullUrl, UrlType) = 0 then;
  12034.                    FullUrl = UrlType || FullUrl;
  12035.  
  12036.                ;--- Remove any "#section" bit ---
  12037.                #Option PUSH AllowPack=NO
  12038.                parse var FullUrl (UrlType) httpServer '/' HttpPageAddr;
  12039.                #Option POP
  12040.                parse var HttpPageAddr HttpPageAddr '#';
  12041.                FullUrl = UrlType || httpServer || '/' || HttpPageAddr;
  12042.    #DefineRexx
  12043.    #ifndef ValidateUrlR_REXX_Location              ;;Allow caller to create their own "location"
  12044.        #DefineRexx ValidateUrlR_REXX_Location
  12045.                    #Option PUSH AllowPack=NO
  12046.                    do  IncIndex = 1 to <?IncludeLevel>
  12047.                    #Option POP
  12048.                        ;--- Format the input file at this level ---
  12049.                        ThisBit = _filespec('name', InputComponentLevel(IncIndex));
  12050.                        ThisBit = ThisBit || '(' || AddCommasToDecimalNumber(InputComponentLineLevel(IncIndex)) || ')';
  12051.  
  12052.                        ;--- Update location string ----------------
  12053.                        if  IncIndex = 1 then
  12054.                            UrlSourceLocation = ThisBit;
  12055.                        else
  12056.                            UrlSourceLocation = UrlSourceLocation || '->' || ThisBit;
  12057.                    end
  12058.        #DefineRexx
  12059.    #endif
  12060.  
  12061.    ;--- Work though URL list and end of successful build --------------------
  12062.    #define ProcessRemoteUrlList                                \
  12063.            #if [ValUrlCount = 0]                              -\
  12064.                #info 'No remote URLs to validate'             -\
  12065.            #elseif                                            -\
  12066.                #info 'Validating <??ValUrlCount> remote URLs' -\
  12067.                ;--- Sort the array ---                        -\
  12068.                #RexxVar ValUtlList.0 = ValUrlCount            -\
  12069.                #evaluate '' ^<$GenRexx2Sort2Arrays ARRAY1='ValUtlList' ARRAY2='ValUtlLocn'>^ -\
  12070.                                                               -\
  12071.                ;--- Process the array ---                     -\
  12072.                #evaluate '' ^<$ProcessRemoteUrlList_REXX>^    -\
  12073.            #endif
  12074.    #DefineRexx ProcessRemoteUrlList_REXX_COMMON_START
  12075.            ;--- Work through URL list (drop duplicates) ---
  12076.            LastUrl = '';
  12077.            LastLoc = '';
  12078.            do  UrlIndex = 1 to ValUtlList.0
  12079.                ThisUrl = ValUtlList.UrlIndex;
  12080.                ThisLoc = ValUtlLocn.UrlIndex;
  12081.                if  ThisUrl <> LastUrl | ThisLoc <> LastLoc then;
  12082.                do
  12083.    #DefineRexx
  12084.    #DefineRexx ProcessRemoteUrlList_REXX_COMMON_END
  12085.                    LastUrl = ThisUrl;
  12086.                    LastLoc = ThisLoc;
  12087.                end;
  12088.            end;
  12089.    #DefineRexx
  12090.  
  12091.    ;--- What are we doing with the list of URLs? ----------------------------
  12092.    #ifndef ProcessRemoteUrlList_REXX
  12093.        #ifdef  VALRURL_CHECK_LATER_MASK
  12094.            ;--- Generate file (user will check URLs later / when online) ----
  12095.            #DefineRexx ProcessRemoteUrlList_REXX
  12096.                    ;--- We already know URL filename & its been deleted ---
  12097.                    call Info 'Generating: ' || UrlListFile;
  12098.                    call lineout UrlListFile, ';---';
  12099.                    call lineout UrlListFile, ';--- Remote URLs from "<?InputFile>"';
  12100.                    call lineout UrlListFile, ';--- Use PPWCURL.CMD under OS/2 or other similar';
  12101.                    call lineout UrlListFile, ';--- tool to process the list.';
  12102.                    call lineout UrlListFile, ';---';
  12103.                    call lineout UrlListFile, '';
  12104.                    call lineout UrlListFile, '';
  12105.  
  12106.                    ;--- Now work through the list of URLs ---
  12107.                    <$ProcessRemoteUrlList_REXX_COMMON_START>;
  12108.                        ;--- Need to output new location pragma? ---
  12109.                        if  ThisLoc <> LastLoc then
  12110.                            call lineout UrlListFile, ';PRAGMA(URL_SOURCE)=' || ThisLoc;
  12111.  
  12112.                        call lineout UrlListFile, ThisUrl;
  12113.                    <$ProcessRemoteUrlList_REXX_COMMON_END>;
  12114.  
  12115.                    ;--- Close the listing file ---
  12116.                    call DieIfIoErrorOccurred UrlListFile;
  12117.                    CloseRc = stream(UrlListFile, 'c', 'close');
  12118.            #DefineRexx
  12119.        #elseif
  12120.            ;--- We are online, do immediate check of URLs -------------------
  12121.            #DefineRexx ProcessRemoteUrlList_REXX
  12122.                    <$ProcessRemoteUrlList_REXX_COMMON_START>;
  12123.                        ;--- Calculate ID for this URL ---
  12124.                        FullPageId     = '!R_' || c2x(ThisUrl);
  12125.                        FullPageIdStat = symbol(FullPageId);    ;;Exists/Name too long?
  12126.  
  12127.                        ;--- Already done this URL (previous build)? ---
  12128.                        if  FullPageIdStat = 'VAR' then;
  12129.                            UrlChkRc = _valueG(FullPageId);   ;;Already know if valid!
  12130.                        else;
  12131.                        do;
  12132.                            ;--- Haven't checked yet ---
  12133.                            interpret 'UrlChkRc = "<??UrlCheckerPgm>"("CHECK1URL " || ThisUrl)';
  12134.  
  12135.                            ;--- Set ID so we won't repeat this exercise! ---
  12136.                            if  FullPageIdStat <> 'BAD' then;
  12137.                                call _valueS FullPageId, UrlChkRc;
  12138.                        end;
  12139.  
  12140.                        ;--- Handle return code ---
  12141.                        if  UrlChkRc = 'OK' then;
  12142.                        do;
  12143.                            <$VALRURL_VALIDATED_OK_REXX>;
  12144.                        end;
  12145.                        else;
  12146.                        do;
  12147.                            <$VALRURL_FAILED_VALIDATION_REXX>;
  12148.                        end;
  12149.                    <$ProcessRemoteUrlList_REXX_COMMON_END>;
  12150.            #DefineRexx
  12151.        #endif
  12152.    #endif
  12153.  
  12154. #endif
  12155.  
  12156.  
  12157. ΓòÉΓòÉΓòÉ 9.4.1. PPWCURL.CMD - Program to Check URLS (Windows and OS/2) ΓòÉΓòÉΓòÉ
  12158.  
  12159. PPWCURL.CMD - Program to Check URLS (Windows and OS/2) 
  12160.  
  12161. This program's basic task is to check URLs in an attempt to eliminate 404 
  12162. errors etc from your web pages. 
  12163.  
  12164. The "VALRURL.H" header file macros is one way that URL lists could be created. 
  12165. Another is the Netscape "Create URL object" option (or Netscape drag and drop 
  12166. pages). 
  12167.  
  12168. This program works under OS/2 and Windows (tested on NT). 
  12169.  
  12170. Syntax 
  12171.  
  12172.     PPWCURL[.CMD]  Command  [CommandsParameters] [Options]
  12173.  
  12174. The program takes a number of commands as follows: 
  12175.  
  12176.        1. VERSION? 
  12177.           The program will return (not displayed) its version number. 
  12178.  
  12179.        2. SOCKETVERSION? 
  12180.           The program will return (not displayed) the version of "RxSock.DLL" 
  12181.           in use (for "http" checks). 
  12182.  
  12183.        3. FTPVERSION? 
  12184.           The program will return (not displayed) the version of "RxFtp.DLL" in 
  12185.           use (for "ftp" checks). 
  12186.  
  12187.        4. SOCKETREADY? 
  12188.           The program will return (not displayed) "OK" if "http" checking is 
  12189.           possible or a reason why not. 
  12190.  
  12191.        5. FTPREADY? 
  12192.           The program will return (not displayed) "OK" if "ftp" checking is 
  12193.           possible or a reason why not. 
  12194.  
  12195.        6. CHECK1URL OneUrl 
  12196.           The program will return (not displayed) "OK" if the URL (with begins 
  12197.           with "http://" or "ftp://" can be accessed or a reason why it 
  12198.           couldn't. 
  12199.  
  12200.        7. CHECKLISTEDURLS [+]UrlFileMask1 ... 
  12201.           The program will read the file or files specified and sort the URLs 
  12202.           listed. If the file mask is preceeded by "+" then all subdirectories 
  12203.           below the one specified are also processed. 
  12204.  
  12205.           This option also allows OS/2 WPS URL objects to be tested, just open 
  12206.           up the properties to determine the path. 
  12207.  
  12208.           Within each file blank lines and lines that begin with ';' are 
  12209.           ignored as is leading and trailing whitespace on all lines and URL 
  12210.           duplicates. 
  12211.  
  12212.           The progress of URL checking is displayed on screen and the return 
  12213.           code is the total number of failing URL's. 
  12214.  
  12215.           It is highly recommended that you use the "/CheckDays" switch even if 
  12216.           you give it a value of 1 (recheck every day). 
  12217.  
  12218.        8. CHECKURLSINHTML [+]HtmlFileMask1 ... 
  12219.           The program will read the file or files specified. The files are 
  12220.           scanned for URLs, otherwise it functions pretty much like the 
  12221.           "CHECKLISTEDURLS" command. 
  12222.  
  12223.  PPWCURL Options 
  12224.  
  12225.        1. /MemoryFile[:NameOfFile] 
  12226.           A memory file is used to hold details about checked URLs. It becomes 
  12227.           really useful if the "/CheckDays" option is also used as this program 
  12228.           will then not retest all URLs but can be more selective (for example 
  12229.           not retest URLs you only checked yesterday). 
  12230.  
  12231.        2. /CheckDays[:OkUrlMinAge[-OkUrlMaxAge]] 
  12232.           This will determine how long ago is too long since the last 
  12233.           successful URL check. For example setting this to 14-14 means that a 
  12234.           URL which tested OK today will not be retested for 2 weeks. You must 
  12235.           have used the "/MemoryFile" switch to specify a file. 
  12236.  
  12237.           If you had have said "14-21" then for each URL a random day between 
  12238.           14 and 21 would be chosen. This allows the URL checking to gradually 
  12239.           spread, that is every two weeks you are not doing the full check. 
  12240.  
  12241.           Note that once a URL has failed this checking is bypassed, the next 
  12242.           time you run this program will will always retest URLs that failed on 
  12243.           the previous run. 
  12244.  
  12245.        3. /ForgetDays[:NumberOfDays] 
  12246.           By default old URLs are dropped from memory if not referred to for a 
  12247.           significant period of time. This option can be used to specify how 
  12248.           old a URL can become or to turn off the dropping (don't specify a 
  12249.           value). 
  12250.  
  12251.        4. /ReadTimeOut[:NumberOfSeconds] 
  12252.           Allows you to specify the maximum number of seconds we will wait for 
  12253.           a server to respond to a request. A blank value will restore default. 
  12254.  
  12255.        5. /TimeOutRetry[:NumberOfSeconds] 
  12256.           If a URL check fails with a timeout, you may specify that after URL 
  12257.           checking has completed that these URLs be retried. If a value of 0 is 
  12258.           supplied you don't wish a retry otherwise the value represents the 
  12259.           timeout value in seconds that should be used. A blank value will 
  12260.           restore default. It may be wise to increase the value past that used 
  12261.           on the "/ReadTimeOut" switch. 
  12262.  
  12263.        6. /GetEnv:NameOfEnvVar 
  12264.           Allows you to pick up options from an environment variable. 
  12265.  
  12266.        7. /ErrorFile[:[+]NameOfFile] 
  12267.           Create new or append to old error file. This file will hold the 
  12268.           complete list of failing URLs along with the reason for the failure 
  12269.           in a format that this program can accept as input (rename file 
  12270.           first!). This is probably less useful if "/IniCheckDays" is 
  12271.           specified. 
  12272.  
  12273.        8. /FtpEmail:YourEmailAddress 
  12274.           When checking FTP addresses this value is used for the password to 
  12275.           the "Anonymous" user, if not supplied a default (obviously incorrect) 
  12276.           value is used. 
  12277.  
  12278.        9. /TestUrl[:Url] 
  12279.           I don't know of any way I can tell if the network is available. By 
  12280.           default a known internet URL is checked as this is expected to exist, 
  12281.           if found you must have access to the internet.  You can either change 
  12282.           URLs (if testing intranet URLs etc) or turn it off altogether. 
  12283.  
  12284.       10. /MemoryBackupLevel[:Level] 
  12285.           This determines how many memory file backups are kept. A value of 0 
  12286.           turns off backups otherwise a value of 1 to 9 is required. 
  12287.  
  12288.       11. /AskIfMoveOk[:YES|NO] 
  12289.           When URLs are moved you may or may not wish to update your address. 
  12290.           Some sites stupidly force moves which they believe will never be seen 
  12291.           by a user (although what these sites are doing does slow the browser 
  12292.           slightly). Rather than treat each move as an error you can be asked 
  12293.           for your opinion (after all other checking has taken place). 
  12294.  
  12295.  PPWCURL Environment Variables 
  12296.  
  12297.        1. PPWCURL_DEBUG=[+]NameOfFile 
  12298.           Create new or append to old debug file. This file will hold much more 
  12299.           detail about the programs internal workings. This will slow down URL 
  12300.           checking. If reporting problems with this command please send me the 
  12301.           debug output. 
  12302.  
  12303.        2. PPWCURL_OPTIONS=Options 
  12304.           This allows you to specify command line options in the environment. 
  12305.  
  12306.  When a filename is required it may contain the text "{Date}" or "{Time}", 
  12307.  these get replaced with "yyyymmdd" or "hhmmss". 
  12308.  
  12309.  EXAMPLE 
  12310.  
  12311.  This batch file reads in 40 or so ".URL" files (created when I built my web 
  12312.  pages - see "VALRURL.H") as well as the list of WPS URLs that I have collected 
  12313.  in multiple folders: 
  12314.  
  12315.   @echo off
  12316.   setlocal
  12317.  
  12318.  
  12319.   REM *** WANT a DEBUG FILE (19990820.DBG etc) ********************************
  12320.   set    ppwcurl_debug=out\remote.url\{Date}.DBG
  12321.  
  12322.   REM *** INIT COMMAND LINE OPTIONS *******************************************
  12323.   SET CLOPTIONS=
  12324.  
  12325.   REM *** WANT a ERROR FILE (19990820.ERR etc) ********************************
  12326.   SET CLOPTIONS=%CLOPTIONS%  /ErrorFile:out\remote.url\{Date}.ERR
  12327.  
  12328.   REM *** SET UP SOME LONG TERM MEMORY ****************************************
  12329.   SET CLOPTIONS=%CLOPTIONS%  /MemoryFile:out\remote.url\CheckUrl.MEM
  12330.  
  12331.   REM *** Check only if last checked 20-30 days ago (spreads out checking) ****
  12332.   SET CLOPTIONS=%CLOPTIONS%  /CheckDays:20-30
  12333.  
  12334.   REM Drop URLs we haven't looked at for more than 100 days *******************
  12335.   SET CLOPTIONS=%CLOPTIONS%  /ForgetDays:100
  12336.  
  12337.   REM *** Don't wait more than 15 seconds for a response from server **********
  12338.   SET CLOPTIONS=%CLOPTIONS%  /ReadTimeout:15
  12339.  
  12340.   REM *** Test all WPS URLs (in "E:\DB\URLS" and subfolders) created by    ****
  12341.   REM *** Netscape ("Create URL object" or with GUI gizmo near "bookmarks")****
  12342.   REM *** Also "*.URL" files (All URLs used in my web pages - VALRURL.H)   ****
  12343.   ppwcurl.cmd CheckListedUrls +E:\DB\URLS\*.*  out\remote.url\*.URL  %CLOPTIONS%
  12344.  
  12345.  
  12346.   REM *** Test URLs in HTML pages *********************************************
  12347.   REM ppwcurl.cmd CheckUrlsInHtml out\*.htm  %CLOPTIONS%
  12348.  
  12349.  Note that the batch file does not retest a previously successfully tested URL 
  12350.  for 20-30 days, this means that usually I'm only testing new or previously 
  12351.  failed URLs, plus a small number of older URLs. 
  12352.  
  12353.  
  12354. ΓòÉΓòÉΓòÉ 9.5. PPWSORT.H - Sorting ΓòÉΓòÉΓòÉ
  12355.  
  12356. PPWSORT.H - Sorting 
  12357.  
  12358. PPWIZARD has an internal sort routine called SortArray(), where possible it is 
  12359. recommended that it be used however the header file has the following 
  12360. advantages: 
  12361.  
  12362.        1. You can generate sort code inline when generating Rexx code 
  12363.           (PPWIZARD's internal code will not be available when the generated 
  12364.           code executes!). 
  12365.  
  12366.        2. You can sort more than one array at a time, this allows you to keep 
  12367.           associated information together. 
  12368.  
  12369.        3. The compare operation can be as complex as you wish. 
  12370.  
  12371.        4. If you wish to sort an array with a known name (probably usual thing 
  12372.           in PPWIZARD code) and there are many entries in the array then the 
  12373.           sort can be much faster. 
  12374.  
  12375.  There are two generic macros you can choose from, "SortArray" generates a 
  12376.  PPWIZARD #evaluate command to perform the sort and "GenRexx2Sort" which 
  12377.  generates the rexx code. 
  12378.  
  12379.  The first element in the array(s) is element 1 (not 0). 
  12380.  
  12381.  The Generic Macro Parameters 
  12382.  
  12383.        1. COUNT 
  12384.           This is used to supply the number of elements that you are sorting. 
  12385.  
  12386.        2. PREFIX 
  12387.           By default the all variables used in the generated sort code are 
  12388.           prefixed by "Srt" this parameter gives you the chance to remove any 
  12389.           conflicts you may have (you may already have your own variables that 
  12390.           begin with "Srt"). 
  12391.  
  12392.        3. GREATER 
  12393.           You need to supply the rexx code which sets the "SrtGreater" variable 
  12394.           to "1" if the first element is greater than the second or '0' 
  12395.           otherwise. If the name of the array can't be hard coded (its name is 
  12396.           held in a variable), the rexx value() routine will need to be used 
  12397.           for all variable accesses. 
  12398.  
  12399.        4. SWAP 
  12400.           You need to supply the rexx code which swaps elements. 
  12401.  
  12402.  The last two macro parameters will need to use the "SrtIndex1" and "SrtIndex2" 
  12403.  variables (using default prefix!) which hold the indexes of the elements to be 
  12404.  compared or swapped. 
  12405.  
  12406.  Some Non-Generic macros 
  12407.  
  12408.  While the generic macros above are very powerful (you can do anything after 
  12409.  all) most people will probably never use them and use the macros described 
  12410.  below (some of the same generic macro parameters are supported). 
  12411.  
  12412.  There are 2 macros which you can use to sort either 1 or 2 arrays (whose names 
  12413.  are known - fixed). The default is that the ".0" element holds the number of 
  12414.  items in the array and the sort is ascending. The macros are 
  12415.  "GenRexx2Sort1Array" and "GenRexx2Sort2Arrays". With the 2 array sort macro 
  12416.  the first array is sorted and the 2nd array is assumed to hold associated 
  12417.  data. 
  12418.  
  12419.  There is one macros which you can use to sort a single array whose name is 
  12420.  only known at runtime (not fixed), its name is "GenRexx2Sort1ArrayIndirect". 
  12421.  
  12422.  EXAMPLES 
  12423.  
  12424.  This example shows the named array "Fred" being sorted: 
  12425.  
  12426.          <$GenRexx2Sort1Array ARRAY="Fred">;
  12427.  
  12428.  This time we want the first 4 items sorted in decending order: 
  12429.  
  12430.          <$GenRexx2Sort1Array ARRAY="Fred" Compare="<" Count="4">;
  12431.  
  12432.  We want a "SortArray" routine in our generated rexx code: 
  12433.  
  12434.          ...
  12435.          call SortArray "fred";
  12436.          return;
  12437.          ...
  12438.          ...
  12439.          /*==========*/
  12440.          SortArray:
  12441.          /*==========*/
  12442.              ArrayNamedIn = translate(arg(1));  ;;Holds name of array
  12443.  
  12444.              <$GenRexx2Sort1ArrayIndirect NamedIn="ArrayNamedIn">;
  12445.              return;
  12446.  
  12447.  PPWSORT.H 
  12448.  
  12449.   ;----------------------------------------------------------------------------
  12450.   ;     MODULE NAME:   PPWSORT.H
  12451.   ;
  12452.   ;         $Author:   Dennis_Bareis  $
  12453.   ;       $Revision:   1.2  $
  12454.   ;           $Date:   02 Oct 1999 18:40:58  $
  12455.   ;        $Logfile:   E:/DB/PVCS.IT/OS2/PPWIZARD/PPWSORT.H_V  $
  12456.   ;
  12457.   ;     DESCRIPTION:   PPWIZARD has a "SortArray()" routine which can be used
  12458.   ;                    to sort a single array.  It does have some flexability
  12459.   ;                    in how it compares entries.
  12460.   ;
  12461.   ;                    This header file would be used to handle sort
  12462.   ;                    requirements that are not possible using "SortArray()".
  12463.   ;
  12464.   ;                    This header allows you to:
  12465.   ;
  12466.   ;                         * Imbed the sort routine between PPWIZARD commands.
  12467.   ;
  12468.   ;                         * Imbed the sort routine between rexx     commands.
  12469.   ;
  12470.   ;                         * Sort more than one array at a time, for example
  12471.   ;                           you may have multiple arrays storing associated
  12472.   ;                           information that should all be sorted together.
  12473.   ;
  12474.   ;                         * Do any sort of compare, no matter how complex.
  12475.   ;
  12476.   ;
  12477.   ;                     EXAMPLE1 - Inline Rexx code (use "SortArray" for inline
  12478.   ;                                PPWIZARD code). Array 'A' is being sorted.
  12479.   ;                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  12480.   ;                     ArrayName = arg(1);      ;;Caller passed "A"
  12481.   ;                     <$GenRexx2Sort                                                                                      \
  12482.   ;                          COUNT=^_valueG(ArrayName || '.0')^                                                             \
  12483.   ;                        GREATER=^SrtGreater = _valueG(ArrayName || '.SrtIndex1') >> _valueG(ArrayName || '.SrtIndex2')^  \
  12484.   ;                           SWAP=^SrtTemp = _valueG(ArrayName || '.SrtIndex1');                                          -\
  12485.   ;                                 call _valueS ArrayName || '.SrtIndex1', _valueG(ArrayName || '.SrtIndex2');            -\
  12486.   ;                                 call _valueS ArrayName || '.SrtIndex2', SrtTemp                                        -\
  12487.   ;                                ^                                                                                       -\
  12488.   ;                     >
  12489.   ;
  12490.   ;                     Note ">>" being used in the compare, if the data being
  12491.   ;                     sorted is numeric use '>' instead (or else)!!!!!!
  12492.   ;
  12493.   ;                     EXAMPLE2 - Exactly same as Example 1
  12494.   ;                                hardcoded - can't handle other arrays).
  12495.   ;                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  12496.   ;                     ArrayName = translate(arg(1));      ;;Caller passed "A" (handle possible value() bug!)
  12497.   ;                     <$GenRexx2Sort1ArrayIndirect NamedIn="ArrayName">
  12498.   ;
  12499.   ;                     EXAMPLE3 - In this case the name of the array ("A" is
  12500.   ;                                hardcoded - can't handle other arrays).
  12501.   ;                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  12502.   ;                     <$GenRexx2Sort1Array ARRAY="A">
  12503.   ;
  12504.   ;----------------------------------------------------------------------------
  12505.  
  12506.  
  12507.   ;--- Only include once ------------------------------------------------------
  12508.   #ifndef VERSION_PPWSORT_H
  12509.  
  12510.  
  12511.   ;--- Define the version number of this header file --------------------------
  12512.   #define   VERSION_PPWSORT_H    99.269
  12513.   #require  99.269
  12514.  
  12515.  
  12516.   ;--- For use within PPWIZARD for immediate sorting of array (PPWIZARD Command!) ---
  12517.   #define SortArray    \
  12518.           #evaluate '' ^<$GenRexx2Sort COUNT={$COUNT} GREATER={$GREATER} SWAP={$SWAP}>^
  12519.  
  12520.   ;--- Generates the rexx code to perform sorting (sort one "NAMED" array) ----
  12521.   #define GenRexx2Sort1Array                                        \
  12522.           <$GenRexx2Sort                                            \
  12523.                COUNT=^{$Count="{$Array}.0"}^                        \
  12524.               PREFIX=^{$Prefix="Srt"}^                              \
  12525.              GREATER=^SrtGreater = {$Array}.SrtIndex1 {$Compare=">"} {$Array}.SrtIndex2^  \
  12526.                 SWAP=^SrtTemp = {$Array}.SrtIndex1;                -\
  12527.                       {$Array}.SrtIndex1 = {$Array}.SrtIndex2;     -\
  12528.                       {$Array}.SrtIndex2 = SrtTemp                 -\
  12529.                      ^                                             -\
  12530.           >
  12531.  
  12532.   ;--- Generates the rexx code to perform sorting (sort 2 "NAMED" arrays) -----
  12533.   #define GenRexx2Sort2Arrays                                                    \
  12534.           <$GenRexx2Sort                                                         \
  12535.                COUNT=^{$Count="{$Array1}.0"}^                                    \
  12536.               PREFIX=^{$Prefix="Srt"}^                                           \
  12537.              GREATER=^{$Prefix}Greater = {$Array1}.{$Prefix}Index1 {$Compare=">"} {$Array1}.{$Prefix}Index2^ \
  12538.                 SWAP=^{$Prefix}Temp = {$Array1}.{$Prefix}Index1;                -\
  12539.                       {$Array1}.{$Prefix}Index1 = {$Array1}.{$Prefix}Index2;    -\
  12540.                       {$Array1}.{$Prefix}Index2 = {$Prefix}Temp;                -\
  12541.                       {$Prefix}Temp = {$Array2}.{$Prefix}Index1;                -\
  12542.                       {$Array2}.{$Prefix}Index1 = {$Array2}.{$Prefix}Index2;    -\
  12543.                       {$Array2}.{$Prefix}Index2 = {$Prefix}Temp                 -\
  12544.                      ^                                                          -\
  12545.           >
  12546.  
  12547.  
  12548.   ;--- Generates the rexx code to perform sorting (array name not hard coded) -
  12549.   #define GenRexx2Sort1ArrayIndirect                                                                             \
  12550.           <$GenRexx2Sort                                                                                         \
  12551.                COUNT=^{$Count="_valueG({$NamedIn} || '.0')"}^                                                    \
  12552.               PREFIX=^{$Prefix="SRT"}^                                                                           \
  12553.              GREATER=^{$Prefix}Greater = _valueG({$NamedIn} || '.{$Prefix}INDEX1') {$Compare=">"} _valueG({$NamedIn} || '.{$Prefix}INDEX2')^  \
  12554.                 SWAP=^{$Prefix}Temp = _valueG({$NamedIn} || '.{$Prefix}INDEX1');                                -\
  12555.                       call _valueS {$NamedIn} || '.{$Prefix}INDEX1', _valueG({$NamedIn} || '.{$Prefix}INDEX2'); -\
  12556.                       call _valueS {$NamedIn} || '.{$Prefix}INDEX2', {$Prefix}Temp                              -\
  12557.                      ^                                                                                          -\
  12558.           >
  12559.  
  12560.   ;--- Generates the rexx code to perform sorting (GENERIC) -------------------
  12561.   #DefineRexx GenRexx2Sort
  12562.              {$Prefix="SRT"}M = 1
  12563.              {$Prefix}Count   = {$COUNT};
  12564.              do  while (9 * {$Prefix}M + 4) < {$Prefix}Count
  12565.                  {$Prefix}M = {$Prefix}M * 3 + 1
  12566.              end /* do while */
  12567.              do  while {$Prefix}M > 0
  12568.                  {$Prefix}K = {$Prefix}Count - {$Prefix}M
  12569.                  do  {$Prefix}J = 1 to {$Prefix}K
  12570.                      {$Prefix}Index1 = {$Prefix}J
  12571.                      do while {$Prefix}Index1 > 0
  12572.                          ;--- Work out what to compare it with ----------------
  12573.                          {$Prefix}Index2 = {$Prefix}Index1 + {$Prefix}M;
  12574.  
  12575.                          ;--- User user supplied logic to check for greater ---
  12576.                          {$Greater};
  12577.  
  12578.                          ;--- Swap if required --------------------------------
  12579.                          if {$Prefix}Greater then
  12580.                          do
  12581.                              {$Swap};
  12582.                          end;
  12583.                          else
  12584.                              leave;
  12585.  
  12586.                          ;--- Prepare for the next loop -----------------------
  12587.                          {$Prefix}Index1 = {$Prefix}Index1 - {$Prefix}M
  12588.  
  12589.                      end /* do while {$Prefix}Index1 > 0 */
  12590.                  end     /* do {$Prefix}J = 1 to {$Prefix}K */
  12591.                  {$Prefix}M = {$Prefix}M % 3
  12592.              end         /* while {$Prefix}M > 0 */
  12593.   #DefineRexx
  12594.  
  12595.  
  12596.  
  12597.  
  12598.   #ifdef   CommentBlock  /* (Saturday 07/08/1999, 20:32:20, by Dennis_Bareis) */
  12599.   **+--------------------------------------------------------------------------
  12600.   **|;--- Generates the rexx code to perform sorting (GENERIC) -------------------
  12601.   **|#DefineRexx GenRexx2Sort
  12602.   **|        {$Prefix="Srt"}Count    = {$COUNT};
  12603.   **|        {$Prefix}Distance = {$Prefix}Count % 2;
  12604.   **|        do  while {$Prefix}Distance > 0
  12605.   **|            do  until {$Prefix}Finished;      /* start of mini-bubblesort loop */
  12606.   **|                {$Prefix}Finished = 1;
  12607.   **|                do  {$Prefix}Index1 = 1 to {$Prefix}Count - {$Prefix}Distance
  12608.   **|                    ;--- We now compare and swap items {$Prefix}Index1 and {$Prefix}Index1+{$Prefix}Distance ---
  12609.   **|                    {$Prefix}Index2 = {$Prefix}Index1 + {$Prefix}Distance;
  12610.   **|
  12611.   **|                    ;--- User user supplied logic to check for greater ---
  12612.   **|                    {$GREATER};
  12613.   **|
  12614.   **|                    ;--- Swap if required --------------------------------
  12615.   **|                    if {$Prefix}Greater then
  12616.   **|                    do
  12617.   **|                        ;--- User user supplied logic to swap items ------
  12618.   **|                        {$Swap};
  12619.   **|                        {$Prefix}Finished = 0;
  12620.   **|                    end;
  12621.   **|                end;
  12622.   **|            end;                       /* end of mini-bubblesort loop */
  12623.   **|            {$Prefix}Distance = {$Prefix}Distance % 2;
  12624.   **|        end;
  12625.   **|#DefineRexx
  12626.   **+--------------------------------------------------------------------------
  12627.   #endif                 /* (Saturday 07/08/1999, 20:32:20, by Dennis_Bareis) */
  12628.  
  12629.  
  12630.   #endif
  12631.  
  12632.  
  12633.  
  12634.  
  12635.  
  12636. ΓòÉΓòÉΓòÉ 9.6. OL_DOC.DH - Document Creation ΓòÉΓòÉΓòÉ
  12637.  
  12638. OL_DOC.DH - Document Creation 
  12639.  
  12640. The header file "OL_DOC.DH" provides a powerful range of facilities to allow 
  12641. you to create electronic documentation. It currently supports IPF/INF and HTML 
  12642. generation but there is no reason this can't be extended in the future. 
  12643.  
  12644. The IPF and HTML versions of the document you are now viewing were produced by 
  12645. the same method. 
  12646.  
  12647. Note that the facilities provided here much simplify the generation of complex 
  12648. documentation and I would recommend it's use even if you were limiting yourself 
  12649. to a single target output format. 
  12650.  
  12651. Using the facilities of this header file your source files need contain no IPF 
  12652. or HTML tags, although it is simple to conditionally include your own HTML or 
  12653. IPF tags as required. 
  12654.  
  12655. The examples batch files (below) will give you an idea of how to invoke 
  12656. ppwizard to generate documentation however please note that it is very 
  12657. important not to hardcode a filename on the /output switch when generating html 
  12658. or ppwizard will fail as each heading will try to update the same file. 
  12659.  
  12660. This is not a recommended way to produce HTML webpages. It's aim is to provide 
  12661. a subset of commands that are useful in the creation of documentation (which 
  12662. may of course be placed on the web). 
  12663.  
  12664. For more information have a look at the tags and options documentation as well 
  12665. as the simplistic example source. 
  12666.  
  12667. CREATING HTML OUTPUT 
  12668.  
  12669. This shows a simple batch file which takes a source file and generates one or 
  12670. more HTML pages: 
  12671.  
  12672. @echo off
  12673.  
  12674. REM *** Name of the .INF ****************************************************
  12675. setlocal
  12676. if     "%1" == "" SET INFNAME=TEST
  12677. if not "%1" == "" SET INFNAME=%1
  12678.  
  12679. REM *** Generate the .HTM ***************************************************
  12680. set DEBUG=/debug
  12681. set DEBUG=
  12682. call ppwizard.cmd %INFNAME%.D %DEBUG% /output:out\*.htm /crlf /define:DocType=HTML
  12683.  
  12684. Note that the /output switch above specified "out\*.htm", all pages will 
  12685. therefore be generated in the "out" directory and they will all have the 
  12686. extension ".htm". 
  12687.  
  12688. Note that the "*" is very important, you must not "hardcode" the name of the 
  12689. html file since for html generation each Heading generates a new page and with 
  12690. a hardcoded name each pages will use the same filename (and ppwizard will then 
  12691. fail)! 
  12692.  
  12693. CREATING IPF OUTPUT 
  12694.  
  12695. This shows a simple batch file which takes a source file and generates the IPF 
  12696. source which can then be compiled to generate an OS/2 INF file: 
  12697.  
  12698. @echo off
  12699.  
  12700. REM *** Name of the .INF ****************************************************
  12701. setlocal
  12702. if     "%1" == "" SET INFNAME=TEST
  12703. if not "%1" == "" SET INFNAME=%1
  12704.  
  12705. REM *** Generate the .IPF ***************************************************
  12706. set DEBUG=
  12707. set DEBUG=/debug
  12708. call ppwizard.cmd %INFNAME%.D %DEBUG% /output:out\*.ipf /crlf /define:DocType=IPF
  12709. if errorlevel 1 goto ERROR
  12710.  
  12711. REM *** Compile the .IPF to create a .INF ***********************************
  12712. SETLOCAL
  12713. CD OUT
  12714. IPFC.EXE   %INFNAME%.IPF /S /INF
  12715. if errorlevel 1 goto ERROR
  12716. goto EndBatch
  12717.  
  12718.  
  12719. :ERROR
  12720. echo ERROR: Somethings wrong!
  12721. :EndBatch
  12722.  
  12723.  
  12724. ΓòÉΓòÉΓòÉ 9.6.1. Tags ΓòÉΓòÉΓòÉ
  12725.  
  12726. Tags 
  12727.  
  12728. This section describes the tags that are available when you make use of the 
  12729. "OL_DOC.DH" header file. The document you are now viewing was produced using 
  12730. the tags documented here. There are some options which can be used to alter how 
  12731. the tags function. 
  12732.  
  12733. The following tags are heading and Heading and hypertext link related: 
  12734.  
  12735.          <$Heading> 
  12736.          <$HeadingAt> 
  12737.          <$HeadingDown> 
  12738.          <$HeadingRestore> 
  12739.          <$HeadingSave> 
  12740.          <$HeadingUp> 
  12741.          <$LinkTo> 
  12742.          <$Target> 
  12743.  
  12744.  The following tags are used to positioning text within your document: 
  12745.  
  12746.          <$BR> 
  12747.          <$P> 
  12748.  
  12749.  The following tags are used to format character text within your document: 
  12750.  
  12751.          <$Bold> 
  12752.          <$BoldItalic> 
  12753.          <$BoldUnderline> 
  12754.          <$DarkGreen> 
  12755.          <$Italic> 
  12756.          <$Magenta> 
  12757.          <$Red> 
  12758.  
  12759.  The following tags are used to handle different types of lists: 
  12760.  
  12761.          <$OrdList> 
  12762.          <$SimpleList> 
  12763.          <$UnNumberedList> 
  12764.          <$UnNumberedListCompact> 
  12765.          <$SimpleListCompact> 
  12766.          <$OrdListCompact> 
  12767.          <$Li> 
  12768.  
  12769.  The following tags are used to include examples: 
  12770.  
  12771.          <$ExampleFile> 
  12772.          <$Example> 
  12773.          <$ExampleFormatted> 
  12774.  
  12775.  The following tags are used to handle some problem characters: 
  12776.  
  12777.          <$Colon> 
  12778.          <$Amp> 
  12779.          <$NoBreakingBlank> 
  12780.  
  12781.  The following tags are used to generate an index for your document: 
  12782.  
  12783.          <$Index1> 
  12784.          <$Index2> 
  12785.  
  12786.  The following tags do not fit into any of the above categories: 
  12787.  
  12788.          <$DocumentStart> 
  12789.          <$DocumentEnd> 
  12790.          <$Title> 
  12791.  
  12792.  
  12793. ΓòÉΓòÉΓòÉ 9.6.1.1. Headings and Links ΓòÉΓòÉΓòÉ
  12794.  
  12795. Headings and Links 
  12796.  
  12797. The following tags are heading and Heading and hypertext link related: 
  12798.  
  12799.          <$Heading> 
  12800.          <$HeadingAt> 
  12801.          <$HeadingDown> 
  12802.          <$HeadingRestore> 
  12803.          <$HeadingSave> 
  12804.          <$HeadingUp> 
  12805.          <$LinkTo> 
  12806.          <$Target> 
  12807.  
  12808.  
  12809. ΓòÉΓòÉΓòÉ 9.6.1.1.1. <$Heading> ΓòÉΓòÉΓòÉ
  12810.  
  12811. <$Heading> 
  12812.  
  12813. This "OL_DOC.DH" tag allows you to specify a new section of your document at 
  12814. the current heading level. In a HTML document this will cause a new HTML page 
  12815. (file) to be created. The heading also marks a destination for a hypertext 
  12816. link. 
  12817.  
  12818. The following tags can be used to adjust the heading level: 
  12819.  
  12820.          <$HeadingAt> 
  12821.          <$HeadingUp> 
  12822.          <$HeadingDown> 
  12823.          <$HeadingRestore> 
  12824.          <$HeadingSave> 
  12825.  
  12826.  If you wish to allow hypertext linking to a section of documentation within 
  12827.  this heading (its not big enough for its own page) then you can use the 
  12828.  <$Target> tag. 
  12829.  
  12830.  SYNTAX 
  12831.  
  12832.       <$Heading  TEXT="?"  [ID="?"]>>
  12833.  
  12834.  The parameters for this tag are: 
  12835.  
  12836.          TEXT 
  12837.           This describes the text that should be used to describe this section 
  12838.           of the document. 
  12839.  
  12840.          ID 
  12841.           This is an optional parameter. If not supplied the "TEXT" parameter 
  12842.           also becomes the ID. The "ID" is an alias that is used in any 
  12843.           references to this section (such as on a "<$LinkTo>" tag). In most 
  12844.           cases you probably won't specify this parameter. The case of this 
  12845.           parameter is ignored. 
  12846.  
  12847.  
  12848. ΓòÉΓòÉΓòÉ 9.6.1.1.2. <$HeadingAt> ΓòÉΓòÉΓòÉ
  12849.  
  12850. <$HeadingAt> 
  12851.  
  12852. This "OL_DOC.DH" tag allows you to specify exactly at what "level" the next 
  12853. heading will be placed, valid values are 1 (top) to 6 (bottom). 
  12854.  
  12855. This is handy if you wish to enforce a particular level and not worry about 
  12856. using HeadingUp tags to restore the correct level. 
  12857.  
  12858. This is (or should be) a rarely used tag, even when required a better way would 
  12859. normally be to use HeadingSave and HeadingRestore. 
  12860.  
  12861. SYNTAX 
  12862.  
  12863.     <$HeadingAt  LEVEL="?">
  12864.  
  12865. The parameters for this tag are: 
  12866.  
  12867.          LEVEL 
  12868.           This should be a value between 1 and 6. 
  12869.  
  12870.  
  12871. ΓòÉΓòÉΓòÉ 9.6.1.1.3. <$HeadingDown> ΓòÉΓòÉΓòÉ
  12872.  
  12873. <$HeadingDown> 
  12874.  
  12875. This "OL_DOC.DH" tag allows you to increase the current heading level by one. 
  12876. An error will be generated if you attempt to generate a Heading at or above 
  12877. level 7! 
  12878.  
  12879. SYNTAX 
  12880.  
  12881.     <$HeadingDown>
  12882.  
  12883. There are no parameters for this tag. 
  12884.  
  12885.  
  12886. ΓòÉΓòÉΓòÉ 9.6.1.1.4. <$HeadingRestore> ΓòÉΓòÉΓòÉ
  12887.  
  12888. <$HeadingRestore> 
  12889.  
  12890. This "OL_DOC.DH" tag allows you to restore the heading level to a value that 
  12891. you previously saved. The advantage of this tag over the HeadingAt tag is that 
  12892. you don't need to know or care what the level is. 
  12893.  
  12894. SYNTAX 
  12895.  
  12896.     <$HeadingRestore  NAME="?">
  12897.  
  12898. The parameters for this tag are: 
  12899.  
  12900.          NAME 
  12901.           This should be the name that you used on the HeadingSave tag. 
  12902.  
  12903.  
  12904. ΓòÉΓòÉΓòÉ 9.6.1.1.5. <$HeadingSave> ΓòÉΓòÉΓòÉ
  12905.  
  12906. <$HeadingSave> 
  12907.  
  12908. This "OL_DOC.DH" tag allows you to "name" the current heading level. This 
  12909. allows you to restore it at some future location. 
  12910.  
  12911. SYNTAX 
  12912.  
  12913.     <$HeadingSave  NAME="?">
  12914.  
  12915. The parameters for this tag are: 
  12916.  
  12917.          NAME 
  12918.           This is the name that you wish to give the current heading level! 
  12919.  
  12920.  
  12921. ΓòÉΓòÉΓòÉ 9.6.1.1.6. <$HeadingUp> ΓòÉΓòÉΓòÉ
  12922.  
  12923. <$HeadingUp> 
  12924.  
  12925. This "OL_DOC.DH" tag allows you to decrease the current heading level by one. 
  12926. An error will be generated if you attempt to generate a Heading at or below 
  12927. level 0! 
  12928.  
  12929. SYNTAX 
  12930.  
  12931.     <$HeadingUp>
  12932.  
  12933. There are no parameters for this tag. 
  12934.  
  12935.  
  12936. ΓòÉΓòÉΓòÉ 9.6.1.1.7. <$LinkTo> ΓòÉΓòÉΓòÉ
  12937.  
  12938. <$LinkTo> 
  12939.  
  12940. This "OL_DOC.DH" tag allows you to create a hypertext link to another part of 
  12941. your document. Targets of the link can be specified with the following tags: 
  12942.  
  12943.          <$Heading> 
  12944.          <$Target> 
  12945.  
  12946.  Note that this tag can refer to target locations which are not yet defined. 
  12947.  This also means that the targets are not validated. 
  12948.  
  12949.  SYNTAX 
  12950.  
  12951.       <$LinkTo  TEXT="?"  [ID="?"]>  [TARGET="?"]>>
  12952.  
  12953.  The parameters for this tag are: 
  12954.  
  12955.          TEXT 
  12956.           This is the text that the user will click on to jump to the target 
  12957.           location in your document. 
  12958.  
  12959.          ID 
  12960.           This is an optional parameter. If not supplied the "TEXT" parameter 
  12961.           also becomes the ID. The "ID" is an alias that is used in any 
  12962.           references to this section (such as on a "<$LinkTo>" tag). In most 
  12963.           cases you probably won't specify this parameter. The case of this 
  12964.           parameter is ignored. 
  12965.  
  12966.          TARGET 
  12967.           You use this optional parameter to refer to a target you name with 
  12968.           the <$Target> tag. This parameter is ignored when generating IPF 
  12969.           documents. 
  12970.  
  12971.  
  12972. ΓòÉΓòÉΓòÉ 9.6.1.1.8. <$Target> ΓòÉΓòÉΓòÉ
  12973.  
  12974. <$Target> 
  12975.  
  12976. This "OL_DOC.DH" tag allows you to specify a destination for a hypertext link. 
  12977.  
  12978. In most cases you should organise your document so that each important 
  12979. component is in its own page (using the <$Heading> tag) however there will be 
  12980. times when the information is so small as to not need its own page. 
  12981.  
  12982. Note that this tag has no effect in IPF documents. 
  12983.  
  12984. The <$LinkTo> tag can be used to create a hypertext link to this heading. 
  12985.  
  12986. SYNTAX 
  12987.  
  12988.     <$Heading  NAME="?">
  12989.  
  12990. The parameters for this tag are: 
  12991.  
  12992.          NAME 
  12993.           This names the destination. To link to this named part of your 
  12994.           document you will need to use the "TARGET" parameter on the <$LinkTo> 
  12995.           tag. 
  12996.  
  12997.  
  12998. ΓòÉΓòÉΓòÉ 9.6.1.2. Text Positioning ΓòÉΓòÉΓòÉ
  12999.  
  13000. Text Positioning 
  13001.  
  13002. The following tags are used to positioning text within your document: 
  13003.  
  13004.          <$BR> 
  13005.          <$P> 
  13006.  
  13007.  
  13008. ΓòÉΓòÉΓòÉ 9.6.1.2.1. <$BR> ΓòÉΓòÉΓòÉ
  13009.  
  13010. <$BR> 
  13011.  
  13012. This "OL_DOC.DH" tag is used to position text. The following text will appear 
  13013. on a new line. This tag must appear on a line of its own. 
  13014.  
  13015. SYNTAX 
  13016.  
  13017.     <$BR>
  13018.  
  13019. EXAMPLE 
  13020.  
  13021.     <$p>The parameters for this tag are<$colon>
  13022.     <$UnNumberedList>
  13023.        <$li><$Bold Text="TEXT">
  13024.             <$Br>
  13025.             This text is made bold.
  13026.     <$eUnNumberedList>
  13027.  
  13028.  
  13029. ΓòÉΓòÉΓòÉ 9.6.1.2.2. <$P> ΓòÉΓòÉΓòÉ
  13030.  
  13031. <$P> 
  13032.  
  13033. This "OL_DOC.DH" tag is used to position text. The following text will appear 
  13034. in a new paragraph. 
  13035.  
  13036. SYNTAX 
  13037.  
  13038.     <$P>
  13039.  
  13040. EXAMPLE 
  13041.  
  13042.     <$p>This is paragraph 1.
  13043.  
  13044.     <$p>This is paragraph 2.
  13045.  
  13046.  
  13047. ΓòÉΓòÉΓòÉ 9.6.1.3. Character Formatting ΓòÉΓòÉΓòÉ
  13048.  
  13049. Character Formatting 
  13050.  
  13051. The following tags are used to format character text within your document: 
  13052.  
  13053.          <$Bold> 
  13054.          <$BoldItalic> 
  13055.          <$BoldUnderline> 
  13056.          <$DarkGreen> 
  13057.          <$Italic> 
  13058.          <$Magenta> 
  13059.          <$Red> 
  13060.  
  13061.  EXAMPLE - Source 
  13062.  
  13063.  This example does some simple formatting: 
  13064.  
  13065.   <$p>This paragraph contains <$Bold Text="some bold"> text!
  13066.  
  13067.   <$p><$DarkGreen Text=^This is a                               \
  13068.                         multi line (in source code at least)    \
  13069.                         paragraph which is completely green.   -\
  13070.                        ^>
  13071.  
  13072.  EXAMPLE - Generated Output 
  13073.  
  13074.  This paragraph contains some bold text! 
  13075.  
  13076.  This is a multi line (in source code at least) paragraph which is completely 
  13077.  green. 
  13078.  
  13079.  
  13080. ΓòÉΓòÉΓòÉ 9.6.1.3.1. <$Bold> ΓòÉΓòÉΓòÉ
  13081.  
  13082. <$Bold>
  13083.  
  13084. This "OL_DOC.DH" tag is used to adjust the character formatting of some text. 
  13085. The text will appear like this.
  13086.  
  13087. SYNTAX 
  13088.  
  13089.  
  13090. <$Bold  TEXT="?">
  13091.  
  13092. EXAMPLE 
  13093.  
  13094.  
  13095. <$Bold  TEXT="Some Text">.
  13096.  
  13097.  
  13098. ΓòÉΓòÉΓòÉ 9.6.1.3.2. <$BoldItalic> ΓòÉΓòÉΓòÉ
  13099.  
  13100. <$BoldItalic>
  13101.  
  13102. This "OL_DOC.DH" tag is used to adjust the character formatting of some text. 
  13103. The text will appear like this.
  13104.  
  13105. SYNTAX 
  13106.  
  13107.  
  13108. <$BoldItalic  TEXT="?">
  13109.  
  13110. EXAMPLE 
  13111.  
  13112.  
  13113. <$BoldItalic  TEXT="Some Text">.
  13114.  
  13115.  
  13116. ΓòÉΓòÉΓòÉ 9.6.1.3.3. <$BoldUnderline> ΓòÉΓòÉΓòÉ
  13117.  
  13118. <$BoldUnderline>
  13119.  
  13120. This "OL_DOC.DH" tag is used to adjust the character formatting of some text. 
  13121. The text will appear like this.
  13122.  
  13123. SYNTAX 
  13124.  
  13125.  
  13126. <$BoldUnderline  TEXT="?">
  13127.  
  13128. EXAMPLE 
  13129.  
  13130.  
  13131. <$BoldUnderline  TEXT="Some Text">.
  13132.  
  13133.  
  13134. ΓòÉΓòÉΓòÉ 9.6.1.3.4. <$DarkGreen> ΓòÉΓòÉΓòÉ
  13135.  
  13136. <$DarkGreen>
  13137.  
  13138. This "OL_DOC.DH" tag is used to adjust the character formatting of some text. 
  13139. The text will appear like this.
  13140.  
  13141. SYNTAX 
  13142.  
  13143.  
  13144. <$DarkGreen  TEXT="?">
  13145.  
  13146. EXAMPLE 
  13147.  
  13148.  
  13149. <$DarkGreen  TEXT="Some Text">.
  13150.  
  13151.  
  13152. ΓòÉΓòÉΓòÉ 9.6.1.3.5. <$Italic> ΓòÉΓòÉΓòÉ
  13153.  
  13154. <$Italic>
  13155.  
  13156. This "OL_DOC.DH" tag is used to adjust the character formatting of some text. 
  13157. The text will appear like this.
  13158.  
  13159. SYNTAX 
  13160.  
  13161.  
  13162. <$Italic  TEXT="?">
  13163.  
  13164. EXAMPLE 
  13165.  
  13166.  
  13167. <$Italic  TEXT="Some Text">.
  13168.  
  13169.  
  13170. ΓòÉΓòÉΓòÉ 9.6.1.3.6. <$Magenta> ΓòÉΓòÉΓòÉ
  13171.  
  13172. <$Magenta>
  13173.  
  13174. This "OL_DOC.DH" tag is used to adjust the character formatting of some text. 
  13175. The text will appear like this.
  13176.  
  13177. SYNTAX 
  13178.  
  13179.  
  13180. <$Magenta  TEXT="?">
  13181.  
  13182. EXAMPLE 
  13183.  
  13184.  
  13185. <$Magenta  TEXT="Some Text">.
  13186.  
  13187.  
  13188. ΓòÉΓòÉΓòÉ 9.6.1.3.7. <$Red> ΓòÉΓòÉΓòÉ
  13189.  
  13190. <$Red>
  13191.  
  13192. This "OL_DOC.DH" tag is used to adjust the character formatting of some text. 
  13193. The text will appear like this.
  13194.  
  13195. SYNTAX 
  13196.  
  13197.  
  13198. <$Red  TEXT="?">
  13199.  
  13200. EXAMPLE 
  13201.  
  13202.  
  13203. <$Red  TEXT="Some Text">.
  13204.  
  13205.  
  13206. ΓòÉΓòÉΓòÉ 9.6.1.4. Lists ΓòÉΓòÉΓòÉ
  13207.  
  13208. Lists 
  13209.  
  13210. The following tags are used to handle different types of lists: 
  13211.  
  13212.          <$OrdList> 
  13213.          <$SimpleList> 
  13214.          <$UnNumberedList> 
  13215.          <$UnNumberedListCompact> 
  13216.          <$SimpleListCompact> 
  13217.          <$OrdListCompact> 
  13218.          <$Li> 
  13219.  
  13220.  EXAMPLE - Source 
  13221.  
  13222.  This example does some simple formatting: 
  13223.  
  13224.   <$p>Things to do<$Colon>
  13225.   <$OrdListCompact>
  13226.      <$li>Make Perfect.
  13227.      <$li>Make sure all bugs removed.
  13228.      <$li>Finish doco.
  13229.      <$li>I'll never get here!
  13230.   <$eOrdListCompact>
  13231.  
  13232.   <$p>The parameters are<$Colon>
  13233.   <$UnNumberedList>
  13234.      <$li><$Bold Text="TEXT">
  13235.           <$br>
  13236.           This is the text that the user will click on.
  13237.  
  13238.      <$li><$Bold Text="TARGET">
  13239.           <$br>
  13240.           You use this optional parameter to refer to a target.
  13241.   <$eUnNumberedList>
  13242.  
  13243.  EXAMPLE - Generated Output 
  13244.  
  13245.  Things to do: 
  13246.  
  13247.        1. Make Perfect. 
  13248.        2. Make sure all bugs removed. 
  13249.        3. Finish doco. 
  13250.        4. I'll never get here! 
  13251.  
  13252.  The parameters are: 
  13253.  
  13254.          TEXT 
  13255.           This is the text that the user will click on. 
  13256.  
  13257.          TARGET 
  13258.           You use this optional parameter to refer to a target. 
  13259.  
  13260.  
  13261. ΓòÉΓòÉΓòÉ 9.6.1.4.1. <$LI> - List Item ΓòÉΓòÉΓòÉ
  13262.  
  13263. <$LI> - List Item 
  13264.  
  13265. This "OL_DOC.DH" tag is used to specify a new list item. Lists are declared 
  13266. using one of the following tags: 
  13267.  
  13268.          <$OrdList> 
  13269.          <$UnNumberedList> 
  13270.          <$UnNumberedListCompact> 
  13271.          <$OrdListCompact> 
  13272.  
  13273.  SYNTAX 
  13274.  
  13275.       <$LI>
  13276.  
  13277.  There are no parameters for this tag. 
  13278.  
  13279.  For an example have a look at the Lists documentation. 
  13280.  
  13281.  
  13282. ΓòÉΓòÉΓòÉ 9.6.1.4.2. <$OrdList> - Numbered List ΓòÉΓòÉΓòÉ
  13283.  
  13284. <$OrdList> - Numbered List 
  13285.  
  13286. This "OL_DOC.DH" tag is used to define the start of an ordered list. The list 
  13287. ends when the "<$eOrdList>" tag is encountered. Lists can be nested. 
  13288.  
  13289. Each list item begins with "<$li>". List items are separated by a blank line, 
  13290. if this is not desired then use the "<$OrdListCompact>" tags instead. 
  13291.  
  13292. SYNTAX 
  13293.  
  13294.     <$OrdList>
  13295.        <$li>Item1
  13296.        <$li>Item2
  13297.     <$eOrdList>
  13298.  
  13299. For an example have a look at the Lists documentation. 
  13300.  
  13301.  
  13302. ΓòÉΓòÉΓòÉ 9.6.1.4.3. <$OrdListCompact> - Numbered List ΓòÉΓòÉΓòÉ
  13303.  
  13304. <$OrdListCompact> - Numbered List 
  13305.  
  13306. This "OL_DOC.DH" tag is used to define the start of an ordered list. The list 
  13307. ends when the "<$eOrdListCompact>" tag is encountered. Lists can be nested. 
  13308.  
  13309. Each list item begins with <$li>. List items are not separated by a blank line, 
  13310. if you want one then use the "<$OrdList>" tags instead. 
  13311.  
  13312. SYNTAX 
  13313.  
  13314.     <$OrdListCompact>
  13315.        <$li>Item1
  13316.        <$li>Item2
  13317.     <$eOrdListCompact>
  13318.  
  13319. For an example have a look at the Lists documentation. 
  13320.  
  13321.  
  13322. ΓòÉΓòÉΓòÉ 9.6.1.4.4. <$SimpleList> - Numbered List ΓòÉΓòÉΓòÉ
  13323.  
  13324. <$SimpleList> - Numbered List 
  13325.  
  13326. This "OL_DOC.DH" tag is used to define the start of an ordered list. The list 
  13327. ends when the "<$eSimpleList>" tag is encountered. Lists can be nested. 
  13328.  
  13329. Each list item begins with "<$li>". List items are separated by a blank line, 
  13330. if this is not desired then use the "<$SimpleListCompact>" tags instead. 
  13331.  
  13332. SYNTAX 
  13333.  
  13334.     <$SimpleList>
  13335.        <$li>Item1
  13336.        <$li>Item2
  13337.     <$eSimpleList>
  13338.  
  13339. For an example have a look at the Lists documentation. 
  13340.  
  13341.  
  13342. ΓòÉΓòÉΓòÉ 9.6.1.4.5. <$SimpleListCompact> - Numbered List ΓòÉΓòÉΓòÉ
  13343.  
  13344. <$SimpleListCompact> - Numbered List 
  13345.  
  13346. This "OL_DOC.DH" tag is used to define the start of an ordered list. The list 
  13347. ends when the "<$eSimpleListCompact>" tag is encountered. Lists can be nested. 
  13348.  
  13349. Each list item begins with <$li>. List items are not separated by a blank line, 
  13350. if you want one then use the "<$SimpleList>" tags instead. 
  13351.  
  13352. SYNTAX 
  13353.  
  13354.     <$SimpleListCompact>
  13355.        <$li>Item1
  13356.        <$li>Item2
  13357.     <$eSimpleListCompact>
  13358.  
  13359. For an example have a look at the Lists documentation. 
  13360.  
  13361.  
  13362. ΓòÉΓòÉΓòÉ 9.6.1.4.6. <$UnNumberedList> - Dotted List ΓòÉΓòÉΓòÉ
  13363.  
  13364. <$UnNumberedList> - Dotted List 
  13365.  
  13366. This "OL_DOC.DH" tag is used to define the start of an ordered list. The list 
  13367. ends when the "<$eUnNumberedList>" tag is encountered. Lists can be nested. 
  13368.  
  13369. Each list item begins with <$li>. List items are separated by a blank line, if 
  13370. this is not desired then use the "<$UnNumberedListCompact>" tags instead. 
  13371.  
  13372. SYNTAX 
  13373.  
  13374.     <$UnNumberedList>
  13375.        <$li>Item1
  13376.        <$li>Item2
  13377.     <$eUnNumberedList>
  13378.  
  13379. For an example have a look at the Lists documentation. 
  13380.  
  13381.  
  13382. ΓòÉΓòÉΓòÉ 9.6.1.4.7. <$UnNumberedListCompact> - Dotted List ΓòÉΓòÉΓòÉ
  13383.  
  13384. <$UnNumberedListCompact> - Dotted List 
  13385.  
  13386. This "OL_DOC.DH" tag is used to define the start of an ordered list. The list 
  13387. ends when the "<$eUnNumberedListCompact>" tag is encountered. Lists can be 
  13388. nested. 
  13389.  
  13390. Each list item begins with <$li>. List items are not separated by a blank line, 
  13391. if you want one then use the "<$UnNumberedList>" tags instead. 
  13392.  
  13393. SYNTAX 
  13394.  
  13395.     <$UnNumberedListCompact>
  13396.        <$li>Item1
  13397.        <$li>Item2
  13398.     <$eUnNumberedListCompact>
  13399.  
  13400. For an example have a look at the Lists documentation. 
  13401.  
  13402.  
  13403. ΓòÉΓòÉΓòÉ 9.6.1.5. Include Examples ΓòÉΓòÉΓòÉ
  13404.  
  13405. Include Examples 
  13406.  
  13407. The following tags are used to include examples: 
  13408.  
  13409.          <$ExampleFile> 
  13410.          <$Example> 
  13411.          <$ExampleFormatted> 
  13412.  
  13413.  OPTIONS 
  13414.  
  13415.  Here are some of the options that you can use to modify the look and feel of 
  13416.  examples: 
  13417.  
  13418.          PRE_COLOR_HTML 
  13419.          PRE_COLOR_IPF 
  13420.          PRE_STYLE_OTHER_HTML 
  13421.  
  13422.  EXAMPLE - Source 
  13423.  
  13424.  This shows some example text being included from a file (only part of the file 
  13425.  is used): 
  13426.  
  13427.       <$ExampleFile INDENT=0 FILE="OlDocXmp.DH" FRAGMENT="[CharacterFormatting]" STATE="REMEMBER">
  13428.       <$ExampleFile INDENT=8 FILE="OlDocXmp.DH" FRAGMENT="[CharacterFormatting]">
  13429.  
  13430.  EXAMPLE - Generated Output 
  13431.  
  13432.   <$p>This paragraph contains <$Bold Text="some bold"> text!
  13433.  
  13434.   <$p><$DarkGreen Text=^This is a                               \
  13435.                         multi line (in source code at least)    \
  13436.                         paragraph which is completely green.   -\
  13437.                        ^>
  13438.  
  13439.  Notice the hypertext links that were placed into the displayed source code in 
  13440.  the above example code does not show the preparation required. This is 
  13441.  demonstrated in the <$ExampleFile> example. 
  13442.  
  13443.  Also note that unsafe (in example) characters such as "<" and others are 
  13444.  tagged in such a way that they will correctly display. 
  13445.  
  13446.  The second lot of output is below, notice no hypertext links and the greater 
  13447.  indenting (I could have changed font and color as well if I'd wished): 
  13448.  
  13449.           <$p>This paragraph contains <$Bold Text="some bold"> text!
  13450.  
  13451.           <$p><$DarkGreen Text=^This is a                               \
  13452.                                 multi line (in source code at least)    \
  13453.                                 paragraph which is completely green.   -\
  13454.                                ^>
  13455.  
  13456.  
  13457. ΓòÉΓòÉΓòÉ 9.6.1.5.1. <$ExampleFile> ΓòÉΓòÉΓòÉ
  13458.  
  13459. <$ExampleFile> 
  13460.  
  13461. This "OL_DOC.DH" tag allows you to include all or part of a file in such a 
  13462. manner that it appears to be viewer (IPF or HTML) much like you'd see it in a 
  13463. text editor.  The point of this tag is to be able to include example code as is 
  13464. without any modifications being manually applied. 
  13465.  
  13466. SYNTAX 
  13467.  
  13468.     <$ExampleFile  FILE="?"  [STATE="?"]>  [INDENT="?"]>  [FRAGMENT="?"]>  [ASIS="?"]>
  13469.  
  13470. The parameters for this tag are: 
  13471.  
  13472.          FILE 
  13473.           This is the name of the text file that includes the example. This can 
  13474.           be unmodified code. 
  13475.  
  13476.          FRAGMENT 
  13477.           If you don't want to include the whole file then you must mark the 
  13478.           start and end lines with a unique string. Only the part between these 
  13479.           lines will be included. This allows you to set up a larger file 
  13480.           containing all your examples in one place if that is your wish. 
  13481.  
  13482.          INDENT 
  13483.           Normally everything is indented a small amount. You may wish to 
  13484.           remove the indent or even make it bigger. The value you supply is the 
  13485.           number of leading spaces you require. 
  13486.  
  13487.          SPELL 
  13488.           Normally spell checking is not allowed to occur in examples. You can 
  13489.           specify "ON" if you wish to allow it or "OFF" if not. Note that this 
  13490.           does not turn on spell checking it just indicates if spell checking 
  13491.           is allowed. 
  13492.  
  13493.          ASIS 
  13494.           All "normal" characters are already taken care of such that they will 
  13495.           correctly display in a browser, for example when generating html "<" 
  13496.           is converted to "<". If you find other characters you'd also like 
  13497.           automatically taken care of you can define these (international 
  13498.           characters might need more work). Have a look at the #AsIs command, 
  13499.           it shows you how to set up the modifications.  This parameter can 
  13500.           take one or more space separated previously setup ASIS state names. 
  13501.  
  13502.          STATE 
  13503.           The contents of this parameter are used in a "#AutoTagState +" 
  13504.           command. If you don't want the automatic tagging you previously set 
  13505.           up to occur then don't pass this parameter. You would normally pass 
  13506.           "REMEMBER" to have them occur. 
  13507.  
  13508.  EXAMPLE - Source 
  13509.  
  13510.  This example shows some HTML source code. 
  13511.  
  13512.   ;--- Create a new clear state, set up new ASIS state, restore state ---
  13513.   #AutoTagState +
  13514.      ;--- Set up aliases for all dangerous character so that they display OK in browser ---
  13515.      #if ['<$DocType>' = 'HTML']
  13516.          ;--- HTML being generated ---
  13517.          #RexxVar  "UMLAUT"   =x= "ü"  ;;Map an alias (for our use) to the output text
  13518.      #elseif
  13519.          ;--- IPF being generated ---
  13520.          #RexxVar  "UMLAUT"   =x= "╨¬"       ;;This char OK as is in IPF
  13521.      #endif
  13522.  
  13523.      ;--- We defined aliases above only so that we more easily refer to strings, for example an umlaut looks the same in IPF and HTML until alias replaced ---
  13524.      #AutoTag   "╨¬"      "<?xUMLAUT>"       ;;Now map char to our alias
  13525.  
  13526.      ;--- Create named ASIS state called "DANGEROUS" ---
  13527.      #AsIs      SETUP   DANGEROUS
  13528.   #AutoTagState -
  13529.  
  13530.   ;--- Now lets also set up some automatic tagging, adding to existing tagging (only applies to this example otherwise we'd not do it here) ---
  13531.   #AutoTagState + Remember           ;;Adding to existing tags (remember current)
  13532.   #AutoTag       ^Gr<?xUMLAUT>n^     ^<$DarkGreen Text='Gr<?xUMLAUT>n'>^  ;;Because we used aliases we don't need to check if html/ipf etc to do this step
  13533.  
  13534.   ;--- Load the example (a part of the file - fragment) ---
  13535.   <$ExampleFile STATE="REMEMBER" FILE="OLDOCXMP.DH" FRAGMENT="[ExampleFileTag2]" AsIs=^DANGEROUS^>
  13536.  
  13537.   ;--- Already processed example, remove now obsolete tagging ---
  13538.   #AutoTagState -
  13539.  
  13540.  The "ASIS" stuff as well as any common "AUTOTAG" steps would normally only 
  13541.  occur once at the start of your document. Note that the tagging that you see 
  13542.  above and below to create hypertext links is such common code in my document. 
  13543.  
  13544.  EXAMPLE - Generated Output 
  13545.  
  13546.       ;--- Some web addresses -----------------------------------------------------
  13547.       #define HttpMagazineOs2Ezine         http://www.os2ezine.com
  13548.       #define HttpOs2SuperSiteMainPage     http://www.os2ss.com
  13549.  
  13550.       ;--- Set up some common styles ----------------------------------------------
  13551.       #define Red               <FONT COLOR=RED>{$Text}</FONT>
  13552.       #define Gr╨¬n              <FONT COLOR=GREEN>{$Text}</FONT> ;;Note international characters can be used in names
  13553.       #define Bold              <B>{$Text}</B>
  13554.       #define Quote             “{$Text}”              ;;Pretty double quotes
  13555.  
  13556.       ;--- Now for some html stuff ------------------------------------------------
  13557.       <P>Some <$Gr╨¬n Text="green text"> blah blah...
  13558.  
  13559.  Notice the green text above is what we asked for, all other tagging (hypertext 
  13560.  links) occurred because its set up that way at the start of this document. 
  13561.  Hopefully you can recognise the power of this facility just from the fact that 
  13562.  I can show you the above source and generated output! 
  13563.  
  13564.  
  13565. ΓòÉΓòÉΓòÉ 9.6.1.5.2. <$Example> ΓòÉΓòÉΓòÉ
  13566.  
  13567. <$Example> 
  13568.  
  13569. This "OL_DOC.DH" tag allows you to specify the start of an inline example. For 
  13570. large examples it is recommended that the <$ExampleFile> tag be used instead. 
  13571. The example continues until "<$eExample>" is found. 
  13572.  
  13573. SYNTAX 
  13574.  
  13575.     <$Example [STATE="?"]>  [INDENT="?"]> [ASIS="?"]>
  13576.        ...
  13577.        ...
  13578.     <$eExample>
  13579.  
  13580. The parameters for this tag are: 
  13581.  
  13582.          STATE 
  13583.           The contents of this parameter are used in a "#AutoTagState +" 
  13584.           command. If you don't want the automatic tagging you previously set 
  13585.           up to occur then don't pass this parameter. You would normally pass 
  13586.           "REMEMBER" to have them occur. 
  13587.  
  13588.          INDENT 
  13589.           Normally everything is indented a small amount. You may wish to 
  13590.           remove the indent or even make it bigger. The value you supply is the 
  13591.           number of leading spaces you require. 
  13592.  
  13593.          ASIS 
  13594.           All "normal" characters are already taken care of such that they will 
  13595.           correctly display in a browser, for example when generating html "<" 
  13596.           is converted to "<". If you find other characters you'd also like 
  13597.           automatically taken care of you can define these (international 
  13598.           characters might need more work). Have a look at the #AsIs command, 
  13599.           it shows you how to set up the modifications.  This parameter can 
  13600.           take one or more space separated previously setup ASIS state names. 
  13601.  
  13602.          SPELL 
  13603.           Normally spell checking is not allowed to occur in examples. You can 
  13604.           specify "ON" if you wish to allow it or "OFF" if not. Note that this 
  13605.           does not turn on spell checking it just indicates if spell checking 
  13606.           is allowed. 
  13607.  
  13608.  EXAMPLE 
  13609.  
  13610.  This is a very simple example, you should have a look at the <$ExampleFile> 
  13611.  example for some advanced techniques. 
  13612.  
  13613.       <$Example STATE="REMEMBER">
  13614.       <P>Some <B>sample html</B>.
  13615.       <$eExample>
  13616.  
  13617.  
  13618. ΓòÉΓòÉΓòÉ 9.6.1.5.3. <$ExampleFormatted> ΓòÉΓòÉΓòÉ
  13619.  
  13620. <$ExampleFormatted> 
  13621.  
  13622. This "OL_DOC.DH" tag allows you to specify the start of an inline example. 
  13623. Unlike the <$Example> tag, you have to handle all formatting manually, for this 
  13624. reason it is a rarely used tag. The example continues until 
  13625. "<$eExampleFormatted>" is found.  This tag mainly sets up the look and feel of 
  13626. the example, everything else is up to you. 
  13627.  
  13628. SYNTAX 
  13629.  
  13630.     <$ExampleFormatted>
  13631.        ...
  13632.        ...
  13633.     <$eExampleFormatted>
  13634.  
  13635. As you can see there are no parameters for this type of example. 
  13636.  
  13637. EXAMPLE 
  13638.  
  13639.     <$ExampleFormatted STATE="REMEMBER">
  13640.     <P>Some <B>sample html</B>.
  13641.     <$eExampleFormatted>
  13642.  
  13643. Note that the above tagging is only valid for viewing in a html viewer, the 
  13644. tagging is not valid for IPF. For this reason the following (making use of 
  13645. standard definitions) would be better: 
  13646.  
  13647.     <$ExampleFormatted STATE="REMEMBER">
  13648.     <?xLT>P<?xGT>Some <?xLT>B<?xGT>sample html<?xLT>/B<?xGT>.
  13649.     <$eExampleFormatted>
  13650.  
  13651.  
  13652. ΓòÉΓòÉΓòÉ 9.6.1.6. Special Characters ΓòÉΓòÉΓòÉ
  13653.  
  13654. Special Characters 
  13655.  
  13656. The following tags are used to handle some problem characters: 
  13657.  
  13658.          <$Colon> 
  13659.          <$Amp> 
  13660.          <$NoBreakingBlank> 
  13661.  
  13662.  
  13663. ΓòÉΓòÉΓòÉ 9.6.1.6.1. <$Amp> ΓòÉΓòÉΓòÉ
  13664.  
  13665. <$Amp> 
  13666.  
  13667. This "OL_DOC.DH" tag is used to wherever you want a '&' character. This 
  13668. character is unsafe in IPF documents. 
  13669.  
  13670. EXAMPLE 
  13671.  
  13672.     <$p>The parameters 1 <$Amp> 2 are
  13673.  
  13674.  
  13675. ΓòÉΓòÉΓòÉ 9.6.1.6.2. <$Colon> ΓòÉΓòÉΓòÉ
  13676.  
  13677. <$Colon> 
  13678.  
  13679. This "OL_DOC.DH" tag is used to wherever you want a ':' character. This 
  13680. character is unsafe in IPF documents. 
  13681.  
  13682. EXAMPLE 
  13683.  
  13684.     <$p>The parameters are<$Colon>
  13685.  
  13686.  
  13687. ΓòÉΓòÉΓòÉ 9.6.1.6.3. <$NoBreakingBlank> ΓòÉΓòÉΓòÉ
  13688.  
  13689. <$NoBreakingBlank> 
  13690.  
  13691. This "OL_DOC.DH" tag is used to wherever you want a space between words however 
  13692. you need both words to be on the same line. 
  13693.  
  13694.  
  13695. ΓòÉΓòÉΓòÉ 9.6.1.7. Generate An Index ΓòÉΓòÉΓòÉ
  13696.  
  13697. Generate An Index 
  13698.  
  13699. The following tags are used to generate an index for your document: 
  13700.  
  13701.          <$Index1> 
  13702.          <$Index2> 
  13703.  
  13704.  
  13705. ΓòÉΓòÉΓòÉ 9.6.1.7.1. <$Index1> ΓòÉΓòÉΓòÉ
  13706.  
  13707. <$Index1> 
  13708.  
  13709. This "OL_DOC.DH" tag allows you to define top level item for the index. 
  13710.  
  13711. This tag is currently ignored unless generating IPF code. 
  13712.  
  13713. SYNTAX 
  13714.  
  13715.     <$Index1  [TEXT="?"]>>
  13716.  
  13717. The parameters for this tag are: 
  13718.  
  13719.          TEXT 
  13720.           This is the text of the index item. If you don't supply this 
  13721.           parameter the text supplied on the previous Heading tag is used. 
  13722.  
  13723.  EXAMPLE 
  13724.  
  13725.       <$Heading Text="Introduction">
  13726.       <$Index1>
  13727.  
  13728.  
  13729. ΓòÉΓòÉΓòÉ 9.6.1.7.2. <$Index2> ΓòÉΓòÉΓòÉ
  13730.  
  13731. <$Index2> 
  13732.  
  13733. This "OL_DOC.DH" tag allows you to define second level item for the index. 
  13734.  
  13735. This tag is currently ignored unless generating IPF code. 
  13736.  
  13737. SYNTAX 
  13738.  
  13739.     <$Index2  [TEXT="?"]>>
  13740.  
  13741. The parameters for this tag are: 
  13742.  
  13743.          TEXT 
  13744.           This is the text of the index item. If you don't supply this 
  13745.           parameter the text supplied on the previous Heading tag is used. 
  13746.  
  13747.  EXAMPLE 
  13748.  
  13749.       <$Heading Text="FAQ">
  13750.       <$Index2>
  13751.  
  13752.  
  13753. ΓòÉΓòÉΓòÉ 9.6.1.8. Other Tags ΓòÉΓòÉΓòÉ
  13754.  
  13755. Other Tags 
  13756.  
  13757. The following tags do not fit into any of the above categories: 
  13758.  
  13759.          <$DocumentStart> 
  13760.          <$DocumentEnd> 
  13761.          <$Title> 
  13762.  
  13763.  
  13764. ΓòÉΓòÉΓòÉ 9.6.1.8.1. <$DocumentStart> ΓòÉΓòÉΓòÉ
  13765.  
  13766. <$DocumentStart> 
  13767.  
  13768. This "OL_DOC.DH" tag defines the start of your document, no other output or 
  13769. tags should be used prior to this tag. 
  13770.  
  13771. SYNTAX 
  13772.  
  13773.     <$DocumentStart  [TEXT="?"]>>
  13774.  
  13775. The parameters for this tag are: 
  13776.  
  13777.          TEXT 
  13778.           This is the text of the document's title. 
  13779.  
  13780.  EXAMPLE 
  13781.  
  13782.       <$DocumentStart Text="The PPWIZARD.CMD PREPROCESSOR - <?Version>">
  13783.  
  13784.  
  13785. ΓòÉΓòÉΓòÉ 9.6.1.8.2. <$DocumentEnd> ΓòÉΓòÉΓòÉ
  13786.  
  13787. <$DocumentEnd> 
  13788.  
  13789. This "OL_DOC.DH" tag defines the end of your document, no other output or tags 
  13790. should be used after this tag. 
  13791.  
  13792. SYNTAX 
  13793.  
  13794.     <$DocumentEnd>
  13795.  
  13796. There are no parameters for this tag. 
  13797.  
  13798.  
  13799. ΓòÉΓòÉΓòÉ 9.6.1.8.3. <$Title> ΓòÉΓòÉΓòÉ
  13800.  
  13801. <$Title> 
  13802.  
  13803. This "OL_DOC.DH" tag allows you to define a title for a section within a page. 
  13804. It is useful as it enforces a common look and feel. 
  13805.  
  13806. SYNTAX 
  13807.  
  13808.     <$Title  [TEXT="?"]>>
  13809.  
  13810. The parameters for this tag are: 
  13811.  
  13812.          TEXT 
  13813.           This is the text of the title. If you don't supply this parameter the 
  13814.           text supplied on the previous Heading tag is used. 
  13815.  
  13816.  EXAMPLE 
  13817.  
  13818.       <$Title Text="EXAMPLE">
  13819.  
  13820.  
  13821. ΓòÉΓòÉΓòÉ 9.6.2. Options - "OL_DOC.DH" ΓòÉΓòÉΓòÉ
  13822.  
  13823. Options - "OL_DOC.DH" 
  13824.  
  13825. As with all my header files the intention is to build them in such a way that 
  13826. you never need to modify the header code to get the look and feel that you 
  13827. require. 
  13828.  
  13829. Most of the options get set before the header file gets included. If you would 
  13830. like other things to be user configurable please provide feedback to this 
  13831. effect. 
  13832.  
  13833. There are many options that you can choose which modify the way that tags from 
  13834. OL_DOC.DH function, they are: 
  13835.  
  13836.          DOCTYPE 
  13837.          OL_DOC_HEADINGS_DONT_GENERATE_TITLE 
  13838.          OL_DOC_HTML_8_3_NAMES 
  13839.          OL_DOC_HTML_ALLOW_ROBOTS 
  13840.          OL_DOC_HTML_BODY 
  13841.          OL_DOC_HTML_BOTTOM 
  13842.          OL_DOC_HTML_CONTENTS 
  13843.          OL_DOC_HTML_CONTENTS_TITLE 
  13844.          OL_DOC_HTML_FOOTER 
  13845.          OL_DOC_HTML_GENERATE_SEARCH_ICON 
  13846.          OL_DOC_HTML_GENERATOR_TAGS 
  13847.          OL_DOC_HTML_HOME 
  13848.          OL_DOC_HTML_META_TAGS 
  13849.          OL_DOC_HTML_NEXT 
  13850.          OL_DOC_HTML_NOCONTENTS_HEADER 
  13851.          OL_DOC_HTML_PREV 
  13852.          OL_DOC_HTML_SEARCH 
  13853.          OL_DOC_HTML_TOP 
  13854.          PRE_COLOR_HTML 
  13855.          PRE_COLOR_IPF 
  13856.          PRE_STYLE_OTHER_HTML 
  13857.  
  13858.  
  13859. ΓòÉΓòÉΓòÉ 9.6.2.1. DocType ΓòÉΓòÉΓòÉ
  13860.  
  13861. DocType 
  13862.  
  13863. This is a definition which must be set. It indicates the type of output that 
  13864. you required. 
  13865.  
  13866. It may support more types in future (so you should code accordingly as much as 
  13867. possible), currently support are: 
  13868.  
  13869.          HTML 
  13870.          IPF 
  13871.  
  13872.  Note that this definition would not normally be used in the source code as 
  13873.  this would require you to modify the source to change the output type! You 
  13874.  could normally use the "/Define" switch to define the mode. 
  13875.  
  13876.  EXAMPLE 
  13877.  
  13878.  I recommend as much as possible that you keep your source clear of conditional 
  13879.  generation code, a much better way is to keep all conditional stuff in one 
  13880.  place and create some macros to hide the differences such as demonstrated here 
  13881.  (you may wish to create your own header file which loads "OL_DOC.DH" and sets 
  13882.  up the rest of your environment): 
  13883.  
  13884.       ;--- Lets create some macros ourselves --------------------------------------
  13885.       #define RedBold  <$Red Text=<$Bold Text=Γûê{$Text}Γûê>>   ;;Uses preexisting macros only
  13886.       #if    ['<$DocType>' = 'HTML']
  13887.              ;--- HTML ------------------------------------------------------------
  13888.              #define MyGreen  <FONT COLOR=GREEN>{$Text}</FONT>
  13889.       #elseif
  13890.              ;--- IPF -------------------------------------------------------------
  13891.              #define MyGreen  :color fc=darkgreen.{$Text}:color fc=default.
  13892.       #endif
  13893.  
  13894.  EXAMPLE 
  13895.  
  13896.  Here I wish to ensure that my code can handle the document type, "OL_DOC.DH" 
  13897.  does its own validation however it may have recently introduced a new type 
  13898.  that I may need to do something about if I wish to use it. I will not try to 
  13899.  (for now) generate anything but HTML or IPF, so lets validate this: 
  13900.  
  13901.       ;--- As I user I only support HTML & IPF ---
  13902.       #if  '<$DocType>' <> 'HTML' & '<$DocType>' <> 'IPF'
  13903.            #error  'I do not support the document type "<$DocType>"!'
  13904.       #endif
  13905.  
  13906.  
  13907. ΓòÉΓòÉΓòÉ 9.6.2.2. OL_DOC_HEADINGS_DONT_GENERATE_TITLE ΓòÉΓòÉΓòÉ
  13908.  
  13909. OL_DOC_HEADINGS_DONT_GENERATE_TITLE 
  13910.  
  13911. This is an option which modifies the tags of OL_DOC.DH operate (look and feel). 
  13912.  
  13913. By default all headings (defined with "<$Heading>") generate a title at the 
  13914. start of each page (using "<$Title>"). Simply define this option (any value) to 
  13915. prevent this from occuring. You would do this if either you don't want any 
  13916. title or you sometimes want the title to differ from the heading. 
  13917.  
  13918. EXAMPLE 
  13919.  
  13920.     #define    OL_DOC_HEADINGS_DONT_GENERATE_TITLE  ;;All my sections already have a title specified
  13921.     #include  "OL_DOC.DH"
  13922.  
  13923.  
  13924. ΓòÉΓòÉΓòÉ 9.6.2.3. OL_DOC_HTML_8_3_NAMES ΓòÉΓòÉΓòÉ
  13925.  
  13926. OL_DOC_HTML_8_3_NAMES 
  13927.  
  13928. This is an option which modifies the tags of OL_DOC.DH operate (look and feel). 
  13929.  
  13930. By default long html filenames are generated for each html page. You simply 
  13931. define this option (any value) to force "8.3" style filenames to be generated. 
  13932.  
  13933. "8.3" style names would allow them to be browsed under Windows 3.1 and other 
  13934. operating systems without long filename support. 
  13935.  
  13936. EXAMPLE 
  13937.  
  13938. This example shows how to force 8.3 filename generation: 
  13939.  
  13940.     #define   OL_DOC_HTML_8_3_NAMES
  13941.     #include  "OL_DOC.DH"
  13942.  
  13943.  
  13944. ΓòÉΓòÉΓòÉ 9.6.2.4. OL_DOC_HTML_ALLOW_ROBOTS ΓòÉΓòÉΓòÉ
  13945.  
  13946. OL_DOC_HTML_ALLOW_ROBOTS 
  13947.  
  13948. This is an option which modifies the tags of OL_DOC.DH operate (look and feel). 
  13949.  
  13950. By default meta tags are placed into the generated HTML to inform robots (such 
  13951. as search engines) not to index the pages. If you do want your pages indexed 
  13952. then simply define this option (any value). 
  13953.  
  13954. EXAMPLE 
  13955.  
  13956. This example shows how to force 8.3 filename generation: 
  13957.  
  13958.     #define    OL_DOC_HTML_ALLOW_ROBOTS
  13959.     #include  "OL_DOC.DH"
  13960.  
  13961.  
  13962. ΓòÉΓòÉΓòÉ 9.6.2.5. OL_DOC_HTML_BODY ΓòÉΓòÉΓòÉ
  13963.  
  13964. OL_DOC_HTML_BODY 
  13965.  
  13966. This is an option which modifies the tags of OL_DOC.DH operate (look and feel). 
  13967.  
  13968. By default the body tag of generated html does not have any parameters, you 
  13969. probably wish to alter the background (and link) colors and maybe have a 
  13970. graphic background. 
  13971.  
  13972. To modify the body tag simply provide a full replacement. 
  13973.  
  13974. EXAMPLE 
  13975.  
  13976. This example shows how to specify a white background: 
  13977.  
  13978.     #define    OL_DOC_HTML_BODY  <BODY BGCOLOR="#FFFFFF">
  13979.     #include  "OL_DOC.DH"
  13980.  
  13981.  
  13982. ΓòÉΓòÉΓòÉ 9.6.2.6. OL_DOC_HTML_BOTTOM ΓòÉΓòÉΓòÉ
  13983.  
  13984. OL_DOC_HTML_BOTTOM 
  13985.  
  13986. This is an option which modifies the tags of OL_DOC.DH operate (look and feel). 
  13987.  
  13988. This tag allows you to either remove the button that links you to the bottom of 
  13989. the current page or completely change its look and feel. 
  13990.  
  13991. EXAMPLE 
  13992.  
  13993.     #define    OL_DOC_HTML_BOTTOM <A HREF="#BOTTOM"><IMG SRC="MyBottom.gif" BORDER=0 WIDTH=30 HEIGHT=30 ALT="[Bottom]"></A>
  13994.     #include  "OL_DOC.DH"
  13995.  
  13996.  
  13997. ΓòÉΓòÉΓòÉ 9.6.2.7. OL_DOC_HTML_CONTENTS ΓòÉΓòÉΓòÉ
  13998.  
  13999. OL_DOC_HTML_CONTENTS 
  14000.  
  14001. This is an option which modifies the tags of OL_DOC.DH operate (look and feel). 
  14002.  
  14003. This tag allows you to either remove the button that links you to the contents 
  14004. page or completely change its look and feel. 
  14005.  
  14006. EXAMPLE 
  14007.  
  14008.     #define    OL_DOC_HTML_CONTENTS <A HREF="<??ContentsId>.<??HtmlExtn>"><IMG SRC="MyContents.gif" BORDER=0 WIDTH=63 HEIGHT=37 ALT="[Contents]"></A>
  14009.     #include  "OL_DOC.DH"
  14010.  
  14011.  
  14012. ΓòÉΓòÉΓòÉ 9.6.2.8. OL_DOC_HTML_CONTENTS_TITLE ΓòÉΓòÉΓòÉ
  14013.  
  14014. OL_DOC_HTML_CONTENTS_TITLE 
  14015.  
  14016. This is an option which modifies the tags of OL_DOC.DH operate (look and feel). 
  14017.  
  14018. By default the contents page of the generated html simply says "Contents". This 
  14019. option allows you to supply alternative text. 
  14020.  
  14021. EXAMPLE 
  14022.  
  14023.     #define    OL_DOC_HTML_CONTENTS_TITLE   PPWIZARD CONTENTS
  14024.     #include  "OL_DOC.DH"
  14025.  
  14026.  
  14027. ΓòÉΓòÉΓòÉ 9.6.2.9. OL_DOC_HTML_FOOTER ΓòÉΓòÉΓòÉ
  14028.  
  14029. OL_DOC_HTML_FOOTER 
  14030.  
  14031. This is an option which modifies the tags of OL_DOC.DH operate (look and feel). 
  14032.  
  14033. By default the generated html does not have a footer, you may wish to have one. 
  14034. The macro you define (if you want a footer) can define the parameter "CONTENTS" 
  14035. which has a value of 'Y' if the footer is for the contents page. 
  14036.  
  14037. EXAMPLE 
  14038.  
  14039.     ;--- Define Footer for PPWIZARD manual --------------------------------------
  14040.     #evaluate DateTime               @date('WeekDay') || ' ' || date('Month') || ' ' || substr(date('Sorted'), 7, 2) || ' ' || left(date('Sorted'), 4) || ' at ' || time('Civil')@
  14041.     #define   MadeWithPpwALT         My whole website and this manual itself was developed using PPWIZARD (free preprocessor written by Dennis Bareis)
  14042.     #define OL_DOC_HTML_NOCONTENTS_HEADER             \
  14043.             PPWIZARD Manual<BR>
  14044.     #define OL_DOC_HTML_FOOTER                        \
  14045.             #if ['{$CONTENTS}' = 'N']                -\
  14046.                 <BR>                                 -\
  14047.             #elseif                                  -\
  14048.                 <HR>    ;;Need line under contents   -\
  14049.             #endif                                   -\
  14050.             <CENTER>                                 -\
  14051.             PPWIZARD Manual                          -\
  14052.             <BR>                                     -\
  14053.             <A HREF="../ppwizard.htm">               -\
  14054.             <IMG SRC="../graphics/madewppw.jpg" VSPACE=5 ALIGN=middle WIDTH=120 HEIGHT=35 BORDER=0 ALT="<$MadeWithPpwALT>"> -\
  14055.             </A>                                     -\
  14056.             <BR>                                     -\
  14057.             <$DateTime>                              -\
  14058.             </CENTER>
  14059.  
  14060.     ;--- Include Header ---
  14061.     #include  "OL_DOC.DH"
  14062.  
  14063. You might notice that I used the ExampleFile tag to include the real live 
  14064. working copy of the footer from my documentation source. This means that the 
  14065. footer on the bottom of this page exactly matches the code shown above (the 
  14066. sample is not a copy, its the master). 
  14067.  
  14068.  
  14069. ΓòÉΓòÉΓòÉ 9.6.2.10. OL_DOC_HTML_GENERATE_SEARCH_ICON ΓòÉΓòÉΓòÉ
  14070.  
  14071. OL_DOC_HTML_GENERATE_SEARCH_ICON 
  14072.  
  14073. This is an option which modifies the tags of OL_DOC.DH operate (look and feel). 
  14074.  
  14075. This option allows you to generate a search icon, this is an inbuilt icon which 
  14076. you may want to generate if you also use the OL_DOC_HTML_SEARCH option. 
  14077.  
  14078. EXAMPLE 
  14079.  
  14080.     #define    OL_DOC_HTML_GENERATE_SEARCH_ICON
  14081.     #define    OL_DOC_HTML_SEARCH  <A HREF="ppwsrch.htm"><IMG SRC="search.gif" BORDER=0 WIDTH=59 HEIGHT=40 ALT="[Search]"></A>
  14082.     #include  "OL_DOC.DH"
  14083.  
  14084.  
  14085. ΓòÉΓòÉΓòÉ 9.6.2.11. OL_DOC_HTML_GENERATOR_TAGS ΓòÉΓòÉΓòÉ
  14086.  
  14087. OL_DOC_HTML_GENERATOR_TAGS 
  14088.  
  14089. This is an option which modifies the tags of OL_DOC.DH operate (look and feel). 
  14090.  
  14091. This option allows you to either completely remove the generation of the 
  14092. "GENERATOR" meta tag or allow you to replace the existing one with an 
  14093. alternative one of your choice. 
  14094.  
  14095. EXAMPLE - No Generator Tag Wanted 
  14096.  
  14097.     #define    OL_DOC_HTML_GENERATOR_TAGS
  14098.     #include  "OL_DOC.DH"
  14099.  
  14100. EXAMPLE - Change Tag 
  14101.  
  14102.     #define    OL_DOC_HTML_GENERATOR_TAGS <META NAME="GENERATOR" CONTENT="PPWIZARD v<?Version> using 'OL_DOC.DH' v<$VERSION_OL_DOC_OH>"><?NewLine>
  14103.     #include  "OL_DOC.DH"
  14104.  
  14105.  
  14106. ΓòÉΓòÉΓòÉ 9.6.2.12. OL_DOC_HTML_HOME ΓòÉΓòÉΓòÉ
  14107.  
  14108. OL_DOC_HTML_HOME 
  14109.  
  14110. This is an option which modifies the tags of OL_DOC.DH operate (look and feel). 
  14111.  
  14112. This tag allows you to specify a button which takes you to a "homepage", by 
  14113. default there is no home button. 
  14114.  
  14115.  
  14116. ΓòÉΓòÉΓòÉ 9.6.2.13. OL_DOC_HTML_META_TAGS ΓòÉΓòÉΓòÉ
  14117.  
  14118. OL_DOC_HTML_META_TAGS 
  14119.  
  14120. This is an option which modifies the tags of OL_DOC.DH operate (look and feel). 
  14121.  
  14122. By default no other meta tags other than the "OL_DOC_HTML_GENERATOR_TAGS" tag 
  14123. are generated. If you wish to add some then use this definition. 
  14124.  
  14125. EXAMPLE 
  14126.  
  14127.     #define    OL_DOC_HTML_META_TAGS <META NAME="AUTHOR" CONTENT="Fred Nerk"><?NewLine>
  14128.     #include  "OL_DOC.DH"
  14129.  
  14130.  
  14131. ΓòÉΓòÉΓòÉ 9.6.2.14. OL_DOC_HTML_NEXT ΓòÉΓòÉΓòÉ
  14132.  
  14133. OL_DOC_HTML_NEXT 
  14134.  
  14135. This is an option which modifies the tags of OL_DOC.DH operate (look and feel). 
  14136.  
  14137. This tag allows you to either remove (unlikely!) the button that links you to 
  14138. the next page or completely change its look and feel. 
  14139.  
  14140. EXAMPLE 
  14141.  
  14142.     #define    OL_DOC_HTML_NEXT  <A {$LinkGuts=^HREF="{$Page}.<??HtmlExtn>"^}><IMG SRC="MyNext.gif" BORDER=0 WIDTH=49 HEIGHT=31 ALT="[Next]"></A>
  14143.     #include  "OL_DOC.DH"
  14144.  
  14145.  
  14146. ΓòÉΓòÉΓòÉ 9.6.2.15. OL_DOC_HTML_NOCONTENTS_HEADER ΓòÉΓòÉΓòÉ
  14147.  
  14148. OL_DOC_HTML_NOCONTENTS_HEADER 
  14149.  
  14150. This is an option which modifies the tags of OL_DOC.DH operate (look and feel). 
  14151.  
  14152. This option allows you to specify text or images etc to appear at the top of 
  14153. all pages except the contents page. Whatever you specify is placed immediately 
  14154. before the images on the top of the page. 
  14155.  
  14156. EXAMPLE 
  14157.  
  14158.     #define    OL_DOC_HTML_NOCONTENTS_HEADER  PPWIZARD Manual<BR>
  14159.     #include  "OL_DOC.DH"
  14160.  
  14161.  
  14162. ΓòÉΓòÉΓòÉ 9.6.2.16. OL_DOC_HTML_PREV ΓòÉΓòÉΓòÉ
  14163.  
  14164. OL_DOC_HTML_PREV 
  14165.  
  14166. This is an option which modifies the tags of OL_DOC.DH operate (look and feel). 
  14167.  
  14168. This tag allows you to either remove (unlikely!) the button that links you to 
  14169. the previous page or completely change its look and feel. 
  14170.  
  14171. EXAMPLE 
  14172.  
  14173.     #define    OL_DOC_HTML_PREV  <A HREF="{$Page}.<??HtmlExtn>"><IMG SRC="MyPrev.gif" BORDER=0 WIDTH=49 HEIGHT=31 ALT="[Prev]"></A>
  14174.     #include  "OL_DOC.DH"
  14175.  
  14176.  
  14177. ΓòÉΓòÉΓòÉ 9.6.2.17. OL_DOC_HTML_SEARCH ΓòÉΓòÉΓòÉ
  14178.  
  14179. OL_DOC_HTML_SEARCH 
  14180.  
  14181. This is an option which modifies the tags of OL_DOC.DH operate (look and feel). 
  14182.  
  14183. By default there is no search mechanism for the generated HTML, if you can 
  14184. provide one then this option allows you to set up the required icon and any 
  14185. required HTML. 
  14186.  
  14187. EXAMPLE 
  14188.  
  14189. I have a simple javascript search engine that I use to search my pages, I got 
  14190. it to generate "ppwsrch.htm", I wish to create a search button and link to the 
  14191. search page: 
  14192.  
  14193.     #define    OL_DOC_HTML_SEARCH  <A HREF="ppwsrch.htm"><IMG SRC="search.gif" BORDER=0 WIDTH=59 HEIGHT=40 ALT="[Search]"></A>
  14194.     #define    OL_DOC_HTML_GENERATE_SEARCH_ICON
  14195.     #include  "OL_DOC.DH"
  14196.  
  14197.  
  14198. ΓòÉΓòÉΓòÉ 9.6.2.18. OL_DOC_HTML_TOP ΓòÉΓòÉΓòÉ
  14199.  
  14200. OL_DOC_HTML_TOP 
  14201.  
  14202. This is an option which modifies the tags of OL_DOC.DH operate (look and feel). 
  14203.  
  14204. This tag allows you to either remove the button that links you to the top of 
  14205. the current page (from the bottom) or completely change its look and feel. 
  14206.  
  14207. EXAMPLE 
  14208.  
  14209.     #define    OL_DOC_HTML_TOP  <A HREF="#TOP"><IMG SRC="MyTop.gif" BORDER=0 WIDTH=30 HEIGHT=30 ALT="[Top]"></A>
  14210.     #include  "OL_DOC.DH"
  14211.  
  14212.  
  14213. ΓòÉΓòÉΓòÉ 9.6.2.19. PRE_COLOR_HTML ΓòÉΓòÉΓòÉ
  14214.  
  14215. PRE_COLOR_HTML 
  14216.  
  14217. This is an option which modifies the tags of OL_DOC.DH operate (look and feel). 
  14218.  
  14219. This option is used to alter the color of the output from the example tags when 
  14220. they generate HTML. You might also wish to modify the PRE_COLOR_IPF option. 
  14221.  
  14222. The color you specify will be ignored by any browser that does not have style 
  14223. sheet support. 
  14224.  
  14225. EXAMPLE 
  14226.  
  14227.     #define   PRE_COLOR_HTML       #FF6600
  14228.     #include  "OL_DOC.DH"
  14229.  
  14230.  
  14231. ΓòÉΓòÉΓòÉ 9.6.2.20. PRE_COLOR_IPF ΓòÉΓòÉΓòÉ
  14232.  
  14233. PRE_COLOR_IPF 
  14234.  
  14235. This is an option which modifies the tags of OL_DOC.DH operate (look and feel). 
  14236.  
  14237. This option is used to alter the color of the output from the example tags when 
  14238. they generate IPF. You might also wish to modify the PRE_COLOR_HTML option. 
  14239.  
  14240. EXAMPLE 
  14241.  
  14242.     #define   PRE_COLOR_IPF       darkred
  14243.     #include  "OL_DOC.DH"
  14244.  
  14245.  
  14246. ΓòÉΓòÉΓòÉ 9.6.2.21. PRE_STYLE_OTHER_HTML ΓòÉΓòÉΓòÉ
  14247.  
  14248. PRE_STYLE_OTHER_HTML 
  14249.  
  14250. This is an option which modifies the tags of OL_DOC.DH operate (look and feel). 
  14251.  
  14252. This option is used to alter the style of the output from the example tags when 
  14253. they generate HTML. You should not use this option to change the forground 
  14254. color as the PRE_COLOR_HTML option is intended for this purpose. 
  14255.  
  14256. If you use this option the then if you are assigning and styles then they must 
  14257. begin with ';'. 
  14258.  
  14259. The styles you specify will be ignored by any browser that does not have style 
  14260. sheet support. 
  14261.  
  14262. EXAMPLE 
  14263.  
  14264.     ;#define   PRE_STYLE_OTHER_HTML                ;;Leave font as is
  14265.     #define   PRE_STYLE_OTHER_HTML ;font-size:80%  ;;Make font a little smaller
  14266.     #include  "OL_DOC.DH"
  14267.  
  14268.  
  14269. ΓòÉΓòÉΓòÉ 9.6.3. EXAMPLE - TEST.D (source file) ΓòÉΓòÉΓòÉ
  14270.  
  14271. EXAMPLE - TEST.D (source file) 
  14272.  
  14273. ;----------------------------------------------------------------------------
  14274. ;     MODULE NAME:   TEST.D
  14275. ;
  14276. ;         $Author:   Dennis_Bareis  $
  14277. ;       $Revision:   1.4  $
  14278. ;           $Date:   26 Oct 1999 17:19:28  $
  14279. ;        $Logfile:   E:/DB/PVCS.IT/OS2/PPWIZARD/TEST.D_V  $
  14280. ;
  14281. ;     DESCRIPTION:   This example shows the creation of 2 sections.  If
  14282. ;                    generating HTML (all that currently works!) then 2 files
  14283. ;                    will be generated.  Currently the "root" output file
  14284. ;                    does not get any data, in future it will hopefully be
  14285. ;                    a contents page.
  14286. ;
  14287. ;----------------------------------------------------------------------------
  14288.  
  14289.  
  14290. ;--- As I user I only support HTML & IPF ------------------------------------
  14291. #if    '<$DocType>' <> 'HTML' & '<$DocType>' <> 'IPF'
  14292.        #error  'The document type "<$DocType>" is unsupported.'
  14293. #endif
  14294.  
  14295. ;--- Include document support -----------------------------------------------
  14296. ;#define    OL_DOC_HTML_8_3_NAMES
  14297. #define    OL_DOC_HTML_BODY                        <BODY BACKGROUND="bground.jpg" BGCOLOR="#FFFFFF">
  14298. #define    OL_DOC_HTML_SEARCH                      <A HREF="pwsearch.htm">[Search]</A>
  14299. #define    OL_DOC_HEADINGS_DONT_GENERATE_TITLE     ;;All my sections already have a title specified
  14300. #include  "OL_DOC.DH"
  14301.  
  14302. ;--- Define the start of the document ---------------------------------------
  14303. <$DocumentStart Text="Stupid Example Document">
  14304.  
  14305. ;--- Lets create some macros ourselves --------------------------------------
  14306. #define RedBold  <$Red Text=<$Bold Text=Γûê{$Text}Γûê>>   ;;Uses preexisting macros only
  14307. #if    ['<$DocType>' = 'HTML']
  14308.        ;--- HTML ------------------------------------------------------------
  14309.        #define MyGreen  <FONT COLOR=GREEN>{$Text}</FONT>
  14310. #elseif
  14311.        ;--- IPF -------------------------------------------------------------
  14312.        #define MyGreen  :color fc=darkgreen.{$Text}:color fc=default.
  14313. #endif
  14314.  
  14315.  
  14316.  
  14317. ;############################################################################
  14318. <$Heading Text="Hash Commands">                     ;;By default ID = TEXT
  14319. <$HeadingDown>                                      ;;Sub headings follow
  14320. ;############################################################################
  14321. <$Index1>                              ;;Same as 'Text="Hash Commands"'
  14322. <$Title>
  14323.  
  14324.  
  14325. <$p>An example which stesses things a bit<$Colon>
  14326. <$Example STATE="REMEMBER">
  14327.    This is line 1.
  14328.    This is line 2.  Note that '&' will get translated as will ';' (you will not notice this in VIEW.EXE of course)!
  14329.  
  14330.    This is line 4.  FONT   => <FONT>Some stuff</FONT>
  14331.    This is line 5.  MACRO  => <$FRED>
  14332.    This is line 5.  SMACRO => <?x41>
  14333. <$eExample>
  14334.  
  14335.  
  14336.  
  14337. <$P>This is an
  14338. #if    ['<$DocType>' = 'IPF']
  14339.        IPF
  14340. #elseif
  14341.        HTML (probably)
  14342. #endif
  14343. manual. The following commands are valid<$Colon>
  14344.  
  14345.    <$OrdListCompact>
  14346.        <$LI><$LinkTo Text="#def">
  14347.        <$LI><$LinkTo Text="#inc">
  14348.    <$eOrdListCompact>
  14349.  
  14350.  
  14351. <$P>This is the second paragraph, the contents of
  14352. "c<$Colon>\config.sys" follows<$Colon>
  14353.  
  14354.    <$ExampleFile INDENT=0 FILE="C:\CONFIG.SYS">
  14355.  
  14356. <$p>This will load "#def" doco at the "target"
  14357. <$LinkTo ID="#def" Text="XXXX" Target="XXXX">!
  14358.  
  14359.  
  14360.  
  14361. ;############################################################################
  14362. <$Heading Text="#def">                     ;;ID = #def
  14363. ;############################################################################
  14364. <$Index2>
  14365. <$Title>                              ;;Title matches heading (no need to specify)
  14366.  
  14367. <$P>This is a link to <$LinkTo Text="ezine">...
  14368. <$P>This is a #def.  This is a link to <$LinkTo Text="#inc">...
  14369.  
  14370. <$P>Note that I was using TEXT=ID with "#" included to stress my macros as
  14371. this character is considered to be invalid and needs to be converted....
  14372.  
  14373. <$Target Name="XXXX">
  14374. <$p>This is the target "XXXX", you can link to here.
  14375.  
  14376. <$p>The following shows some different colors used as well as demonstrating
  14377. an unnumbered list (with space between each entry)<$Colon>
  14378.  
  14379.    <$UnNumberedList>
  14380.        <$LI><$Red     Text="This is RED.">
  14381.        <$LI><$Bold    Text="This is BOLD.">
  14382.        <$LI><$MyGreen TEXT='This is "MyGreen".'>
  14383.             <$br>This starts on a new line.
  14384.             <$p>This starts a new paragraph.
  14385.        <$LI><$RedBold Text="This is RED <$Amp> BOLD (my custom macro).">
  14386.    <$eUnNumberedList>
  14387.  
  14388.  
  14389. <$p>The following shows a compact unnumbered list<$Colon>
  14390.    <$UnNumberedListCompact>
  14391.        <$LI>Item 1
  14392.        <$LI>Item 2
  14393.        <$LI>Item 3
  14394.    <$eUnNumberedListCompact>
  14395.  
  14396.  
  14397. ;############################################################################
  14398. <$Heading ID="#inc" Text="#inc">
  14399. ;############################################################################
  14400. <$Index2>
  14401. <$Title>
  14402.  
  14403. <$P>This is a #inc. This is a link to <$LinkTo Text="#def">...
  14404.  
  14405. <$P>This is a new paragraph with an example of <$Bold Text="bold"> text.
  14406.  
  14407.  
  14408.  
  14409.  
  14410.  
  14411.  
  14412. ;############################################################################
  14413. <$HeadingUp>
  14414. <$Heading Text="EXAMPLES">
  14415. ;############################################################################
  14416. <$Index1>
  14417.  
  14418. <$Title Text="Example #1 - Not from file">
  14419.  
  14420. <$Example STATE="REMEMBER">
  14421.    This is line 1.
  14422.    This is line 2.  Note that '&' will get translated as will ';' (you will not notice this in VIEW.EXE of course)!
  14423. <$eExample>
  14424.  
  14425.  
  14426. <$Title Text="Example #1 - NO special Tagging">
  14427. <$ExampleFile FILE="C:\AUTOEXEC.BAT">
  14428.  
  14429.  
  14430. <$Title Text="Example #2 - Convert 'REM' to '***'">
  14431. #AutoTagState  +
  14432. #AutoTag       'REM' '***'
  14433. <$ExampleFile FILE="C:\AUTOEXEC.BAT" State='REMEMBER'>
  14434. #AutoTagState  -
  14435.  
  14436.  
  14437. ;--- Define some codes ------------------------------------------------------
  14438. #RexxVar  "QM"      =x=  "?"
  14439. #RexxVar  "DOLLAR"  =x=  "$"
  14440. #include "EZINE.DH"
  14441.  
  14442. ;--- End of source code -----------------------------------------------------
  14443. <$DocumentEnd>
  14444.  
  14445.  
  14446. ΓòÉΓòÉΓòÉ 9.7. PUSHPOPM.H - Save/Restore Macro Values ΓòÉΓòÉΓòÉ
  14447.  
  14448. PUSHPOPM.H - Save/Restore Macro Values 
  14449.  
  14450. This is a small header file with support for the saving and restoring of macro 
  14451. values. 
  14452.  
  14453. PUSHPOPM.H 
  14454.  
  14455. ;----------------------------------------------------------------------------
  14456. ;     MODULE NAME:   PUSHPOPM.H
  14457. ;
  14458. ;         $Author:   Dennis_Bareis  $
  14459. ;       $Revision:   1.2  $
  14460. ;           $Date:   13 Nov 1999 13:39:46  $
  14461. ;        $Logfile:   E:/DB/PVCS.IT/OS2/PPWIZARD/PUSHPOPM.H_V  $
  14462. ;
  14463. ;     DESCRIPTION:   This is a header file for saving and restoring MACRO
  14464. ;                    values.
  14465. ;
  14466. ;                    This is useful where you need to "protect" the value
  14467. ;                    from a header file you are including.  Fairly rare
  14468. ;                    requirement, but handy when you need it.
  14469. ;
  14470. ;         EXAMPLE:   #define     XXXX    Some value
  14471. ;                    <$MacroPush Macro='XXXX'>           ;;Save it
  14472. ;                    #include    "File"                  ;;Header may change value
  14473. ;                    <$MacroPop  Macro='XXXX'>           ;;Restore it
  14474. ;----------------------------------------------------------------------------
  14475.  
  14476.  
  14477. ;--- Only include once ----------------------------------
  14478. #ifndef VERSION_PUSHPOPM_H
  14479.    ;--- Define the version number of this header file ---
  14480.    #define   VERSION_PUSHPOPM_H    99.289
  14481.  
  14482.    ;--- Include nesting validation code -----------------
  14483.    #include "nestchk.h"
  14484.    <$NestingInit Id="PUSHPOPM" DESC="PUSHPOPM.H stack macro tag">
  14485.  
  14486.    ;--- Push Macro --------------------------------------
  14487.    #define MacroPush                                                    \
  14488.            <$NestingInc Id="PUSHPOPM">                                 -\
  14489.            #evaluate    ''          ^MacroPush = MacroGet('{$Macro}')^ -\
  14490.            #RexxVar     'MacroPush'  PUSH
  14491.  
  14492.    ;--- Pop Macro ---------------------------------------
  14493.    #define MacroPop                                  \
  14494.            <$NestingDec Id="PUSHPOPM">              -\
  14495.            #RexxVar     'MacroPush'  POP            -\
  14496.            #evaluate+   '{$Macro}'  'MacroPush'
  14497. #endif
  14498.  
  14499.  
  14500. ΓòÉΓòÉΓòÉ 10. Performance ΓòÉΓòÉΓòÉ
  14501.  
  14502. Performance 
  14503.  
  14504. While PPWIZARD is written in rexx a lot of work has gone into keeping it fast. 
  14505. It has a lot of features and I'll probably add more.  In general I have added 
  14506. these with no loss of performance (in fact I've generally gained as I've 
  14507. rewritten parts to add new functionality). 
  14508.  
  14509. As PPWIZARD is so powerful you will be tempted to do some very complex things, 
  14510. much like I have in writing the document you are now reading in PPWIZARD 
  14511. macros.  This section aims to give you some hints as to what you can do to 
  14512. speed up processing (if you need to). 
  14513.  
  14514. Macro Performance 
  14515.  
  14516.        1. Macro performance is not affected by the number of macros you create. 
  14517.  
  14518.        2. Macro performance is not affected by the length of a definition's 
  14519.           name. 
  14520.  
  14521.        3. The #evaluate & #if commands are very slow (on a Pentium 100 you can 
  14522.           do about 380/second). If you have large numbers of these in your 
  14523.           source then where possible use the #define or #RexxVar command in 
  14524.           place of "#evaluate". The #if [] form is very quick and should be 
  14525.           used where possible. Better yet for complex logic consider using 
  14526.           straight rexx code, possibly defined using #DefineRexx, this allows 
  14527.           you to use rexx's "select" etc and rapidly perform complex logic. 
  14528.  
  14529.        4. Keep the macros as short as possible (particularly the line count). 
  14530.  
  14531.        5. Don't include conditional logic where possible. For example if you 
  14532.           know at macro definition time that you will never follow a certain 
  14533.           path then don't include it (that is conditionally generate the macro 
  14534.           once). Not only will the line count decrease but a #if command is one 
  14535.           of the slower ones. Another benefit is that its easier to watch whats 
  14536.           going on when debug mode is on. 
  14537.  
  14538.        6. In a similar vein to the previous point, if you have to pass a 
  14539.           parameter to a macro to conditionally execute a certain path, then it 
  14540.           would be better to create multiple variations of the macro and drop 
  14541.           the parameter and conditional generation code. 
  14542.  
  14543.        7. To make code easier to understand I usually do one rexx task per 
  14544.           #evaluate, however as an evaluate is slow you could bunch a number of 
  14545.           rexx commands in one #evaluate command (at least in any of your high 
  14546.           use macros). The #DefineRexx command can be used to define a whole 
  14547.           series of rexx statements in an easy to read/understand way. 
  14548.  
  14549.        8. You have the choice of storing information in a macro or rexx 
  14550.           variable.  Look at your main uses for the variable and decide which 
  14551.           is best for each situation.  If you are doing heaps of rexx 
  14552.           manipulations or tests (#if etc) then it would normally be better as 
  14553.           a rexx variable. 
  14554.  
  14555.        9. You can save steps in a macro by using " <??RexxVariable>" to get 
  14556.           access to a rexx variable without first having to get a copy with 
  14557.           #evaluate. 
  14558.  
  14559.       10. You can use "#define+" & "#evaluate+" instead of #undef. 
  14560.  
  14561.       11. For simple text macros you might want to consider using rexx 
  14562.           variables. Depending on how you use the information using rexx 
  14563.           variables can be much faster, for example in a #if or #evaluate 
  14564.           statement you can remove the need for the substitution syntax and use 
  14565.           the value directly. Where you do need to specify substitution use the 
  14566.           <??RexxVariable> syntax. 
  14567.  
  14568.  #AutoTag Performance 
  14569.  
  14570.        1. Unlike macros, the more autotags you have defined the slower it will 
  14571.           be to tag each line. 
  14572.  
  14573.        2. Replacing autotags (defined with #AutoTag) are slow. Only use if no 
  14574.           other way and for as few lines as possible. 
  14575.  
  14576.        3. To temporarily reduce your autotag count (remove ones you don't need) 
  14577.           you can use the #AutoTagState to hide current definitions before 
  14578.           creating your own command. Making good use of named states will 
  14579.           simplify this process. 
  14580.  
  14581.  #AsIs Performance 
  14582.  
  14583.        1. Unlike macros, the more changes you have defined the slower it will 
  14584.           be to tag each line. 
  14585.  
  14586.        2. There is inbuilt optimization for single character "from" text, if 
  14587.           possible  group these together. This allows the BulkChar2String() 
  14588.           routine to be used to greater effect. Tagging must take place in the 
  14589.           order you specify so PPWIZARD does not reorder the items to improve 
  14590.           performance. 
  14591.  
  14592.  Other Performance Hints 
  14593.  
  14594.        1. This may be obvious but PPWIZARD is CPU bound. What this means is the 
  14595.           speed of the CPU is directly proportional with the time PPWIZARD 
  14596.           takes. If your CPU is twice as fast PPWIZARD will take half the time. 
  14597.           Do yourself a favor and use the fastest machine you can find. 
  14598.  
  14599.        2. Under OS/2 you have multiple choices as to which rexx interpreter you 
  14600.           can use (DOS has 2 as well). There is the REGINA version as well as 
  14601.           traditional rexx (as exists after OS/2 install) or Object Orientated 
  14602.           Rexx. If you find things a bit slow it is probably worth your while 
  14603.           experimenting. Different interpreters will do some things better than 
  14604.           others. You really need to time your particular situation. 
  14605.  
  14606.        3. For common headers etc it may be better if they were not on a network 
  14607.           drive. Better yet a RAM disk would be good. Maybe increasing your 
  14608.           hard disk cache size could improve things. 
  14609.  
  14610.        4. You might wish to try the /Inc2Cache switch. 
  14611.  
  14612.        5. You might wish to try PPWSORT.H macros rather than SortArray(). 
  14613.  
  14614.        6. Ppwizard is optimised for fast execution with debug turned off, and 
  14615.           in fact may perform extra work when debug is on (on the assumption 
  14616.           that execution time is not an issue). So for high performance turn 
  14617.           debug off! 
  14618.  
  14619.  
  14620. ΓòÉΓòÉΓòÉ 11. e-Zine! Articles ΓòÉΓòÉΓòÉ
  14621.  
  14622. e-Zine! Articles 
  14623.  
  14624. The e-Zine! magazine (http://www.os2ezine.com) as well as the OS/2 Supersite 
  14625. (http://www.os2ss.com/) both use this preprocessor. 
  14626.  
  14627. Chris Wenham (the Senior Editor of OS/2 e-Zine! chris@os2ezine.com) has written 
  14628. a series of articles for e-Zine! which he has allowed me to include in my 
  14629. documentation. 
  14630.  
  14631. The following articles are available: 
  14632.  
  14633.        1. http://www.os2ezine.com/v3n05/htmlpp1.htm 
  14634.  
  14635.        2. http://www.os2ezine.com/v3n06/htmlpp.htm 
  14636.  
  14637.        3. http://www.os2ezine.com/v3n12/dyn3.htm 
  14638.  
  14639.        4. http://www.os2ezine.com/v3n14/dws.htm 
  14640.  
  14641.        5. http://www.os2ezine.com/v4n3/dws.htm 
  14642.  
  14643.  
  14644. ΓòÉΓòÉΓòÉ 12. Examples ΓòÉΓòÉΓòÉ
  14645.  
  14646. Examples 
  14647.  
  14648. As well as the many examples that follow, you should also have a look at the 
  14649. PPWIZARD Extensions section as it contains many header files that make 
  14650. excellent examples. 
  14651.  
  14652.  
  14653. ΓòÉΓòÉΓòÉ 12.1. Importing fields into multiple HTML documents ΓòÉΓòÉΓòÉ
  14654.  
  14655. Importing fields into multiple HTML documents 
  14656.  
  14657. This example shows how to import a comma delimited file into multiple html 
  14658. pages. The page each record goes into depends on the first character of the 
  14659. "surname" field. This basic process would also work for Fixed Field and Multi 
  14660. Line imports. 
  14661.  
  14662. Example 
  14663.  
  14664. ;----------------------------------------------------------------------------
  14665. ;    MODULE NAME:   IMPORT.IT
  14666. ;
  14667. ;    DESCRIPTION:   Example file of import of a comma delimited file into
  14668. ;                   3 separate HTML files based on the surname field (the
  14669. ;                   second field).
  14670. ;
  14671. ;
  14672. ;                   Imported file looks like:
  14673. ;                   ~~~~~~~~~~~~~~~~~~~~~~~~~
  14674. ;                   Dennis,Bareis,Programmer
  14675. ;                   Wendy,Buxton,Librarian
  14676. ;                   Fred,Nerk,Idiot
  14677. ;
  14678. ;----------------------------------------------------------------------------
  14679.  
  14680.  
  14681. ;--- Start and end main HTML file -------------------------------------------
  14682. <HTML>
  14683. <HEAD>
  14684.    <TITLE>MAIN FILE</TITLE>
  14685. </HEAD>
  14686. <BODY>
  14687. <H1>MAIN FILE</H1>
  14688. <P>This is a fairly basic example kept simple on purpose to hopefully
  14689. make things easier to understand.
  14690. Basically we imported a comma delimited
  14691. file (could have been fixed or other format) and put the record into a
  14692. particular html page based on the surname field.
  14693.  
  14694. <P>The following imported tables are available:
  14695. <OL>
  14696.    <LI><A HREF="p_a2l.htm">A - L</A>
  14697.    <LI><A HREF="p_m2z.htm">M - Z</A>
  14698.    <LI><A HREF="p_oth.htm">Others</A>
  14699. </OL>
  14700. </BODY></HTML>
  14701.  
  14702.  
  14703.  
  14704. ;--- Define HTML to start the import data files -----------------------------
  14705. #define StartsImportFiles                           \
  14706.         #output 'p_{$Suffix}.htm' ASIS             -\
  14707.         <HTML>                                     %\
  14708.         <HEAD>                                     %\
  14709.            <TITLE>IMPORTED: {$DESCRIPTION}</TITLE> %\
  14710.            <?PpwizardGeneratorMetaTags>            %\
  14711.         </HEAD>                                    %\
  14712.         <BODY>                                     %\
  14713.         <CENTER>                                   %\
  14714.         <H1>IMPORTED: {$DESCRIPTION}</H1>          %\
  14715.         <TABLE BORDER=5 CELLSPACING=5>             %\
  14716.         <TR><TH ALIGN=CENTER>First<BR>Name<TH ALIGN=CENTER>Surname<TH ALIGN=CENTER>Job</TR> %\
  14717.         #output
  14718.  
  14719. ;--- Define HTML to end the import data files -------------------------------
  14720. #define TrNoRecords   <TD ALIGN=CENTER><FONT COLOR="RED">No records</FONT></TD>
  14721. #define EndsImportFiles                                          \
  14722.         #output 'p_{$Suffix}.htm' ASIS APPEND                   -\
  14723.         #if {$Suffix} = 'N'                                     -\
  14724.             <TR><$TrNoRecords><$TrNoRecords><$TrNoRecords></TR> -\
  14725.         #endif                                   -\
  14726.         </TABLE>                                 %\
  14727.         </CENTER>                                %\
  14728.         </BODY></HTML>                           %\
  14729.         #output
  14730.  
  14731.  
  14732.  
  14733. ;--- Create 3 output files and fill with start of HTML and start table etc ---
  14734. <$StartsImportFiles SUFFIX="oth" DESCRIPTION="OTHER">
  14735. <$StartsImportFiles SUFFIX="a2l" DESCRIPTION="A to L">
  14736. <$StartsImportFiles SUFFIX="m2z" DESCRIPTION="M to Z">
  14737.  
  14738. ;--- Prepare for import -----------------------------------------------------
  14739. #evaluate ''  'NL = d2c(10)'                        ;;NL = Newline Code
  14740. #evaluate ''  'oth = 'N'; a2l = 'N'; m2z = 'N';'    ;;No records output yet
  14741. #define     IMPORT_PROTECT_START                    ;;We don't want imported data "protected" or #output etc won't get executed
  14742. #define     IMPORT_PROTECT_END
  14743. #define     IMPORT_HEADER                           ;;We will output our own headers
  14744. #define     IMPORT_BEFORE
  14745. #define     IMPORT_AFTER                            ;;We will output our own trailers
  14746. #DefineRexx IMPORT_RECORD_FILTER
  14747.         ;--- Which output file should contain this record? ---
  14748.         Char1 = translate(left(Column.2, 1));
  14749.         if Char1 < 'A' & Char1 > 'Z' then
  14750.         do;
  14751.            Suffix = 'oth';    ;;Not a letter
  14752.            oth    = 'Y';
  14753.         end;
  14754.         else;
  14755.         do;
  14756.            ;--- We have a letter ---
  14757.            if Char1 < 'M' then
  14758.            do;
  14759.               Suffix = 'a2l';
  14760.               a2l    = 'Y';
  14761.            end;
  14762.            else;
  14763.            do;
  14764.               Suffix = 'm2z';
  14765.               m2z    = 'Y';
  14766.            end;
  14767.         end;
  14768.  
  14769.         ;--- make sure output will go to correct file ---
  14770.         call WriteLineToTmpImportFile '#if <?OutputLevel> > 1' || NL || '   #output' || NL || '#endif';
  14771.         call WriteLineToTmpImportFile '#output ^p_' || Suffix || '.htm^ ASIS APPEND';
  14772. #DefineRexx
  14773.  
  14774. ;--- Import the data into the 3 files ---------------------------------------
  14775. #import Import.CMA CMA "" "First Name" "Surname" "Job"
  14776.  
  14777. ;--- Close last file --------------------------------------------------------
  14778. #if <?OutputLevel> > 1
  14779.     #output
  14780. #endif
  14781.  
  14782. ;--- Finish off 3 html tables and files ----
  14783. <$EndsImportFiles SUFFIX="oth">
  14784. <$EndsImportFiles SUFFIX="a2l">
  14785. <$EndsImportFiles SUFFIX="m2z">
  14786.  
  14787. Note that the example above overrides "IMPORT_PROTECT_START" and 
  14788. "IMPORT_PROTECT_END", this allows the generated PPWIZARD commands such as #if 
  14789. and #output to be interpreted rather than simply passed through as data. 
  14790.  
  14791. In some cases this may not be desirable as depending on exactly what you are 
  14792. doing you could put PPWIZARD into a situation where it could "make mistakes" 
  14793. (such as if a field contained '<$'). 
  14794.  
  14795. Although it can be desirable that PPWIZARD interpret macros and expand them if 
  14796. you catered for this in your design, I will demonstrate how you can ensure that 
  14797. they will not be - no matter what.  This will demonstrate an alternative 
  14798. approach to using the two "WriteLineToTmpImportFile" lines in the example above 
  14799. and will also ensure that the record line is "protected" from PPWIZARD: 
  14800.  
  14801.         ;--- Update what will get written to temp file ---                                     \
  14802.         AddB =         '#if <?OutputLevel> > 1' || NL || '   #output' || NL || '#endif' || NL; \
  14803.         AddB = AddB || '#output ^p_' || Suffix || '.htm^ ASIS APPEND' || NL;                   \
  14804.         AddB = AddB || '<?ProtectFromPpwStart>' || NL;                                         \
  14805.         AddA = NL   || '<?ProtectFromPpwEnd>';                                                 \
  14806.         ThisRecordsCodes = AddB || ThisRecordsCodes || AddA;
  14807.  
  14808.  
  14809. ΓòÉΓòÉΓòÉ 12.2. Resource Validation - Local ΓòÉΓòÉΓòÉ
  14810.  
  14811. Resource Validation - Local 
  14812.  
  14813. This example shows how you could ensure that your local resources actually 
  14814. exist (you should also have a look at the validation of remote resources 
  14815. support that PPWIZARD supplies). This helps to eliminate mistakes (its assumed 
  14816. that you won't forget to FTP local resources to the web server!). The example 
  14817. is HTML based but would work for any language or text file where external 
  14818. resources are referenced. 
  14819.  
  14820. While the macros I will show will work, typically everyone has a different way 
  14821. of working which would probably require these macros to be modified, however 
  14822. they are great as a guide. 
  14823.  
  14824. Generic Macro 
  14825.  
  14826. This macro makes no assumptions about your development environment and causes 
  14827. PPWIZARD to fail with an appropriate error message if the resource does not 
  14828. exist. 
  14829.  
  14830. The macro takes 2 manditory parameters, one identifies the full name of the 
  14831. file on the development machine and the other is used for resource 
  14832. identification purposes (when error occurs) and is normally how your HTML 
  14833. references it. 
  14834.  
  14835. The macro is as follows: 
  14836.  
  14837.     ;--- Generic check for resource validity routine ---
  14838.     #define    CheckResource                                                     \
  14839.                #if stream('{$LocalName}', 'c', 'query exists') = ''              \
  14840.                    #Error ^Resource "{$Name}" appears to be invalid. The file "{$LocalName}" could not be located!^ \
  14841.                #endif
  14842.  
  14843. Of course you may not wish to abort PPWIZARD for what you consider to be a 
  14844. warning situation, in this case you could use #warning instead. 
  14845.  
  14846. Development Environment Specific Macro 
  14847.  
  14848. In HTML when I refer to an image such as "graphics/fred.gif", the file 
  14849. "fred.gif" exists in the "graphics" directory when the HTML is "run". The image 
  14850. file could exist anywhere on my development machine so I will taylor a graphics 
  14851. validation setup as follows: 
  14852.  
  14853.     ;--- Check if Graphic exists ------------------------------------------------
  14854.     #option    PUSH LineContinuation="NULL"      ;;Next line ends with continuation char!
  14855.     #define    MyLocalGraphicsDirectory    C:\PROJECTS\HOMEPAGE\GRAPHICS\
  14856.     #option    POP                               ;;Restore original continuation char
  14857.     #define    MyRemoteGraphicsDirectory   graphics/
  14858.     #define    ValGraphic                                                        \
  14859.                <$CheckResource LocalName=^<$MyLocalGraphicsDirectory>{$SNAME}^   \
  14860.                                     Name=^<$MyRemoteGraphicsDirectory>{$SNAME}^  \
  14861.                >
  14862.  
  14863. The above macros are probably defined in a validation or other common header 
  14864. file. Note that you might wish to use shorter names such as "vlg" for "validate 
  14865. local graphic" etc. To actually test that an image file exists I could use: 
  14866.  
  14867.     <$ValGraphic SNAME="fred.gif">
  14868.     <IMG SRC="graphics/fred.gif">
  14869.  
  14870. Even the above macro and reference make some assumptions about how I personally 
  14871. wish to use them, this is another reason why everyone would probably "roll 
  14872. their own". 
  14873.  
  14874. An Alternative Way - #1 
  14875.  
  14876. The problem with the above set of macros is that you have to do 2 operations, 
  14877. the first is to validate the resource and the second is to use it. 
  14878.  
  14879. A better alternative is for the same routine that does the validation to 
  14880. generate the "remote" resource so that the generic macro (lets also change to 
  14881. only warning if resource is missing) becomes: 
  14882.  
  14883.     ;--- Generic check for resource validity routine ---
  14884.     #define    CheckResource                                                     \
  14885.                #if stream('{$LocalName}', 'c', 'query exists') = ''              \
  14886.                    #Warning ^$MR00^ ^Resource "{$Name}" appears to be invalid. The file "{$LocalName}" could not be located!^ \
  14887.                #endif                                                            \
  14888.                {$Name}             ;;"output" the "runtime" file name
  14889.  
  14890. Now the image based macros might look like: 
  14891.  
  14892.     ;--- Check if Graphic exists ------------------------------------------------
  14893.     #option    PUSH LineContinuation="NULL"      ;;Next line ends with continuation char!
  14894.     #define    MyLocalGraphicsDirectory    C:\PROJECTS\HOMEPAGE\GRAPHICS\
  14895.     #option    POP                               ;;Restore original continuation char
  14896.     #define    MyRemoteGraphicsDirectory   graphics/
  14897.     #define    UseGraphic                                                        \
  14898.                <$CheckResource LocalName=^<$MyLocalGraphicsDirectory>{$SNAME}^   \
  14899.                                     Name=^<$MyRemoteGraphicsDirectory>{$SNAME}^  \
  14900.                >
  14901.  
  14902. And to use the macro becomes automatic and simple: 
  14903.  
  14904.     <IMG SRC="<$UseGraphic SNAME='fred.gif'>">
  14905.  
  14906. Note that I kept the "UseGraphic" macro simple for demonstration purposes, for 
  14907. my purposes I would create a higher level "img" macro which not only validated 
  14908. the file exists but used GetImageHeightWidth() (by default) to automatically 
  14909. calculate the image size. Other "img" tag parameters could be passed as macro 
  14910. parameters (with suitable defaults). 
  14911.  
  14912. A html validation version would be slightly more complex than the above since 
  14913. you would probably wish to also handle the "#location" suffix. The simplest 
  14914. (and maybe best) way to handle it might be just to have a new optional 
  14915. parameter. Another complication is that you would probably look for a local 
  14916. file with the extension ".IT", again exactly how it looks is really a personal 
  14917. preference. 
  14918.  
  14919. An Alternative Way - #2 
  14920.  
  14921. Under OS/2 there is a free URL checking program which can be given a list of 
  14922. URLs to check. Similar programs will exist for other operating systems. 
  14923.  
  14924. You could create a ".URL" file for each html page and have your macros not only 
  14925. check that everything is fine locally, but add each URL in turn to the new file 
  14926. (deleted at start of build). Later when online and after updating your web site 
  14927. you could run the lists through the URL checking program. 
  14928.  
  14929. Case Sensitivity 
  14930.  
  14931. None of the code shown actually checks the case of the filename so its possible 
  14932. that although the code shows that the file exists locally, if copied to a unix 
  14933. server a "browser" will not find the file. There are a number of changes you 
  14934. can do to check the case or even simpler would be to transfer the files to the 
  14935. unix server in lower case and ensure that you refer to the files in lower case. 
  14936.  
  14937. SiteCopy 
  14938.  
  14939. So as to be very sure that you never forget to correctly update your web site 
  14940. you can use an automated tool such as "SiteCopy" to FTP new or modified files 
  14941. and directories. It will also delete obsolete files and directories. 
  14942.  
  14943. This tool is a bit rough around the edges but it is free and if you provide the 
  14944. developers with constructive feedback they will probably listen. I am using 
  14945. this tool for my site updating. 
  14946.  
  14947. There are OS/2, Windows and other ports of the unix program, the main sitecopy 
  14948. page is at http://www.lyra.org/sitecopy/. 
  14949.  
  14950.  
  14951. ΓòÉΓòÉΓòÉ 12.3. SHARING HEADERS - HTML + REXX CGI ΓòÉΓòÉΓòÉ
  14952.  
  14953. SHARING HEADERS - HTML + REXX CGI 
  14954.  
  14955. Whenever you use the #define command to define something you have already 
  14956. decided (whether or not you realise it) the contexts it can be used in. 
  14957.  
  14958. As an example, you could create a definition which expands to a filename 
  14959. surrounded by double quotes, this can only be used in situations where the 
  14960. double quotes are required (or won't interfere). Your other major choice was 
  14961. not to supply double quotes, this then requires you to supply double quotes 
  14962. when used in situations where the quotes are required. 
  14963.  
  14964. Sometimes you can have a mismatch between "languages" which mean that you will 
  14965. need to get "tricky" when creating definitions when a header file is shared 
  14966. such as where a common header file is shared between HTML and rexx code (server 
  14967. CGI script for example). 
  14968.  
  14969. You should understand that PPWIZARD has a /CGI mode, this example does not 
  14970. cover this at all. The rexx CGI script discussed in this example is generated 
  14971. by ppwizard and placed onto the web server for execution. When the /CGI mode is 
  14972. used the header sharing issues discussed here along with the solutions are not 
  14973. relevant and in a lot of cases using this switch may be the simplest solution. 
  14974.  
  14975. Some REXX CGI / HTML Issues 
  14976.  
  14977.        1. Rexx has a limit on the size of a literal. So if you had a standard 
  14978.           HTML footer which successfully expands to 2000 characters in a HTML 
  14979.           document, simply putting quotes around the text for rexx would result 
  14980.           in a 2000 byte literal. The limit is more likely to be around 250 
  14981.           bytes! 
  14982.  
  14983.        2. In a REXX CGI script it may be that some substituted text (macro 
  14984.           parameter) may not be known until runtime whereas with HTML you are 
  14985.           likely to be able to "hard code" it. 
  14986.  
  14987.        3. Some rexx interpreters also have a limit on the maximum length of a 
  14988.           command. 
  14989.  
  14990.        4. There may be a maximum line limit in some rexx interpreters. 
  14991.  
  14992.  EXAMPLE - COMMON HEADER 
  14993.  
  14994.   ;--- We need to get tricky to use some LONG macros in rexx code -------------
  14995.   #if  ['<?ProcessingMode>' = 'REXX']
  14996.        ;--- We are generating REXX code (take care of OS/2 & REGINA restrictions on lengths of literals and clauses) ---
  14997.        #define   RexxAssignTo CgiVar           ;;The user must assign macro to this variable
  14998.        #define   RexxQuote  ' || "'" || '      ;;Used in place of any single quotes
  14999.        #define   RexxConcat ';<?NewLine><$RexxAssignTo> = <$RexxAssignTo> || '                 ;;End old & start new literal
  15000.   #elseif
  15001.        ;--- We are generating HTML --------------------------------------------
  15002.        #define   RexxQuote    '                ;;Simply expand to single quote
  15003.        #define   RexxConcat
  15004.   #endif
  15005.  
  15006.  In the above "RexxConcat" is designed to be used "every so often" (within 
  15007.  rexx's literal limit). When expanding in HTML it does nothing. In rexx code it 
  15008.  finishes off the literal, statement and line then starts another. 
  15009.  
  15010.  The "RexxQuote" is designed to be used in place of any single quotes you might 
  15011.  wish to output in the expanded text. There should be few of these as you will 
  15012.  try to use double quotes everywhere. 
  15013.  
  15014.  The following shows how a large macro might make use of the above definitions 
  15015.  (note that a lot of external macros are referenced which are not shown): 
  15016.  
  15017.   ;--- Define Headings --------------------------------------------------------
  15018.   #define TitleHtml                                                        \
  15019.           ;--- Start Html ------------------------------------------      -\
  15020.           <HTML>                                                          -\
  15021.           <HEAD>                                                          -\
  15022.           <$HtmlDebugNL>                                                  -\
  15023.           <TITLE>{$Title=^{$Text}^}</TITLE>                               -\
  15024.           #if '{$OTHERHEADER_TAGS=^^}' <> ''                              -\
  15025.                <$HtmlDebugNL>                                             -\
  15026.                {$OTHERHEADER_TAGS=^^}                                     -\
  15027.           #endif                                                          -\
  15028.           <$HtmlDebugNL>                                                  -\
  15029.           </HEAD>                                                         -\
  15030.                                                                           -\
  15031.           ;--- Set up Body tag -------------------------------------      -\
  15032.           <$HtmlDebugNL>                                                  -\
  15033.           <$BodyStandardOs2Warp>                                          -\
  15034.           <$RexxConcat>                                                   -\
  15035.                                                                           -\
  15036.           ;--- Now output the standard heading bar -----------------      -\
  15037.           <$BsdHeadingBar TEXT=^{$Text=^Branch Systems Development^}^>
  15038.   #define BsdHeadingBar                                                    \
  15039.           ;--- Put Heading of page into a TABLE --------------------      -\
  15040.           <$HtmlDebugNL>                                                  -\
  15041.           <$HtmlDebugComment TEXT="Start of Heading Bar">                 -\
  15042.           <TABLE WIDTH=100% BORDER=0                                       \
  15043.                  BGCOLOR=<$BsdColorBgTitleAndNavigation>                   \
  15044.                  CELLSPACING=0 CELLPADDING=5                              -\
  15045.           >                                                               -\
  15046.           <$HtmlDebugNL>                                                  -\
  15047.           <$RexxConcat>                                                   -\
  15048.           <TR>                                                            -\
  15049.              ;--- All left hand images in one cell -------                -\
  15050.              <$HtmlDebugComment TEXT="All right hand images into 1 cell"> -\
  15051.              <TD ALIGN=LEFT>                                              -\
  15052.              <TABLE BORDER=0 CELLSPACING=0                                 \
  15053.                     CELLPADDING=1  ;;Set Image spacing                    -\
  15054.              >                                                            -\
  15055.              <TR>                                                         -\
  15056.                  ;--- Link To Intranet home page --------------           -\
  15057.                  <$HtmlDebugComment TEXT="Go to Intranet Homepage">       -\
  15058.                  <TD ALIGN=LEFT>                                          -\
  15059.                      <A HREF="<$IntranetHomePage>" TARGET=_top>           -\
  15060.                      <$IntranetImgHeaderAnz>                              -\
  15061.                      </A>                                                 -\
  15062.                  </TD>                                                    -\
  15063.                  <$RexxConcat>                                            -\
  15064.                                                                           -\
  15065.                  ;--- Link To BSD home page --------------                -\
  15066.                  <$HtmlDebugComment TEXT="Go to BSD Homepage">            -\
  15067.                  <TD ALIGN=LEFT>                                          -\
  15068.                      <A HREF="<$BsdHomePage>" TARGET=_top>                -\
  15069.                      <$BsdImgBsdHome>                                     -\
  15070.                      </A>                                                 -\
  15071.                  </TD>                                                    -\
  15072.                  <$RexxConcat>                                            -\
  15073.                                                                           -\
  15074.              ;--- End of left hand images TABLE ----------                -\
  15075.              <$HtmlDebugNL>                                               -\
  15076.              </TABLE>                                                     -\
  15077.              </TD>                                                        -\
  15078.                                                                           -\
  15079.              ;--- Output title of this page ---------------               -\
  15080.              <$HtmlDebugComment TEXT="Title of this page">                -\
  15081.              <TD ALIGN=MIDDLE><FONT COLOR=<$BsdColorFgTitle>               \
  15082.                  SIZE={$FONTSIZE="+2"}                                    -\
  15083.              >                                                            -\
  15084.                  <B><CENTER><STRONG>                                      -\
  15085.                  {$Text=^Branch Systems Development^}                     -\
  15086.                  </STRONG></CENTER></FONT></B>                            -\
  15087.              </TD>                                                        -\
  15088.              <$RexxConcat>                                                -\
  15089.                                                                           -\
  15090.              ;--- All right hand images in one cell -------               -\
  15091.              <$HtmlDebugComment TEXT="All right hand images into 1 cell"> -\
  15092.              <TD ALIGN=RIGHT>                                             -\
  15093.              <TABLE BORDER=0 CELLSPACING=0                                 \
  15094.                     CELLPADDING=1  ;;Set Image spacing                    -\
  15095.              >                                                            -\
  15096.              <TR>                                                         -\
  15097.                  ;--- Link to search for phone number ---------           -\
  15098.                  <$HtmlDebugComment TEXT="Link to Intranet Phone Search"> -\
  15099.                  <TD>                                                     -\
  15100.                      <A HREF="<$IntranetPhoneSearchPage>" TARGET=_top>    -\
  15101.                         <$IntranetImgHeaderPhone>                         -\
  15102.                      </A>                                                 -\
  15103.                  </TD>                                                    -\
  15104.                  <$RexxConcat>                                            -\
  15105.                                                                           -\
  15106.                  ;--- Link to Site Information ----------------           -\
  15107.                  <$HtmlDebugComment TEXT="Link to Intranet Site Info">    -\
  15108.                  <TD>                                                     -\
  15109.                      <A HREF="<$IntranetSiteInfoPage>" TARGET=_top>       -\
  15110.                      <$IntranetImgHeaderSiteInfo>                         -\
  15111.                      </A>                                                 -\
  15112.                  </TD>                                                    -\
  15113.                  <$RexxConcat>                                            -\
  15114.                                                                           -\
  15115.                  ;--- Link to search Engine -------------------           -\
  15116.                  <$HtmlDebugComment TEXT="Link to Intranet Search">       -\
  15117.                  <TD>                                                     -\
  15118.                      <A HREF="<$IntranetSiteSearchPage>" TARGET=_top>     -\
  15119.                      <$IntranetImgHeaderSiteSearch>                       -\
  15120.                      </A>                                                 -\
  15121.                  </TD>                                                    -\
  15122.                  <$RexxConcat>                                            -\
  15123.                                                                           -\
  15124.              ;--- End of right hand images TABLE ----------               -\
  15125.              <$HtmlDebugNL>                                               -\
  15126.              </TABLE>                                                     -\
  15127.              </TD>                                                        -\
  15128.                                                                           -\
  15129.           ;--- End of Heading Row/Table -------------------               -\
  15130.           </TR>                                                           -\
  15131.           </TABLE>                                                        -\
  15132.           <$HtmlDebugNL>                                                  -\
  15133.           <$HtmlDebugNL>
  15134.   #define Title                                                            \
  15135.           {$Rule="<P><HR>"}                                               -\
  15136.           #if  ['{$ID=''}' <> '']                                         -\
  15137.                <A NAME="{$ID=''}"></A>    ;;User wants to name this posn  -\
  15138.           #endif                                                          -\
  15139.           <CENTER><H2><FONT COLOR=<$BsdColorBgTitleAndNavigation>>        -\
  15140.           {$Text}                                                         -\
  15141.           </FONT></H2></CENTER>
  15142.  
  15143.  The following show how one of the macros could be used to generate a title in 
  15144.  HTML: 
  15145.  
  15146.   <$TitleHtml Text=^The Title of the Page^ FONTSIZE=^+2^>
  15147.  
  15148.  The following show how one of the macros could be used to generate a title in 
  15149.  a rexx CGI script (need to be written to stdout): 
  15150.  
  15151.   /*--- Get dummy title (set up at compile - of rexx source - time) ---*/
  15152.   #define+   RexxAssignTo    NewLineVar
  15153.   NewLineVar = '<$TitleHtml Text=^$DUMMY$^ FONTSIZE=^+2^>';
  15154.  
  15155.   /*--- Convert to real title and output (done at CGI runtime) --------*/
  15156.   NewLineVar = ReplaceString(NewLineVar, '$DUMMY$', RealTitle);
  15157.   say NewLineVar;
  15158.  
  15159.  Note that the ReplaceString() used above is not PPWIZARD's as of course at 
  15160.  runtime it is unavailable. My website contains the source code for this and 
  15161.  many other handy routines. 
  15162.  
  15163.  
  15164. ΓòÉΓòÉΓòÉ 12.4. TEXTEDIT with PPWIZARD ΓòÉΓòÉΓòÉ
  15165.  
  15166. TEXTEDIT with PPWIZARD 
  15167.  
  15168. I have another handy program called TEXTEDIT, it takes a text file as input. 
  15169. PPWIZARD can simplify handling of any text file and this example shows how I 
  15170. have used it to create some "macro" commands that not only simplifies the 
  15171. syntax but checks the return code (TEXTEDIT aborts on error). 
  15172.  
  15173. The code shown here is a small fragment of what I use to completely 
  15174. automatically extract menus, dialogs etc out of Netscape and modify or delete 
  15175. controls, then put the modified resources back into Netscape. 
  15176.  
  15177. DLG102.TE - The MAIN Program 
  15178.  
  15179. ;--------------------------------------------------------
  15180. ;--- Edits dialog 102 of Netscape 4.04 "Communicator" ---
  15181. ;--------------------------------------------------------
  15182.  
  15183. ;--- Include header file ----------------------------------------------------
  15184. #include   "DIALOG.H"
  15185.  
  15186. ;--- Disable Choose file button ---------------------------------------------
  15187. <$DisableControlLineGivenMiddle LINE=^<$DLG_CHOOSE_FILE>^>
  15188.  
  15189. ;--- Disable "Composer" radio button ----------------------------------------
  15190. <$DisableControlLineGivenMiddle LINE=^<$DLG_COMPOSER>^>
  15191.  
  15192. ;--- Thats all Folks! -------------------------------------------------------
  15193. <$WriteFile>
  15194.  
  15195. DIALOG.H - Dialog Specific Header 
  15196.  
  15197. ;--- Include generic stuff -------------------------------------------------
  15198. #include "TEXTEDIT.H"
  15199.  
  15200. ;--- Constants -------------------------------------------------------------
  15201. #define DLG_CHOOSE_FILE         Choose ~File
  15202. #define DLG_COMPOSER            ~Composer
  15203.  
  15204. ;--- Disable Control -------------------------------------------------------
  15205. #define DisableControlLineGivenMiddle                                            \
  15206.         ReplaceLines {$COUNT="1"} ^*{$LINE}*^ ^${ReplacedLine}, WS_DISABLED^    %\
  15207.         <?Hash>if  '${Rc}' <> '0'                                               %\
  15208.                @exit 255 'Could not find a control line matching = "*{$LINE}*"' %\
  15209.         <?Hash>endif
  15210.  
  15211. TEXTEDIT.H - Generic Header (for dialogs, menus etc) 
  15212.  
  15213. ;--- Macro to delete a line ------------------------------------------------
  15214. #define DeleteLineGivenMiddle                                            \
  15215.         DeleteBlock ^*{$LINE}*^   ^*{$LINE}*^                           %\
  15216.         <?Hash>if  '${Rc}' <> '0'                                       %\
  15217.                @exit 255 'Could not find a line matching = "*{$LINE}*"' %\
  15218.         <?Hash>endif
  15219.  
  15220. ;--- Write changed data to file --------------------------------------------
  15221. #define WriteFile                                            \
  15222.         ;--- Pretty up the final code (easier to read) ---  %\
  15223.         top                                                 %\
  15224.         ReplaceText 9999 "BEGIN" "{"                        %\
  15225.         ReplaceText 9999 "END"   "}"                        %\
  15226.                                                             -\
  15227.         ;--- Write the file ------------------------------  %\
  15228.         checkpoint
  15229.  
  15230. ;--- Find a line -----------------------------------------------------------
  15231. #define MustFindLineGivenMiddle                                          \
  15232.         Find {$COUNT="1"} ^*{$LINE}*^                                   %\
  15233.         <?Hash>if  '${Rc}' <> '0'                                       %\
  15234.                @exit 255 'Could not find a line matching = "*{$LINE}*"' %\
  15235.         <?Hash>endif
  15236.  
  15237.  
  15238. ΓòÉΓòÉΓòÉ 12.5. Rexx Preprocessing ΓòÉΓòÉΓòÉ
  15239.  
  15240. Rexx Preprocessing 
  15241.  
  15242. This program while mainly designed for html processing could be used for most 
  15243. languages.  It has specific support built in for the preprocessing of rexx 
  15244. code. 
  15245.  
  15246. Rexx code is by default packed.  This makes the resultant ".CMD" file much 
  15247. smaller than the original code and in many cases this would be enough of a 
  15248. reason to use it (although the packing is irrelevant if you then compile the 
  15249. ".CMD" into a ".EXE" using my rexx compiler). Also note that the packing will 
  15250. not speed up the execution of your code although it may slightly speed up the 
  15251. initial tokenization. 
  15252.  
  15253. If you examine the small example, you will notice that I used "#ifdef" commands 
  15254. to determine which parts of the header file I wished to include.  You could 
  15255. easily extend this concept to allow debug code to be added only when you wish 
  15256. to debug or have variations on error handling (log the message, ignore it etc). 
  15257. I don't normally define my subroutines as procedures because in my opinion the 
  15258. disadvantages of the way rexx does it outweighs the advantages, my example 
  15259. header file has been written so that the user of the subroutines can determine 
  15260. not only whether they should be procedures but what variables they should 
  15261. expose if they are! 
  15262.  
  15263. MORE ON PACKING 
  15264.  
  15265. The preprocessor packs well written code (by my definition!) and can fail to 
  15266. correctly pack code where strings are appended without the use of the "||" 
  15267. operator (as the excess spaces will be removed).  For example the following 
  15268. statement will not create the string you expect when packed: 
  15269.  
  15270.        BothPartsCombined = 'Value:'   TheValue;
  15271.  
  15272. The following statement is a version of the above that will work: 
  15273.  
  15274.         BothPartsCombined = 'Value:   ' || TheValue;
  15275.  
  15276. You can get very good results by packing but if you have got legacy code or you 
  15277. don't wish to change (your evil ways!) you should use the "/Pack:N" command 
  15278. line switch.  This turns off most packing (rexx comment and trailing ';' 
  15279. removal still occurs). 
  15280.  
  15281. If you have trouble with some parts of your code but the bulk packs well then 
  15282. you may wish to consider leaving packing on and using the AllowPack option to 
  15283. indicate parts of your rexx code that should not be packed. 
  15284.  
  15285. WARNING 
  15286.  
  15287. This has not been tested on object rexx so I don't know if it will work or not 
  15288. (I assume it will). 
  15289.  
  15290.  
  15291. ΓòÉΓòÉΓòÉ 12.5.1. Rexx Example ΓòÉΓòÉΓòÉ
  15292.  
  15293. Rexx Example 
  15294.  
  15295. The following batch file was used to generated the rexx code: 
  15296.  
  15297. @echo off
  15298. rem set DEBUG=/debug
  15299. ppwizard.cmd REXAMPLE.X /output:out\REXAMPLE.CMD /rexx
  15300.  
  15301. The source files are: 
  15302.  
  15303.        1. REXAMPLE.X 
  15304.        2. REXAMPLE.XH 
  15305.  
  15306.  The generated rexx code is: 
  15307.  
  15308.        1. REXAMPLE.CMD 
  15309.  
  15310.  
  15311. ΓòÉΓòÉΓòÉ 12.5.1.1. REXAMPLE.X ΓòÉΓòÉΓòÉ
  15312.  
  15313. REXAMPLE.X 
  15314.  
  15315. ;----------------------------------------------------------------------------
  15316. ;    MODULE NAME:   REXAMPLE.X
  15317. ;
  15318. ;        $Author:   Dennis_Bareis  $
  15319. ;      $Revision:   1.0  $
  15320. ;          $Date:   15 Mar 1999 17:33:38  $
  15321. ;       $Logfile:   E:/DB/PVCS.IT/OS2/PPWIZARD/REXAMPLE.X_V  $
  15322. ;
  15323. ;    DESCRIPTION:   Small example routine.
  15324. ;
  15325. ;----------------------------------------------------------------------------
  15326.  
  15327. /*--- Want the following comment in the generated output --------------------*/
  15328. /*
  15329.  * $Header:   E:/DB/PVCS.IT/OS2/PPWIZARD/REXAMPLE.X_V   1.0   15 Mar 1999 17:33:38   Dennis_Bareis  $
  15330.  */
  15331.  
  15332.  
  15333. /*--- I want all my routines to (1) be procedures & (2) Expose some variables ---*/
  15334. #define Procedure  procedure expose Variable1 Variable2
  15335.  
  15336.  
  15337. /*--- Load supporting routines ----------------------------------------------*/
  15338. #define  INCL_ReplaceString
  15339. #define  INCL_AddCommasToDecimalNumber
  15340. #include "REXAMPLE.XH"
  15341.  
  15342.  
  15343. /*--- Make a few changes and Generate the output message --------------------*/
  15344. Count  = 0;                                             ;;Initialize Counter (this is a PPWIZARD comment)
  15345. String = ReplaceString('AAAA', 'A', 'B', "Count");      /* Make some changes (this is a REXX comment) */
  15346. if Count = 0 then
  15347.    say 'No Changes made';
  15348. else
  15349.    say 'Count = ' || AddCommasToDecimalNumber(Count);
  15350. return(Count);
  15351.  
  15352.  
  15353. ΓòÉΓòÉΓòÉ 12.5.1.2. REXAMPLE.XH ΓòÉΓòÉΓòÉ
  15354.  
  15355. REXAMPLE.XH 
  15356.  
  15357. ;----------------------------------------------------------------------------
  15358. ;    MODULE NAME:   REXAMPLE.XH
  15359. ;
  15360. ;        $Author:   Dennis_Bareis  $
  15361. ;      $Revision:   1.2  $
  15362. ;          $Date:   09 Sep 1999 13:29:16  $
  15363. ;       $Logfile:   E:/DB/PVCS.IT/OS2/PPWIZARD/REXAMPLE.XHV  $
  15364. ;
  15365. ;    DESCRIPTION:   Small example header file.
  15366. ;
  15367. ;----------------------------------------------------------------------------
  15368.  
  15369. /*
  15370.  * $Header:   E:/DB/PVCS.IT/OS2/PPWIZARD/REXAMPLE.XHV   1.2   09 Sep 1999 13:29:16   Dennis_Bareis  $
  15371.  */
  15372.  
  15373.  
  15374. /*--- Skip past rexx routines -----------------------------------------------*/
  15375. #require   99.249
  15376. <?RexxSkip>
  15377.  
  15378.  
  15379. #ifdef INCL_AddCommasToDecimalNumber
  15380. /*===========================================================================*/
  15381. AddCommasToDecimalNumber:                                  /* Integers Only! */
  15382.                        #ifdef Procedure
  15383.                               <$Procedure>
  15384.                        #endif
  15385. /*===========================================================================*/
  15386.    /*--- Get number return it it we already have commas ---------------------*/
  15387.    acNoComma = strip( arg(1) );
  15388.    if  pos(',', acNoComma) <> 0 then
  15389.        return(acNoComma);
  15390.  
  15391.    /*--- split at possible decimal point ------------------------------------*/
  15392.    acDotPos = pos('.', acNoComma);
  15393.    if  acDotPos = 0 then
  15394.        acAfterDecimal = '';
  15395.    else
  15396.    do
  15397.        /*--- There is a decimal component -----------------------------------*/
  15398.        if  acDotPos = 1 then
  15399.            return("0" || acNoComma);
  15400.        acAfterDecimal = substr(acNoComma, acDotPos+1);
  15401.        acNoComma      = left(acNoComma, acDotPos-1);
  15402.    end;
  15403.  
  15404.    /*--- Reverse the integer ------------------------------------------------*/
  15405.    acNoComma = reverse(acNoComma);
  15406.  
  15407.    /*--- Grab 3 digits at a time --------------------------------------------*/
  15408.    acResultWithCommas = "";
  15409.    do  while length(acNoComma) > 3
  15410.        acResultWithCommas = acResultWithCommas || left(acNoComma, 3) || ',';
  15411.        acNoComma          = substr(acNoComma, 4);
  15412.    end;
  15413.    acResultWithCommas = acResultWithCommas || acNoComma;
  15414.  
  15415.    /*--- Reverse the string and add decimal component -----------------------*/
  15416.    acResultWithCommas = reverse(acResultWithCommas)
  15417.    if  acAfterDecimal <> '' then
  15418.        acResultWithCommas = acResultWithCommas || '.' || acAfterDecimal;
  15419.    return(acResultWithCommas);
  15420. #endif
  15421.  
  15422.  
  15423.  
  15424. #ifdef INCL_GetAmPmTime
  15425. /*===========================================================================*/
  15426. GetAmPmTime:                         /* Fixed length AM/PM time with seconds */
  15427.                        #ifdef Procedure
  15428.                               <$Procedure>
  15429.                        #endif
  15430. /*===========================================================================*/
  15431.    gtCivilTime  = time('C');  if length(gtCivilTime)  = 6 then gtCivilTime=' 'gtCivilTime;
  15432.    gtNumSeconds = ':'substr(time(), 7, 2);
  15433.    return( insert(gtNumSeconds, gtCivilTime, 5) );       /* Insert # seconds */
  15434. #endif
  15435.  
  15436.  
  15437.  
  15438. #ifdef INCL_ReplaceString
  15439. /*===========================================================================*/
  15440. ReplaceString:               /* Too tricky & limiting to set up as procedure */
  15441. /*===========================================================================*/
  15442.    /*--- Get the passed parameters ------------------------------------------*/
  15443.    rsString       = arg(1);
  15444.    rsChangeFrom   = arg(2);
  15445.    rsChangeTo     = arg(3);
  15446.    rsChangeCntVar = arg(4);                          /* Passed by reference! */
  15447.  
  15448.    /*--- Look for the search string -----------------------------------------*/
  15449.    rsChangeFromLength = length(rsChangeFrom);
  15450.    rsChangeToLength   = length(rsChangeTo);
  15451.    rsFoundPosn        = pos(rsChangeFrom, rsString);
  15452.    rsChangesMade      = 0;
  15453.    do  while rsFoundPosn <> 0
  15454.        /*--- Perform the substitution ---------------------------------------*/
  15455.        rsString = left(rsString, rsFoundPosn-1) || rsChangeTo || substr(rsString, rsFoundPosn+rsChangeFromLength);
  15456.  
  15457.        /*--- Look for the more occurances of the search string --------------*/
  15458.        rsFoundPosn = pos(rsChangeFrom, rsString, rsFoundPosn+rsChangeToLength);
  15459.        rsChangesMade = rsChangesMade + 1;
  15460.    end;
  15461.  
  15462.    /*--- Update the change counter and return to the caller -----------------*/
  15463.    if  rsChangeCntVar <> "" then
  15464.        interpret rsChangeCntVar || " = rsChangesMade + " || rsChangeCntVar;
  15465.    return(rsString);
  15466. #endif
  15467.  
  15468.  
  15469.  
  15470. /*--- End of header file ----------------------------------------------------*/
  15471. <?RexxSkipTo>
  15472.  
  15473.  
  15474. ΓòÉΓòÉΓòÉ 12.5.1.3. REXAMPLE.CMD (generated output) ΓòÉΓòÉΓòÉ
  15475.  
  15476. REXAMPLE.CMD (generated output) 
  15477.  
  15478. /*
  15479.  * Generator   : PPWIZARD version 99.289
  15480.  *             : FREE tool for OS/2, Windows, DOS and UNIX by Dennis Bareis (db0@anz.com)
  15481.  *             : http://www.labyrinth.net.au/~dbareis/ppwizard.htm
  15482.  * Time        : Sunday, 17 Oct 1999 2:06:48pm
  15483.  * Input File  : E:\DB\PROJECTS\OS2\ppwizard\REXAMPLE.X
  15484.  * Output File : out\REXAMPLE.CMD
  15485.  */
  15486.  
  15487. if arg(1)="!CheckSyntax!" then exit(21924)
  15488.  
  15489. /*
  15490. * $Header:   E:/DB/PVCS.IT/OS2/PPWIZARD/REXAMPLE.X_V   1.0   15 Mar 1999 17:33:38   Dennis_Bareis  $
  15491. */
  15492. /*
  15493. * $Header:   E:/DB/PVCS.IT/OS2/PPWIZARD/REXAMPLE.XHV   1.2   09 Sep 1999 13:29:16   Dennis_Bareis  $
  15494. */
  15495. signal REXAMPLE_1;
  15496.  
  15497. AddCommasToDecimalNumber:
  15498. procedure expose Variable1 Variable2
  15499. acNoComma = strip( arg(1) )
  15500. if  pos(',', acNoComma) <> 0 then
  15501. return(acNoComma)
  15502. acDotPos = pos('.', acNoComma)
  15503. if  acDotPos = 0 then
  15504. acAfterDecimal = ''
  15505. else
  15506. do
  15507. if  acDotPos = 1 then
  15508. return("0" || acNoComma)
  15509. acAfterDecimal = substr(acNoComma, acDotPos+1)
  15510. acNoComma      = left(acNoComma, acDotPos-1)
  15511. end
  15512. acNoComma = reverse(acNoComma)
  15513. acResultWithCommas = ""
  15514. do  while length(acNoComma) > 3
  15515. acResultWithCommas = acResultWithCommas || left(acNoComma, 3) || ','
  15516. acNoComma          = substr(acNoComma, 4)
  15517. end
  15518. acResultWithCommas = acResultWithCommas || acNoComma
  15519. acResultWithCommas = reverse(acResultWithCommas)
  15520. if  acAfterDecimal <> '' then
  15521. acResultWithCommas = acResultWithCommas || '.' || acAfterDecimal
  15522. return(acResultWithCommas)
  15523.  
  15524. ReplaceString:
  15525. rsString       = arg(1)
  15526. rsChangeFrom   = arg(2)
  15527. rsChangeTo     = arg(3)
  15528. rsChangeCntVar = arg(4)
  15529. rsChangeFromLength = length(rsChangeFrom)
  15530. rsChangeToLength   = length(rsChangeTo)
  15531. rsFoundPosn        = pos(rsChangeFrom, rsString)
  15532. rsChangesMade      = 0
  15533. do  while rsFoundPosn <> 0
  15534. rsString = left(rsString, rsFoundPosn-1) || rsChangeTo || substr(rsString, rsFoundPosn+rsChangeFromLength)
  15535. rsFoundPosn = pos(rsChangeFrom, rsString, rsFoundPosn+rsChangeToLength)
  15536. rsChangesMade = rsChangesMade + 1
  15537. end
  15538. if  rsChangeCntVar <> "" then
  15539. interpret rsChangeCntVar || " = rsChangesMade + " || rsChangeCntVar
  15540. return(rsString)
  15541.  
  15542. REXAMPLE_1:
  15543. Count  = 0
  15544. String = ReplaceString('AAAA', 'A', 'B', "Count")
  15545. if Count = 0 then
  15546. say 'No Changes made'
  15547. else
  15548. say 'Count = ' || AddCommasToDecimalNumber(Count)
  15549. return(Count)
  15550.