═══ 1. Introduction ═══ Introduction This is a generic preprocessor which allows you to use some very powerful features such as "#if", "#define" and "#include". The preprocessor works under: 1. OS/2 2. Windows NT 3. Windows 95 4. Windows 3.1 (use DOS) 5. DOS 6. UNIX (tested on Linux) PPWIZARD is more powerful than virtually any other preprocessor available and unlike many others remains simple to use (no complicated syntax), its replacement syntax is HTML like. The free "Regina" interpreter is required for operating systems other than OS/2. This preprocessor is commonly used as a HTML preprocessor as well as a rexx preprocessor however there is no reason why this one preprocessor can't handle almost any file you have around (example you can change preprocessor to use "!if" etc and leave "#if" commands alone if you wish. You may wish to have a look at my HTML/IPF document creation example. This method was used to create both the HTML and IPF versions of the documentation you are now viewing. Most people would probably find the #include and #define commands the most useful as they could be used to ensure that you need never specify something more than once. For example you might refer to a specific link (or image) in tens of places in different html pages but you can define it in one place. When you need to change it you make the one change and regenerate the html. Its not just easier and fast, it eliminates mistakes. You could set up your source and have automatic checking of the existance of any resources on your web page (no incorrect links). The "#if" support is much more powerful than that of any other preprocessor due to the fact that what it executes is rexx code, what this means is that any rexx expression can be called including your own rexx procedures. The "#evaluate" command allows you to parse files or do whatever you need to to obtain the text you wish to use in your HTML. You can use this program to produce different versions of your html pages for different locations. For example for an offline copy you may not want to have links to internet sites or have different links. The preprocessor could be used in conjunction with a HTML editor however it is most useful for power users. You may wish to check out "http://www.yoursite.co.uk/os/2/webwriter/" as this beta tool has specific support for this preprocessor. This tool can be used to automatically calculate image widths and heights, file sizes or file dates and times and basically do all the drudge work (the stuff most likely to otherwise quickly become out of date). By default excess leading spaces are removed from the output file so that you can format the input as much as you like without impacting download speed. If you can't explain why an error message is being displayed or your code is not generated as you'd expect then I highly recommend you try the "/debug" command line switch. I'd also like the debug output if you report problems. If you have used a previous version of the preprocessor then I'd recommended you examine the change history section to determine what changes might effect you. Please see my web page at http://www.labyrinth.net.au/~dbareis/ppwizard.htm for the latest copy of this program or contact me (Dennis Bareis) via email (dbareis@labyrinth.net.au). I value feedback from users. If the examples in this INF version of the documentation don't look correct (fonts overlap etc) then you have removed "Courier 8' font from your operating system. Please restore it... Note that I would have loved to have written this in Java, however as a compiled language it does not have an "interpret" instruction. Apparently something is being added to version 1.2 which might allow something similar, I'll have a look then. The "interpret" instruction is important as it allows the preprocessor to be extended as well as doing a lot of work I'd otherwise need to do myself (and I wouldn't do it as well). I will not be rewriting the preprocessor in Java (as it wouldn't be compatible with the rexx version), but with any luck I'd be able to write any similar future stuff in Java.... ═══ 1.1. Operating System Status ═══ Operating System Status I have ported this program to work with the free Regina interpreter (available at "http://www.lightlink.com/hessling"). Do not try to use versions prior to 0.08f. This program was originally written for native OS/2 rexx and this is where most of my testing occurs. My release procedure ensures that when I package up PPWIZARD, it passes the more stingent regina syntax checking and that a small test run generates the same code under OS/2 and Regina. Every so often I test the generation of my web pages under NT and do some other testing under Linux. If you use this program under other operating systems and it fails (or works) then please let me know. If it fails then I will try to resolve it if you are prepared to help (supply info & test). When reporting problems please run the preprocessor with the "/debug" flag and give the the command line used, the redirected output and the source file(s). Your Source I have made the preprocessor cross platform. This does not mean that your source will correctly build the output on another platform. There are issues that you will need to take care of to ensure that your code is cross platform also! As an example of a mistake you could easily have made, you could have used the OS/2 "filespec()" routine instead of the PPWIZARD "_filespec" call. Status Under OS/2 Works like a champ! Regina - All Operating Systems Some things that are currently disabled are: /FILTERINPUT /FILTEROUTPUT #MacroSpace Some other situations not fully supported yet: No colors used by default (except under OS/2). You could try "/Color" but it may not work. You should not use #UnDef on versions of regina prior to "0.08f". Status Under Windows NT No known issues. Status Under Windows 98 People are happily using it under Windows 98. I believe the Windows 98 has the same 3 or 4 year old bug with its command processor as Windows 95. Status Under Windows 95 PPWIZARD under Windows 95 works exactly like the DOS version. It appears that a bug in Windows 95 (thanks Microsoft!) might prevent you getting the return code and so automatically determining if everything worked or not. Status Under Windows 3.1 Use DOS version. Status Under DOS My own web site is reasonably complex and the DOS (DPMI) version has successfully compiled it. Had to increase DMPI memory to do my whole site in one hit (*.IT), if you have a similar problem just call PPWIZARD many times (maybe processing " A*.IT B*.IT ... K*.IT" in one go and the rest the next. You get the idea! An even simpler method would be to use dependancies (/DependsOn), this way if you run out of memory, you simply restart the build and it will pick up from where it left off. Status Under Unix All command line switches should be specified using '-' and not '/'. All my testing has been performed on Red Hat Linux 5.1 and 5.2 (using it's default "bash" shell as well as "csh"). You will need to obtain the Regina source code and compile it. All testing used the generated "rexx" program. The source can be obtained from my http://www.labyrinth.net.au/~dbareis/regina.htm. Note that temporary files are put into the directory identified by the "TMP" environment variable, you must have write access to this. If the environment variable does not exist then files are placed into the "/tmp" directory. As with all operating systems I am keen to fix any problems, unix is a bigger unknown to me with all it's different shells etc. If you have a problem, please use the "-debug" command line switch and redirect the commands output, along with the name of the shell you are using and any other relevant details. I will typically have a fix for you in a few days and maybe a workaround even faster. Other Operating Systems If regina works on your operating system but your operating system is not listed above then contact me. If you are prepared to help (test changes etc) then I will try to get it to work for you. ═══ 1.2. Change History ═══ Change History I'm getting quite a bit of feedback now but most simply tells me how happy you all are. While I do lap it all up, I would like more suggestions or bug reports. I don't care how small a bug is (incorrect spelling, incorrectly formatted or difficult to understand error messages). My aim for PPWIZARD to to be very flexible and to work the way you do. If you have to work hard to get PPWIZARD to do what you want then I'd like to know. Most of the changes I have made are due to the fact that as a heavy user of PPWIZARD myself I find situations where PPWIZARD could be modified to make my life easier. Other changes have come about because people have asked me how to do something and I've decided I can make life simpler for everyone! I have a very long list of possible enhancements, your feedback can ensure that something you would like goes to the top of the list! In some cases people have told me what they were doing, this allows me to think about a specific set of circumstances (rather than all possible theoretical ones). After thinking about things a bit I have frequently enhanced PPWIZARD before I was asked (that is I have anticipated my user's requirements). Sometimes I also know something I've done is not perfect, but am waiting for users to indicate a problem area before 'correcting'. 1. Version "Next Release" You tell me, feedback please! Have you ever looked at a product and said "Wouldn't it be nice if ...", well get on your backside and send an email, make it so! Note that if you require any of the changes mentioned here for the next release then email me and I will either send you a copy or speed up its release. Also if you disagree with a change then tell me why, I can then think about implementing a feature which will do what you want in a better manner (or in worst case senario say "oops" and reverse the change). Your idea here :-). 2. Version 99.329 PPWIZARD now supports Positional Parameters, these remove the need to "name" parameters. I have worked out a workaround to regina's annoying "clause length" feature. This has also prompted me to work out a better way of handling rexx code generation (when used as a rexx code preprocessor). If you define your rexx code with #DefineRexx you will never get the clause length message unless an individual line is greater than the "maximum clause length" (1,024 characters in regina interpreters ppwizard supports). Not only that but any rexx code you generate will also not cause clause length problems. Note that regina incorrectly calls a line a clause. New line continuation code for separate with newline, new default code is "%\" (I should never have used the down arrow...). Using the old code will work for now but generate a warning. At some future stage this support will be removed. PPWCURL.CMD improved to handle "SSL" links ("https://"). The "{$Parm-}" format no longer exists, it is probably rarely used, if required however (extremely unlikely) you can use the new "$$IGNORE" parameter command. Some debug mode changes which hopefully make it easier to work through. 3. Version 99.324 Updated '{$?}', can now specify '$$' commands in which case they are applied to each parameter (and they are not in pass through format). When defining your own '$$' commands you can now determine the source of the value (macro or parameter name). Updated directory creation code, under regina we can tell if a directory exists, so now only create when required. New ProcessNext() routine. New ReplaceMacros() routine. New /DebugTime switch. The "BIN2PPW.CMD" updated to work within regina's tight restrictions. Updated HtmlPre.IH & OL_DOC.DH so that the right angle bracket is now converted to the html code. Updated error messages when a macro expansion fails, the macro being expanded is now reported. Try to show macro expanded lines where possible. If compound rexx variable unknown then known "components" are now always dumped. Some lists and other items would not show up correctly under Internet Explorer, hopefully all occurances have now been fixed. There could be some glitches in the documentation, if you notice problems please report them... 4. Version 99.317 New '$$' command of '$$SPCPLUS'. Adds space before item if its non empty. If executing #DefineRexx code immediately then macro parameters are always replaced. New MacroSet() & MacroGet() routines, the later replaces any "GetMacro()" calls which will be removed in a later release. Updated OL_DOC.DH so that it should now work under regina. Updated NestChk.H to perform more validation of IDs and created new macro for easy definition of HTML tags you want to verify the nesting of. 5. Version 99.313 Fixed bug in '{$?}', would not always work unless in debug mode! New "#option" of CsReplacement. By default ppwizard Macros and their parameters are case insensitive. Updated OL_DOC.DH so that headings can contain single quotes. Also added new as yet undocumented "SimpleList" list type to match IPF "sl" and "esl" tags. New BulkChangePrepare() routine. New "" variable which simply tells you if debug is on or off. The new IsDebugOn() call tells you similar information. New "user" DebugLevel states that you can use for your own purposes. New Debug() and DebugIndent() calls. 6. Version 99.310 The '$$' commands introduced last release now also apply to Standard Definitions, allowing standard variables as well as rexx variables to be easily handled. The #{ loops can now be used in a macro. Prior to this it would only work if read from file. The #DefineRexx command can now immediately execute rexx code (no need to save as macro contents). Document that AddInputFileToDependancyList() and AddOutputFileToDependancyList() can now be used. Updated OL_DOC.DH so that it no longer generates java navigation (wasn't reliable). Removed a number of files from main download, now available separately. 7. Version 99.304 New macro and macro parameter replacement options, you can perform translations on whole macro values or on individual parameter values. Tell me if you can think of any other common transformations you would like to be able to do. New macro replacement option, you can now use '{$?}' to generate "unused" parameters. This will be a very handy feature and allows you to create better macros as replacements to existing HTML tags. Some rare very early errors were not being correctly reported as they would cause ppwizard to trap. 8. Version 99.299 Updated the #RexxVar command to create better "PUSH" and "POP" commands (old format still supported). Updated FTPLIKE.IH header so that it can handle filenames and directories that contain single quotes. 9. Version 99.289 There are now some special alternatives to the normal method of macro replacement. Valueless parameters starting with '$$' are now special cases and represent instructions to PPWIZARD. Updated OL_DOC.DH header, main change is validation of links to ensure that the destination heading exists. Updated it's documentation and fixed some faulty links. Modified GetImageHeightWidth() so that it now dies on failure instead of generating warnings. The FTPLIKE.IH header was updated. Added new WPS URL to HTML example. Input (only) dependencies are now converted to upper case on case insensitive operating systems so that we don't store information for the same file more than once. Dependency file has a new format. The #DependsOn command has been enhanced so that you can "stamp" commands or files matching masks. Regina 08h allows better reporting on syntax traps, improved trap handler to take advantage of this change. 10. Version 99.281 New Summary() routine to allow you to add (or remove) details on the displayed summaries. Updated VALRURL.H to remove "name expected" trap when used under regina. Updated default whitespace to include EOF (26 decimal) as different versions of regina seem to handle it correctly, then not! Work around to stream('STATE') & stream('DESCRIPTION') bug in regina 08h beta. Improved text of some error messages. 11. Version 99.276 Fixed bug in handling of macro parameters which did not have a value (new feature in 99.225). PPWIZARD would fail if the parameter was the last supplied (and there was no spaces after it). The SortArray() routine has been updated so you can decide whether or not compares are strict. The default is that they are not, strict compares are best for text, numbers however will not correctly sort this way. Spelling dictionaries are now put into dependency file if required. Improved way ppwizard fails if user makes certain mistakes with the name of an included file (such as empty name), rexx used to spit the dummy. New FAQ section in doco. The HTML generator tags now go in no matter the case of the user html tags. It now also handles a body tag with parameters. Finally managed to generate a very small test case to demonstrate the 08g "stream('query exists')" bug and sent it to Mark Hessling, he has fixed the problem for the next release. We have also confirmed that this bug has been around for a while. While ppwizard (in my setup) would only fail on 08g, my testcase fails on all regina versions I have access to. For this reason I have decided to support 08g and remove the warning. 12. Version 99.269 Had to restore an old workaround to a regina bug (removed in 99.225). I'd thought it had been fixed (looks like only partially fixed). Quite a few header files updated to correct this. If you had trouble retrieving variables after you'd created them (ppwizard would trap - variable not found) then you were probably bitten by this bug. The default is now to see each spelling error (for a word) once per build, you can use the new /SpellShowAll switch to indicate that you'd like to see each error. You can now modify the spelling delimiters from within a dictionary. 13. Version 99.268 Updated #import command so that closing column tags are now generated by default. These are optional but some browsers such as Netscape may not work correctly in all circumstances when they are missing. There are now options which allow the easy definition of text which goes before and after record data (say to change fonts within a cell). When generating rexx code (/Rexx used) the syntax of the generated code is now checked in all cases. With regina the generated code had previously not been checked. We now have a basic spell checker, its not perfect and will probably change in future (maybe based on user feedback), but its a good start. It tries to avoid HTML tags and so does not yet handle "ALT" text etc. There are 2 basic modes (you can use both together) as follows: - You can indicate words that you frequently get wrong and ppwizard will tell you when you use the word. - You can supply a list of "good" words (dictionaries) and ppwizard will tell you if you use a word which is not in a dictionary. There are new switches of /SpellCheck and /SpellAddWord. A new option of AllowSpell gives you control over which parts of the output you wish to spell check. Note that currently ppwizard only reports a spelling related error for a word once per ppwizard invocation not once (or many) per individual build (as it probably should). HtmlPre.IH & OL_DOC.DH updated so spell checking on examples is optional (default state controlled by user). The "/DependsOnPpw" switch no longer exists, see the new "/DependsOnComplete" switch. PPWCURL.CMD improved. New switches allow timed out URLs to be retried and for you to specify if moved URLs are OK or not (for each one). Memory file can be backed up to 'x' levels. The default handling of the FTPLIKE.IH header should now handle spaces in filenames better. If you have any problems please let me know! Updated "PPWSORT.H" so default method of sorting is not strict (">>") as this incorrectly sorts numeric values. Better debug output. You may need to modify your source, see following issues: a. Updated #import command so that the option "?_BLANK_COLUMN#" now has a underscore before the field number to be consistant with all other options which refer to column #. b. If you use "DecodeUrl()" or "EncodeUrl()" see doco for UrlDecode() & UrlEncode(). 14. Version 99.261 Windows (at least NT) appears to have a bug/feature in its handling of the "dir" command which caused ppwizard to report that no files were found when /ScanSubDir used and maybe other times. I've worked around this bug. This would probably have affected the use of the FTPLIKE.IH header and maybe others. The way PPWCURL.CMD is invoked has changed, most environment variables have disappeared, replaced by command line switches. Can now test URLs extracted straight from HTML pages. The program is much improved in many other ways. PPWCURL.CMD will now run under Windows using the windows version of RxSock (although there is no support for FTP checking under windows). Apparently there is a linux version of RxSock with object rexx this may or may not work with regina, please tell me if you try it! 15. Version 99.252 The /Output and /DependsOn switches can now generate their output in a completely separate directory tree (when /ScanSubDir used). New "" and "" variables. Updated OL_DOC.DH, main change allows you to specify "targets" on links (section within a html page). Can also save/restore heading levels. Documented fact that PPWCURL.CMD can be used to check WPS URL objects (created by Netscape etc). Also minor improvements to program. Assorted performance enhancements. Started documenting the tags and options of OL_DOC.DH. A few names modified. 16. Version 99.234 Updated #OneLine command so it will correctly handle ppwizard commands embedded within a #define (a macro which executes ppwizard commands). Updated VALRURL.H and PPWCURL.CMD so that it will now tell you in which html file(s) the failing URL occurs. Assorted other improvements. New InputComponentLevel() and InputComponentLineLevel() routines. 17. Version 99.230 I've set up an email based PPWIZARD discussion group (using "list bot"). Join up at http://www.labyrinth.net.au/~dbareis/ppwizard.htm. Please read the changes to the "Bugs or Suggestions" section. New #OneLine command, hopefully this will please a lot of people (judging by past feedback). The "PPWCURL.CMD" (URL validator) batch file has had some major improvements, the biggest one being able to specify a period of time (in days) after a successful check before another is required (this is major performance improvement). Must have forgotten to document the /HtmlGenerator switch. Wasn't working 100% anyway! Minor change to #import to allow the specification of particular values for each column to replace empty fields (not just "?_BLANK_FIELD" - which still exists). 18. Version 99.225 Can now have macro parameters without you having to specify a value (it will be given the value of the parameter name in upper case). Thanks to feedback from "Mads Orbesen Troest" for this one. Removed work around to regina value() bug (to speed up PPWIZARD). This bug is fixed in regina 0.08f onwards (the only version that PPWIZARD now supports - see next item!). Found bug in regina 0.08g (latest available), do NOT use this version, I have reported the problem and am providing as much detail as possible so hopefully the next version will be OK. A debug message and warning message will be generated if PPWIZARD does not "approve" of the version of regina you are using. Updated "VALRURL.H" to not do http/ftp support checking if URL checking is not immediate. 19. Version "99.220 The #DefineRexx command now honours the AllowPack setting. The SortArray() routine is now much faster. Note that the routine now "correctly" uses strict compares, this may have caused "funny" sorts if you had leading/trailing whitespace. You may need to modify your source, see following issues: a. Updated "PPWSORT.H". Added some easy to use macros for 1 and 2 array sorts. New much faster code is generated, see doco about changes to variable names. 20. Version "99.215 New #DefineRexx command which simplifies the definition of rexx code (for example line continuation characters are no longer required). 21. Version 99.150 New "PPWSORT.H" header. This allows you to define how the sorting is done as well as sort more than one array (keep associated info together). Updated "VALRURL.H" support. 22. Version 99.148 New Info() routine to match #info command. Updated "VALRURL.H" header file. Now performs immediate checking of URLs at end of each successful build or can batch URL's for later validation, or you can define your own URL handler. You may need to modify your source, see following issues: a. "BubbleSort()" renamed to "SortArray()". b. "ReverseIt()" renamed to "ReverseArray()". 23. Version 99.145 New "VALRURL.H" header file which allows validation of remote http and ftp URLs. I am very interested in feedback on this feature. Updated FTPLIKE.IH. New "DieIfIoErrorOccurred()" routine which can be called any time prior to the closing of a stream to see if any input or output errors have occurred. Updated "GetEnv()", it now takes an optional parameter telling it to die if the env var does not exist. Removed "/CheckImage" & "/CheckHref" validation switches as they did not handle all cases, did not do a really good job of checking, there are better ways of doing it anyway (see the Resource Validation - Local section for more details) and user feedback seems to imply its a rarely used feature. I will probably come up with a new header file and framework for the validation of local files (and maybe remote as well) in a future release. New "GenerateFileName()" routine which allows you to create filenames from masks exactly like switches such as /Output do. 24. Version 99.135 Assorted linux improvements. Updated FTPLIKE.IH so it can handle directories in operating systems other than OS/2. It now works well under linux. Updated NestChk.H to work around bug in regina. Note that under regina 0.08e you will get a "clause" error, please change to "0.08f". Updated _SysFileTree() to handle directories. Basically also clean up some other "strange" stuff. #import would fail if you used some import types such as ",,," and your "TMP" or "TEMP" environment variable pointed to a drive without long filename support (PPWIZARD would trap). If "TMP" or "TEMP" pointed to a root directory (such as in "E:\") then PPWIZARD would trap. A terminating slash on other directories was OK! Now when a trap occurs variables from nearby lines are dumped to help in problem diagnosis. 25. Version 99.131 In some unusual situations where a file that ppwizard had to locate is read directly from file it could get confused. Under OS/2 this would correctly trap, due to a regina bug/feature it will cause an infinite loop. Summary information improved. 26. Version 99.120 The way a file is included has been rewritten. A file may now either be read directly from the file or via a memory cache. Reading from cache will improve performance if the file resides on slow media (if it needs to be re-read). If a recursive #include is detected (this is now allowed) then read from cache is forced, there is no more need for a file copy workaround. A /Inc2Cache switch allows you to override the default read method (file/cache) chosen by PPWIZARD. Improved CompareReplaceFixed() routine so that it can also be used as a compare function. No bugs reported or seen however I think in some situations #import could have caused some weird looping or other bugs. 27. Version 99.115 New "#OnExit" command. Added new _filespec types. New parameter on GetIdPrepare() call improves functionality in some circumstances. New ExpandXCodes() call. New "PUSHPOPM.H" header file which allows you to easily save/restore macro values. Updated "FTPLIKE.IH" as well as NestChk.H and OL_DOC.DH headers. Better validation on "#include" and "#output" commands. Now only generate warning if no lines generated. 28. Version 99.110 New "FTPLIKE.IH" header file which allows you to create simple FTP like listings with ".DIZ" file support. The DIZ file can contain HTML tags. Fixed bug in "#{" type loops where #if nesting level could get confused if loops were "nested". Possibly other effects. 29. Version 99.106 Improved CompareReplaceFixed() routine. Now added infinite loop detection (can be turned off) for expansion of macros. 30. Version 99.100 New "#option" of AtChangeType to allow variations on the "normal" case sensitive #AutoTag or #AsIs changes. If you have some fantastic free PURE REXX search and replace code then I can include it as a new PPWIZARD extension if you send me the code! New "#option" of ExpandX to provide more control over when codes get expanded. New ReplaceStringCI() routine to perform case insensitive search and replaces. New CompareReplaceFixed() routine to perform complex "fixed" type compare and replace operations. New "" variable. New TEXTEDIT with PPWIZARD and SHARING HEADERS - HTML + REXX CGI examples. 31. Version 99.092 More of a feature (as code functioned...), however the "StartsMacroParm" and similar stuff was not what I was aiming for! You would only have seen this while debugging T2H imports. So problems such as the one above can never reoccur, rather than delay trap handling I now use a "simple" trap handler until PPWIZARD has initialized itself enough to use the normal (much more complex) one. New GetInputFileNameAndLine(), GetFileLineBeingProcessed() & GetLineBeingProcessed() calls so rexx code can keep track of debugging/diagnostic type information. New "NestChk.H" header file which contains macros for generic handling of nesting validation. You could use this to ensure numbers of "TABLE" tags match numbers of "/TABLE" tags etc (rather than hope testing shows this up). Now validate #AutoTagState nesting level. Much more complex import example put into doco. The example reads a comma delimited file (could have been fixed field etc) and generates 3 html files based on the first letter of the surname. 32. Version 99.083 New /WarningsIgnore switch. This allows you to specify one or more individual (expected) messages to ignore. A parameter on the command line can now be surrounded by double quotes if it needs to contain spaces. Updated documentation, particularly the #Import command (more details on internal processing etc). New "Resource Validation - Local" section in documentation. Documented WriteLineToTmpImportFile() routine, must have forgotten to do so in an earlier release. New Error() & Warning() routines (useful in filters etc). Fixed bug which may occur if you had used the ReplacementTags option (rare bug to do with 'x' codes). Summary now includes warning count (if any). You may need to modify your source, see following issues: a. The '\\' line continuation form no longer exists (it was an alias for '-\'). You can use the modified (but backwards compatible) LineContinuation option to allow '\\' if you wish. b. Syntax of #Warning slightly modified. To quickly get yourself going simply add "USER " before your warning text. c. If the defined line continuation character ends a line but it otherwise does not look like a line continuation then the line is no longer treated as continued. In practical terms you now need a space before the '\' character! 33. Version 99.074 Enhanced the #Output command so that the new file does not need to be processed in the same mode as the "current" file. For example while generating rexx code you may wish to generate data files (such as TEXTEDIT scripts) which the rexx program will use as input at runtime. This allows #define variables to be easily shared and gives you the option of wrapping everything up in a single source file. Fixed error message when invalid parameter used on #Output command. Better temporary file name calculation (and handling) under regina. Handling of "stderr" redirection changed so should work on "csh" and similar shells under unix and not just the "bash" shell (not 100% sure this was required as regina seems to use "bash" shell for operating system commands). The "#Import" command can now take "EOF:" in the "Remove" variable to remove to EOF. Updated "#Import" command so that you can now always specify a number of lines to drop and not just if "CMA-" etc used. Whether or not the '-' is used now just determines the default state. New /beep switch for people who don't like beeps on errors (grumpy bunch!). On all operating systems now do "set" command (and capture output) when /debug used. No real reason except may help me in future debugging (help me identify unix shell, version etc). Other minor debug and doco improvements. 34. Version 99.067 When environment variables containing paths are searched the character separating paths is now ':' for unix, for all other operating systems it remains ';'. Similar change for processing of /#Include switch. Minor debug and doco improvements. 35. Version 99.056 In unix now default to lines terminating with a newline (no carriage return). Other operating systems now default to CR + LF even for HTML, to 'pack' this more use the /CRLF switch to turn off carriage returns (HTML browsers don't require them). No switches apart from /CRLF modify the line termination state. New /Exclude switch to allow you to exclude certain files. Now only process a file once even if specified in multiple masks on the same command line. Improved syntax/novalue trap information on user errors in #if, #evaluate commands etc. More debug parameters for AddressCmd(), lots of other little debug changes. 36. Version 99.051 New "#option" of WhiteSpace, under unix this defaults to the EOF (decimal 27) and CR (decimal 13) characters. This allows unix to read PC files without problems. Whitespace after line continuation characters no longer prevents line continuation. Temporary files under unix will no longer go into the root directory if the "TMP" environment variable is not set up, they will go into the "/tmp" directory (I assume this will always be there). The /output and /DependsOn switches now have non-wildcard alternatives as placeholders. Unix has case sensitive filenames, the documentation should now match the correct case of the files. Other minor changes. 37. Version 99.049 Unix fix for directory search bug. 38. Version 99.048 Improved "TRYME.IT" example to demonstrate more features (while hopefully still being fairly easy to understand). If all input files end in ".X" and "/Rexx" (or other mode switch) was not specified then /rexx is invoked anyway. Now have a /html switch. After looking everywhere else for a file PPWIZARD now also checks the directory it is executing from. Removed "OL_DOC.DH" from document and now bundle together with PPWIZARD. Minor change to generated rexx header. 39. Version 99.044 New "HtmlPre.IH" header file to make it easier for people to start using PPWIZARD to include example code into a html page. Many enhancements to ML importing, other import types have also had relatively small changes. New "Dropped" array during import so you can access fields that are not directly displayed. This would allow you to create combined fields etc. Fix to /DependsOn when /Template also used. Minor change to way REXXTRACE define is accessed for tracing rexx code. Improved use of "interactive mode" rexx debugging. 40. Version 99.038 Fixed "#Import" bug where fields could not be reordered with '{2}' etc. New "#Import" type ML, this allows you to create a text database in an easy to manage format. Some people are already using WRAP imports to handle similar formatted text databases. 41. Version 99.034 Optimised #AsIs text changes so that it will work much better for large numbers of single character replacements such as would be required to convert international characters for correct display in a html browser. New BulkChar2String() routine. The /output and /DependsOn switches now have a new special character of '?' (allows specification of paths relative to the input file). Worked out a faster workaround to a regina bug, this should speed up PPWIZARD when the regina interpreter is used. Major update to the "rexx" section of the manual. Minor improvement to rexx packing. Minor change to generator header. Minor cleanups for rexx tracing. 42. Version 99.030 Oops, wildcards were not expanding correctly under regina. New SortArray() and ReverseArray() "array" routines. If you were having trouble with the /DependsOn switch then you are probably using regina version 0.08e. It has a bug in the "parse" command which can generate spaces. I have added a workaround but it would be safer to move to a newer version. 43. Version 99.027 Document fact that delimited and fixed imports can be setup so that the format for each record (row of table) can vary depending on the data. This documents a new variable that can be used in a filter. Enhanced looping so that it can contain "#include" or "#import" commands. New DebugLevel option of REXXTRACE for debugging any rexx that you might be executing. Removed "RestrictKey" routine, this functionality can be achieved through the new "GetId" routine. Also see the new "SetId" routine. This is a much more powerful mechanism which "OL_DOC.DH" now uses. New "" variable. Minor debug improvements. 44. Version 99.023 New AsIs() and AsIsPrepare() routines. New AutoTag() routine. New QuoteIt() routine. 45. Version 99.020 Changed syntax and way "#AsIs" command works so that it is now much more flexible. If you have used the "#AsIs" command you will need to make minor changes. Sorry but I never liked the way it was before... Too limiting. Changed "#AsIs" mode so that when turned off it restores the state of the options to the state that existed just before the "as is" mode was turned on. More "#Import" changes/options. You can now filter records in the T2H mode. Largish changes to WRAP import. You can now easily disable or extend on the "standard" #AsIs replacements that occur during import (chars like '<' and the box chars). New "" & definitions. New "ToLowerCase" routine. New "rexx" section in the manual. Improved summary information. 46. Version 99.014 More "#Import" changes. Default is now to "PROTECT" delimited and fixed imported data. More configurable parameters in T2H import. "T2H" import now finds and by default tags email addresses. Parm 2 of #AutoTag command now can now include "{$AT}" to refer to the before (automatically tagged) text. This can save a lot of retyping. 47. Version 99.009 Fix looping problem on loops other than the first. Improved "#Import" type T2H, this affects you if you used "_LINK" definitions. Modified "#Import" type WRAP, to work better under regina (OS/2 seems to have better garbage collection). No longer delete temporary files during #Import command if debug mode is on. Modified "#option" command so push and pop commands can be combined with setting options. Added an example of importing using SQL. I correct some code which may not have correctly handled a line with all blanks (when writing to output file). Note that you can now tell PPWIZARD exactly what characters to translate during the #Import command. For example if your text includes internation characters such as umlauts you could convert them to the html symbols so that they display correctly. 48. Version 99.006 Improved documentation. Fixed major problems with "#Import" type T2H. 49. Version 99.005 PPWIZARD looping is now possible. Requested by Chris Wenham. Note that you have always been able to do loops in rexx (#evaluate). New "#Import" type T2H. This is basically a TEXT to HTML conversion mode. It is reasonably configurable (and will get more so). You can determine look and feel and whether "http:" links are made links or not, plus more. Use /Debug to make up for lack of doco for now - everything can be turn off or changed for example you can turn off creation of links and can change mode from "PRE" to blank line indicates end of paragraph. If you know of common examples of text then maybe we can get much smarter. Basically feedback required. Now when in HTML mode (the default), if no input files were specified PPWIZARD will look for "DEFAULT.IT". Requested by Chris Wenham. New "" variable. Feedback from Chris Wenham. New "", "", "", "" and "" variables. 50. Version 99.001 Fix some minor documentation issues. Generator meta tagging added when generating html. I have still kept the history for previous releases (as far back as 98.044), so if you wish I could send it to you, however if you are interested in stuff this far back take my word for it you are better off with the current release! ═══ 1.3. FAQ ═══ PPWIZARD FAQ The following (currently short list) of questions are answered: 1. Can ppwizard accept options from a configuration file? Currently I have some very long command lines and its hard to swap between frequently used configurations. 2. I have a perfectly working series of lines that I wish to place into a macro. The macro takes one or more parameters so that I can generate many versions of the output. I use the example tags, #AsIs" or #AutoTag" commands but these don't seem to be working correctly. What am I doing wrong? ═══ 1.3.1. QUESTION #1 - Does PPWIZARD support config files? ═══ QUESTION #1 Can ppwizard accept options from a configuration file? Currently I have some very long command lines and its hard to swap between frequently used configurations. ANSWER There is no need for a separate file as ppwizard can accept anything the command line can accept from environment variables. In most operating systems you can either put your options in "config.sys" or in a batch file that you run for your project. That is, the facility is there, it is just supplied in a different way. You can create a whole range of different common options and select from them as you wish, hopefully the following example demonstates the method: @echo off REM *** YOU MIGHT WISH TO SET THIS IN CONFIG.SYS ETC ******* SET PPWIZARD_OPTIONS=/beep /color:n REM *** NOW SET SOME OTHER STUFF **** SET PPWDEBUG=/debug /option:DebugLevel{x3D}"-ALL" SET STUPID=/DependsOn:out\*.DEP SET OTHERS=/GetEnv:Stupid REM *** START PPWIZARD *** if "%1" == "" ppwizard *.IT /GetEnv:OTHERS if not "%1" == "" ppwizard %1.IT /GetEnv:OTHERS REM *** IF I'd wanted debug *** goto Endbatch if "%1" == "" ppwizard *.IT /GetEnv:PPWDEBUG /GetEnv:OTHERS if not "%1" == "" ppwizard %1.IT /GetEnv:PPWDEBUG /GetEnv:OTHERS :Endbatch ═══ 1.3.2. QUESTION #2 - My macros are not generating output correctly? ═══ QUESTION #2 I have a perfectly working series of lines that I wish to place into a macro. The macro takes one or more parameters so that I can generate many versions of the output. I use the example tags, #AsIs" or #AutoTag" commands but these don't seem to be working correctly. What am I doing wrong? ANSWER The #AsIs and #AutoTag commands only work on data read directly from the a file. This means that you may need to use a bit of trial and error (maybe swearing a bit) and you can get it to work. What is probably easier is rather than creating a macro, put the information into its own header file, then instead of macro parameters you simply #define+ each "parameter" prior to each #include command. ═══ 1.4. Bugs, Problems or Suggestions ═══ Before asking questions, I would appreciate it if you'd ensure that your answer was not in the FAQ or the this manual! Requested Information - Bugs or Problems If reporting bugs/problems please supply: 1. A detailed description of the problem. Please don't bother wasting your and my time by telling me "it did not work". 2. All files involved (input, output and any batch files used to run the preprocessor). You have hopefully trimmed out everything which is not required by me to recreate the problem. 3. When supplying the redirected output from PPWIZARD please ensure that you had used /DEBUG on the command line to turn on debug mode. The easier you make it for me the faster I will be able to come up with a fix or tell you what your doing wrong etc. Reporting Bugs/Problems or Suggestions There are two main ways to report PPWIZARD issues or ask questions, they are: 1. PPWIZARD Discussion List People who are very interested in PPWIZARD can now join an email based discussion group, any email sent to ppwizard@listbot.com will be seen by all subscribers. Hopefully I won't have to answer them all, but if one person answers, everyone gets the benefit of the response. All messages are archived so you can always go back and see previous messages. I will also make announcements on this list. If you think the problem might be a ppwizard or regina bug (which you think others probably haven't encountered) you may wish to contact me directly as others may not be interested (we don't want too many messages). Please don't attach large files to emails sent to this address (there is a 100K limit as well anyway). We'll have to see how it goes, hopefully it does not need to become moderated (I probably haven't got time for that!). 2. Authors Email Address I will take feedback in this manner but in general prefer the email list mentioned above. Exceptions might be where you have large attachments, you don't think anyone else would be interested, you don't want to join the group (why not?) or you really want to hammer me! If you must email me directly then send it to dbareis@labyrinth.net.au. If I think its appropriate I will "CC" the above discussion group with my response. Please zip attachments, this reduces the size of the email and ensures that the information gets here uncorrupted. Known Bugs or Problems The following bugs are ppwizard bugs: 1. None Known The following bugs may occur when using the native interpreters under OS/2: 1. None Known The following bugs may occur under any operating system using regina (I will assume on "one of my recommended versions only"): 1. The debug time will be plus or minus a second (this can produce negative times etc). 2. Regina has a number of 'query exists' bugs, the one that might affect you is if you specify an input file such as "C:\CONFIG.SYS" and PPWIZARD tells you it can't open the "CONFIG.SYS" file in a completely different directory! Another one is where "garbage" might appear after a filename. ═══ 1.5. Disclaimer ═══ Disclaimer I believe it is very unlikely that ppwizard or regina will cause damage to your system however I feel that it is wise to advise you of steps you can take if your data is highly critical. I wish to stress that you take full responsibility for ensuring that PPWIZARD (or any other software related to PPWIZARD) is suitable for use in your intended environment. PPWIZARD is supplied "as is" and may contain bugs. It is just impossible to test software (or even information) in all environments as there are just too many possibilities. For this reason you should test any software/information yourself for suitability before using in production or placing onto machines containing important information. By doing this you will have helped ensure that there are no unintended drastic side effects. Prior to testing it is recommended that a full backup of your hard disk be performed. Updating from Older Versions While I will try to keep PPWIZARD backwards compatible with older versions, I will at times (intentionally or not) change it in such a way as to require you to make changes to your source (batch files, code etc) if you wish to upgrade to the newer version of PPWIZARD. It is recommended that you backup your source AND the older versions of my programs before trying a newer version. LINKS Any links I mention are provided "as is", it is up to you to determine the quality of any site I link to or any software I mention... ═══ 2. PPWIZARD.CMD Command Line ═══ PPWIZARD.CMD Command Line PPWIZARD[.CMD] InputMask1 [Options[:parms]] The "InputMask1" can be the name of a single file or a filemask containing the normal wildcard characters "?" & "*". You may specify more than one file or mask and they may appear anywhere on the line however none are processed until after all options). Each source file may include other files such as common header files with your standard definitions. If all input files end in the extension ".X" then the default processing mode is /rexx (normally /html). Options All Options begin with '/' unless running under UNIX where '-' is used instead. Options in the optional environment variable "PPWIZARD_OPTIONS" are processed before any specified on the command line. Normally files or options are separated by spaces, if the file or option needs to contain spaces then you can surround it by double quotes. If you use double quotes the quoted value must not contain double quotes (encode with "{x22}" - see below). Commonly used options: 1. /CrLf 2. /Debug 3. /DependsOn 4. /Rexx 5. /Pack 6. /Output Validation options: 1. /WarningsIgnore 2. /WarningsOk 3. /SpellCheck 4. /SpellAddWord 5. /SpellShowAll Less commonly used options: 1. /Option 2. /Define 3. /DebugTime 4. /Template 5. /GetEnv 6. /Exclude 7. /Inc2Cache 8. /CGI 9. /DependsOnComplete 10. /FileNames 11. /#Include 12. /Other 13. /Tabs 14. /**/ 15. /FilterInput 16. /FilterOutput 17. /ScanSubDir 18. /Color 19. /Beep 20. /Info 21. /Sleep 22. /Html 23. /HtmlGenerator Note that if you know the ASCII code of a character (in hex) you can encode it, for example "{x20}" represents a space. If a code looks invalid then it is ignored. The following are codes for some of the more difficult command line characters you are likely to need: {x20} - Space {x22} - " {x3C} - < {x3D} - = {x3E} - > {x7C} - | {x26} - & {x5B} - [ {x5D} - ] {x7B} - { {x7D} - } LONG COMMAND LINES / CONFIGURATION FILES Note that PPWIZARD does not support a separate configuration file. It does not need one, you can use the /GetEnv switch to obtain the same effect. RETURN CODES A return code of 0 indicates success. A return code of 1 indicates success (with warnings) and /WarningsOk was not used to turn them off. Any other value indicates an error occurred. EXAMPLE This example has the following attributes: 1. Make file functionality without the hassle. 2. All source files have an extension of ".IT" (headers use ".IH"). 3. All output to have the extension ".html" and go into the "OUT" directory. +-[ MAKEIT.CMD ]----------------------------------------------------+ | @echo off | | md OUT >nul 2>&1 | | md OUT\DEPEND >nul 2>&1 | | ppwizard.cmd %1.IT /Output:OUT\*.html /DependsOn:OUT\DEPEND\*.DEP | | if errorlevel 1 echo ERROR: Command failed! | +-------------------------------------------------------------------+ Example - Redirection Ppwizard (or any other program) can at times generate quite a lot of output. When /Debug is used you will definitely wish to "redirect" the output into a file, the following is an example which would work in virtually all operating systems (including linux bash shell - change switch characters to '-'!): ppwizard.cmd index.it /Output:OUT\*.htm /Debug > OUT\output.TXT 2>&1 If the redirection example does not work you will need to read the documentation for the operating system you are using to determine the correct method. ═══ 2.1. /Beep ═══ Switch /Beep[:YesOrNo] This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. You can determine if beeps occur in some situations such as ppwizard detecting errors. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise one of the following values is expected: Y N YES NO ═══ 2.2. /CGI ═══ Switch /CGI:LogFile This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. This command changes the way PPWIZARD works to allow it to be used as a web server based CGI program (or part of a bigger CGI process). The output goes to stdout and what would normally go to stdout is prevented from going there. If the optional "LogFile" is not specified then all status, debug and error output is dropped. If you need to see this you would specify the name of a file. If the filename includes "?" then a "random" 8.3 filename (no path) is chosen and replaces the "?". If the ppwizard output is not part of a larger process then you may want to make use of the "" variable. Being a CGI script (or part of one) you would want your code to be as fast as possible, I highly recommend you read the "performance" documentation. CGI OPTIONS You may /define, #define or #evaluate the following variables to control the output which occurs in the case of a fatal error (the default is to display the information): CGI_FATAL_MY_MESSAGE_ONLY Define this variable if you don't want any details of the message to be displayed in the HTML output. Leave this variable empty so as not to indicate an error (other than truncated output!) or supply the HTML codes and text you wish displayed. CGI_FATAL_HEADER This variable controls the HTML codes that are sent to stdout before the lines that contain the details of the error. It is recommended that these codes include "
" or similar to retain the line formatting on error lines. CGI_FATAL_TRAILER This variable controls the HTML codes that are sent to stdout after the lines that contain the details of the error. The codes will usually reverse those you specified for use before the error details. Example The following examples show the options being specified on the command line, it is probably better to have any common options specified in CONFIG.SYS on the web server. ppwizard.cmd EmailForm.TEM /CrLf /CGI ppwizard.cmd EmailForm.TEM /CrLf /CGI:LOGS\LAST.LOG ppwizard.cmd EmailForm.TEM /CrLf /CGI:LOGS\? ═══ 2.3. /Color ═══ Switch /Color[:YesOrNo] This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. You can determine if colors are used in displayed output. Useful if redirecting output to log files (or you just hate colors!). If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise one of the following values is expected: Y N YES NO For colors to work the session must support ANSI color strings. OS/2 does this by default. NT does not seem to. ═══ 2.4. /CrLf ═══ Switch /CrLf[:YesOrNo] This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. This switch can be used to vary the line termination characters. These are initialized to newline on unix and carriage return plus linefeed elsewhere. You can "compress" html on OS/2 and Windows systems a bit more by removing the carriage return as html browsers don't need them, this way you'd save one byte per line. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise one of the following values is expected: Y N YES NO ═══ 2.5. /Debug ═══ Switch /Debug This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. This option can be useful in determining what is going wrong when you don't get the output you expected. The output is fairly easy to understand and aims to actually teach (or help you to understand) certain commands (such as #import). To get the maximum output use the switch as early as possible on the command line, if you are getting too much output, there are many filtering options (see the DebugLevel option). If you wish to report a problem with ppwizard then please use this switch and send the output along with any other details. Note that if this command line switch is used you can no longer turn debug mode on and off with the #debug command. The following switches are also simulated: /INFO ═══ 2.6. /DebugTime ═══ Switch /DebugTime[:NoOrFormat] This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. By default ppwizard outputs the elapsed time (short display format) at the start of any debug line it outputs. This option allows you to select a longer format (HH:MM:SS.99) or turn off time generation altogether. Outputting the time can help you identify areas of code that may be taking longer than you'd expect to execute. The parameter should be one of the following values: N or NO L or LONG S or SHORT Note that ppwizard is optimised for fast execution with debug turned off, and in fact may perform extra work when debug is on (on the assumption that execution time is not an issue). For these reasons you should use the timings you obtain as a guide only. Note that a regina bug prevents this from working correctly at this time. ═══ 2.7. /Define ═══ Switch /Define:Variable=Contents This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. This command sets variables (like #define), but from the command line. You can set as many variables as you wish. If the contents needs to include a space you should use "" instead. EXAMPLE Define 2 variables ppwizard.cmd 1.in /output:out\*.out /CrLf /Define:OpSys=OS/2 In your code you could do: #if '<$OpSys>' = 'OS/2' ... #elseif ... #endif ═══ 2.8. /DependsOn ═══ Switch /DependsOn:[-]EditMask This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. This option requires a parameter which controls how the "InputFile" parameter is transformed into the name of a dependancy file. The default is that there is no dependancy file (therefore dependancies are not checked). If you use dependancy files then the output is only built if required (a source file has changed). Unless you preceeded the EditMask parameter with a '-' the dependancy checking progress is displayed. You can not build a system that can not be reliably tracked however you may need to use the #DependsOn command if you directly access files yourself via macros. on An edit mask is basically much like a file (with path if required) and will contain zero or one special characters as follows: 1. * or {$BASE} This gets replaced with the short filename (less extension) of the current input file. 2. ? or {$PATH} This gets replaced with the path (including terminating slash) of the current input file. This is most likely to be of use if you want to position generated files relative to the input file and you use the "/ScanSubDir" switch. For example "?OUT\*.HTM". 3. {$path} This allows you to set up a separate tree for generated filenames, the input mask and file are examined and the relative path extracted, the result is either blank ('') or a relative path that ends with a path separator. Note for this to work the input mask must either use an absolute path, begin with '.' or '..' followed by slash or not have a path attached at all otherwise ppwizard will abort. It would be pointless to use this sort of path unless the "/ScanSubDir" switch was also used. The "EditMask" can be absolute or relative (your exact circumstances will determine your choice). Note that resultant relative filenames are always relative to the current directory. While you control the case of the mask you can't control the case of the part that replaces the '*'. What you can do is ensure the whole name is either in upper or lower case with the /FileNames switch. EXAMPLE In the following example the command will check/create a file called "OUT\DEPEND\IN.DEP": +-[ MAKEIT.CMD ]----------------------------------------------------+ | @echo off | | ppwizard.cmd IN.IT /Output:OUT\*.html /DependsOn:OUT\DEPEND\*.DEP | | if errorlevel 1 echo ERROR: Command failed! | +-------------------------------------------------------------------+ ═══ 2.9. /DependsOnComplete ═══ Switch /DependsOnComplete[:YesOrNo] This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. This switch alters the way "/DependsOn" works. Normally ppwizard is very strict in its input dependancy checking in that it puts itself and any spelling dictionaries used in the list. This means that when one of these items changes everything gets remade. While the safest option is to leave it on you may wish to turn it off. Note that this switch controls the building of the dependancy file. Existing dependancy files will need to rebuild at least once under the new setting for everything to work as you wish, for this reason you may wish to delete any existing dependancy files when you change the setting. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise one of the following values is expected: Y N YES NO ═══ 2.10. /Exclude ═══ Switch /Exclude:FileMask This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. Sometimes you may wish to process most files with a few exceptions, this switch allows you to specify those exceptions. The switch may be used as many times as required. ppwizard.cmd *.IT /Exclude:TEST*.IT /Exclude:TRY?.IT /Output:OUT\*.html ═══ 2.11. /FileNames ═══ Switch /FileNames:TranslateType This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. Normally the case of output filenames are not modified, you can override this behaviour with this command line switch. It requires either "Upper" or "Lower" as a parameter. ═══ 2.12. /FilterInput ═══ Switch /FilterInput:RexxCmdFile This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. This will probably be a rarely used option. This switch allows you to translate file input a line at a time. The mechanism provides the filter enough information to perform complex processing (in case required). Your filter routine will return the possibly changed line or lines. In most cases it would probably be easier to write a translation procedure as a separate step before PPWIZARD is invoked (however sometimes this may not be practical). The rexx filter code you identify will be passed the following arguments: 1. The literal 'I' indicates that input is being filtered. 2. The line as read by rexx (still has comments and all whitespace). 3. The name of the file where the line came from. 4. The line number of the source file being processed (first line is 1). 5. The overall input line number (counter). 6. The newline character you should use if returning more than one line. The following environment variables are also available for use: 1. PPWIZARD_VER_II This variable contains the version number of the interface used by this program. This version number will only change when PPWIZARD has been modified in such a way that existing input filters could break. Its is recommended that you validate the interface in your filter. 2. PPWIZARD_DEBUG This variable tells you the current debug state ('Y' means on). This can be modified by the #debug command or the "/debug" command line switch. 3. Your Own Variables You can create your own state variables in the environment. I have a need where each input line is encrypted to prevent tampering by users, the source is divided over many header files. For a number of reasons I do not wish to perform a separate step to get the files in the clear. This switch is my generic solution. WHAT YOU RETURN 1. You may modify the passed line in any way you wish and return the result. 2. You may pass back more than one line by separating the lines with the passed newline character. This allows you to insert macros or #include instructions. 3. You may drop a line altogether by returning the string value "d2c(0)". 4. You may indicate an error by returning "d2c(0)" followed the error message, processing will stop. EXAMPLE OF INPUT FILTER /************************************************/ /* Stupid non-useful example of an input filter */ /************************************************/ /*--- Get ALL parameters ----------------------------------------------------*/ FilterType = arg(1); TheLine = arg(2); FromFile = arg(3); FromFileLine = arg(4); TotalLine = arg(5); NewLine = arg(6); /*--- Check ONCE if on correct interface ------------------------------------*/ if TotalLine = 1 then do /*--- Filter written to interface version "98.131" --------------------------*/ WrittenToFilterVer = "98.131"; CallersVer = GetEnv("PPWIZARD_VER_II"); if CallersVer <> WrittenToFilterVer then return(d2c(0) || 'FILTERIN: Interface written to version ' || WrittenToFilterVer || ' (found ' || CallersVer || ')' ); end; /*--- Get current debug state (output input line if debug is on) ------------*/ DebugOn = GetEnv("PPWIZARD_DEBUG"); if DebugOn = 'Y' then say 'FILTERIN: #' || TotalLine || ' -> ' || TheLine; /*--- Process the input -----------------------------------------------------*/ if TotalLine = 1 then do /*--- We wish to drop the 1st line ---------------------------------------*/ if DebugOn = 'Y' then say ' We are dropping this line'; return(d2c(0)); end; else do /*--- Now either insert a line (if 4th) or return line unchanged ---------*/ if TotalLine = 4 then return(TheLine || NewLine || 'This line was inserted after the 4th line input line!'); else return(TheLine); end; /*===========================================================================*/ GetEnv: /* */ /* arg(1) : Name of environment variable. */ /*===========================================================================*/ return( value(arg(1),,'OS2ENVIRONMENT') ); ═══ 2.13. /FilterOutput ═══ Switch /FilterOutput:RexxCmdFile This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. This will probably be a rarely used option. This switch allows you to translate all generated lines a line at a time. The mechanism provides the filter enough information to perform complex processing (in case required). Your filter program actually writes all output lines. In most cases it would probably be easier to write a translation procedure as a separate step after PPWIZARD has completed (however sometimes this may not be practical). The rexx filter code you identify will be passed the following arguments: 1. The literal 'O' indicates that output is being filtered. 2. The generated line without terminating newline. 3. The name of the output file. 4. The number of lines already generated to the file (starts at 0). 5. The overall number of lines generated. 6. The newline character(s) that need to terminate each line that you write. The value of the newline may change if /CrLf is used. The following environment variables are also available for use: 1. PPWIZARD_VER_OI This variable contains the version number of the interface used by this program. This version number will only change when PPWIZARD has been modified in such a way that existing output filters could break. Its is recommended that you validate the interface in your filter. 2. PPWIZARD_DEBUG This variable tells you the current debug state ('Y' means on). This can be modified by the #debug command or the "/debug" command line switch. 3. Your Own Variables The filter program can create its own state variables in the environment, this is demonstrated in the example further on. You can also set environment variables with the built in SetEnv routine. WHAT YOU RETURN 1. If successful you should return the string "OK:" followed by the number of lines you wrote to the output file. For example you would return "OK:0" if you dropped the passed line. 2. Any string that does not begin with "OK:" indicates an error. The message will be displayed and processing will stop. EXAMPLE OF OUTPUT FILTER /*************************************************/ /* Stupid non-useful example of an output filter */ /*************************************************/ /*--- Get ALL parameters ----------------------------------------------------*/ FilterType = arg(1); TheLine = arg(2); ToFile = arg(3); ToFileLine = arg(4); /* Written so far */ TotalLine = arg(5); /* Written so far */ NewLine = arg(6); /*--- Check "ONCE" if on correct interface (Actually checked twice) ---------*/ if TotalLine = 0 then do /*--- Filter written to interface version "98.132" -----------------------*/ WrittenToFilterVer = "98.132"; CallersVer = GetEnv("PPWIZARD_VER_OI"); if CallersVer <> WrittenToFilterVer then return( 'FILTEROUT: Interface written to version ' || WrittenToFilterVer || ' (found ' || CallersVer || ')' ); end; /*--- Get current debug state (output input line if debug is on) ------------*/ DebugOn = GetEnv("PPWIZARD_DEBUG"); if DebugOn = 'Y' then say 'FILTEROUT: #' || TotalLine+1 || ' -> ' || TheLine; /*--- If first line drop (this is complicated by line counters not changing!)*/ if TotalLine = 0 then do /*--- Only drop the first "first" file! ----------------------------------*/ if GetEnv('FiltOut_0') = '' then do /*--- We wish to drop the 1st line -----------------------------------*/ if DebugOn = 'Y' then say ' We are dropping the first line of output'; call SetEnv 'FiltOut_0', 'Line 0 dropped'; return("OK:0"); end; end; /*--- All lines reversed (except inserted 5th) ------------------------------*/ NumberOfLines = 1; ToWrite = reverse(TheLine); if TotalLine = 3 then do /*--- We are inserting a line (generating 2) -----------------------------*/ NumberOfLines = 2; ToWrite = ToWrite || NewLine || 'This line was inserted after the 4th output line line!'; end; /*--- Output the data -------------------------------------------------------*/ if 0 <> charout(ToFile, ToWrite || NewLine) then return('Write to "' || ToFile || '" failed!'); else return("OK:" || NumberOfLines); /*===========================================================================*/ GetEnv: /* */ /* arg(1) : Name of environment variable. */ /*===========================================================================*/ return( value(arg(1),,'OS2ENVIRONMENT') ); /*===========================================================================*/ SetEnv: /* */ /* arg(1) : Name of environment variable. */ /* arg(2) : New Value. */ /* */ /* Returns original value of the environment variable. */ /*===========================================================================*/ return( value(arg(1),arg(2),'OS2ENVIRONMENT') ); ═══ 2.14. /GetEnv ═══ Switch /GetEnv:EnvVarName This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. This allows you to specify an environment variable which must exist and whose value is more PPWIZARD command line parameters. This switch could be used to handle long command line, it effectively allows you to have an infinitely long command line since the included contents can itself refer to other environment variables. ═══ 2.15. /HTML ═══ Switch /HTML This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. This switch should rarely be required as html mode is the default mode unless all input files end in the extension ".X" (its use is recommended for rexx source code). On non unix operating systems lines end with carriage return followed by linefeed, with the internet unix has finally won (it only requires lines to terminate with a linefeed). Web servers and browsers do not require the carriage return (which they ignore). You can save an extra one character per line with use of the /CRLF switch. This switch sets the processing mode for the output file as well as the default processing mode for other output files specified with the #Output command. ═══ 2.16. /HtmlGenerator ═══ Switch /HtmlGenerator:Contents This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. By default when generating HTML, ppwizard will try to insert a meta tag similar to the following in the "HEAD" section: You can turn off the generation of the tags altogether by specifying an empty value or you can supply alternative line(s). PPWIZARD is supplied as freeware and I would appreciate it if you at least mention PPWIZARD and its homepage in the pages that you generate (either in meta tags or comments). The switch is mainly supplied so that you can add your own details if you wish. If you wish to specify your own generator contents (or refer to ppwizard details in HTML comments) you can make use of these variables (on the command line replace '<' with '{x3C}' and '>' with '{x3E}') : 1. 2. 3. 4. The value you wish to give this switch is probably so large that you would normally need to use the /GetEnv switch to get the information out of an environment variable. ═══ 2.17. /Inc2Cache ═══ Switch /Inc2Cache[:YesOrNo] This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. This switch can be used to override the way PPWIZARD includes files. This would not normally be required as PPWIZARD is likely to choose a good way. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise one of the following values is expected: Y N YES NO Warning Loading the files to cache will of course require more memory than you'd otherwise require. From what I gather Windows (95/98 and NT!) do not have very good memory management. ═══ 2.18. /Info ═══ Switch /Info[:YesOrNo] This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. By default important informational messages may be output, these could be considered as similar to a warning but no as severe. They inform you of situations that are unusual but may be perfectly OK in your environment. This switch allows you to turn these messages off. It is recommended that you do not turn them off. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise one of the following values is expected: Y N YES NO ═══ 2.19. /Other ═══ Switch /Other This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. This switch indicates that the input is not one of the types specifically supported such as HTML or REXX. It turns of any funny stuff while in #AsIs Mode. This switch sets the processing mode for the output file as well as the default processing mode for other output files specified with the #Output command. ═══ 2.20. /Option ═══ Switch /Option:OptionParameters This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. The "OptionParameters" is basically anything that is acceptable on the #option command. When PPWIZARD starts it sets up a default value for each option. This switch allows you to modify the value to suit your needs. Warning You may need to be careful about some of the characters used on a command line or when setting an environment variable. For example from an OS/2 command prompt you can not set an environment variable to a value that contains an equal sign, you would need to use '{x3D}' (it's ASCII code in hexadecimal) instead. ═══ 2.21. /Output ═══ Switch /Output:EditMask This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. This parameter controls how the "InputFile" parameter is transformed to generate the correct name for the generated output file. on An edit mask is basically much like a file (with path if required) and will contain zero or one special characters as follows: 1. * or {$BASE} This gets replaced with the short filename (less extension) of the current input file. 2. ? or {$PATH} This gets replaced with the path (including terminating slash) of the current input file. This is most likely to be of use if you want to position generated files relative to the input file and you use the "/ScanSubDir" switch. For example "?OUT\*.HTM". 3. {$path} This allows you to set up a separate tree for generated filenames, the input mask and file are examined and the relative path extracted, the result is either blank ('') or a relative path that ends with a path separator. Note for this to work the input mask must either use an absolute path, begin with '.' or '..' followed by slash or not have a path attached at all otherwise ppwizard will abort. It would be pointless to use this sort of path unless the "/ScanSubDir" switch was also used. The "EditMask" can be absolute or relative (your exact circumstances will determine your choice). Note that resultant relative filenames are always relative to the current directory. While you control the case of the mask you can't control the case of the part that replaces the '*'. What you can do is ensure the whole name is either in upper or lower case with the /FileNames switch. The default mask is "*.htm". I place all my output into a separate "OUT" directory and use "/Output:OUT\*.HTM". ═══ 2.22. /Pack ═══ Switch /Pack[:YesOrNo] This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. This switch is only useful if "/rexx" is also specified. You can get a much smaller generated rexx program by packing (off by default). Packing does not significantly slow down processing. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise one of the following values is expected: Y N YES NO MORE ON PACKING The preprocessor packs well written code (by my definition!) and can fail to correctly pack code where strings are appended without the use of the "||" operator (as the excess spaces will be removed). For example the following statement will not create the string you expect when packed: BothPartsCombined = 'Value:' TheValue; The following statement is a version of the above that will work: BothPartsCombined = 'Value: ' || TheValue; You can get very good results by packing but if you have got legacy code or you don't wish to change (your evil ways!) you should use the "/Pack:N" command line switch. This turns off most packing (rexx comment and trailing ';' removal still occurs). If you have trouble with some parts of your code but the bulk packs well then you may wish to consider leaving packing on and using the AllowPack option to indicate parts of your rexx code that should not be packed. WARNING This has not been tested on object rexx so I don't know if it will work or not (I assume it will). ═══ 2.23. /Rexx ═══ Switch /Rexx This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. The input is treated as rexx source. Rexx comments are removed from the source. This switch sets the processing mode for the output file as well as the default processing mode for other output files specified with the #Output command. Packing of the resultant rexx code (within one generated line) occurs by default. You can specify "/Pack" if you don't want this done. Turning off packing will speed up the generation of rexx code but in my mind the compression gain from leaving it on is worth it. Other options you may wish to use are "LeaveBlankLines" & "KeepIndent". WARNING Note that if you are taking unknown code and passing it through the preprocessor to reduce its size you should use the "/Pack;N" option as there are situations where the operation of the code will be affected. Some good and safe reduction in code size will still occur. ═══ 2.24. /SpellAddWord ═══ Switch /SpellAddWord:[-]NameOfAddFile This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. This option can be specified if you have used /SpellCheck (use empty dictionary if required) to enable spell checking. What it allows you to do is indicate which incorrect words should be added to a dictionary file. All words you wish to add are added to the file sorted in order of the number of occurances of this word so that the most frequently used (therefore most important) are first. You would typically manually cut and paste words from the generated file to one of your dictionary files. To automatically add all words to the file preceed the filename with "-". ═══ 2.25. /SpellCheck ═══ Switch /SpellCheck:NameOfDictionary This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. This option loads a dictionary and turns on spell checking. The switch can be used any number of times to load as many dictionaries as you wish. As an example you might wish to set up "GLOBAL.DIC", "PROJECT.DIC" and "JUNK.DIC". You may need to set up "JUNK.DIC" to hold junk words that are not really valid but get picked up as words during the spell check. In interactive spell checking such as in Microsoft word, these junk words are the annoying ones you keep replying "Ignore All" to! Note that ppwizard ignores the case of words and should work for international languages such as German. The /SpellAddWord will help you update or create dictionaries. A dictionary file must exist and it can be empty. There are large dictionaries available (such as in isspell40.zip on hobbes) however this take too long to load if you are impatient like me. The extra time will be required to load the extra words into memory, once loaded I do not think it will take longer to process your files. Spell checking has 2 basic modes (you can use both together) as follows:, You can indicate words that you frequently get wrong and ppwizard will tell you when you use the word. You can supply a list of "good" words (dictionaries) and ppwizard will tell you if you use a word which is not in a dictionary. Dictionaries All leading whitespace on all lines is ignored as are any blank lines or lines that begin with ';' (a comment). There are two types of dictionary entries as follows: 1. A valid word. Each word occurs on its own line. The fact that we have loaded at least one dictionary word (you are not required to do so) means that ppwizard will try to validate (spell check) all words. Note that a "word" can contain any characters and so if required could be "ASD%^". 2. A '$command' as follows: $MISTAKE This command allows you to specify a word that you frequently get wrong. Ppwizard will tell you if you use this word. The command takes one or two parameters the first parameter is the incorrectly spelt word while the second (if passed) is the word correctly spelt. $DELIMITERS If you don't like the default delimiters that ppwizard uses then you can specify a rexx expression which represents the delimiters you wish to use. Each character you specify is converted to a space and is therefore ignored. A warning is generated if this command is used more than once. Example of Dictionary ;--- Add common mistakes ---- $mistake seperate ;--- Specify alternate delimiters ---- $Delimiters d2c(9) || ',.=:;<>&-%()!/~?#${}[]"' ;--- A few words ---- THE CAT DOG computer. ═══ 2.26. /SpellShowAll ═══ Switch /SpellShowAll[:YesOrNo] This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. By default you only see a warning for the first time a word error occurs in each build. This switch allows you to indicate that you would like to see every error. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise one of the following values is expected: Y N YES NO ═══ 2.27. /ScanSubDir ═══ Switch /ScanSubDir This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. By default this program only checks the directory specified in the "InputMask", specify this option if you wish to process subdirectories as well. ═══ 2.28. /Sleep ═══ Switch /Sleep:NumberOfSeconds This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. This option can be used to pause execution for a period of time after PPWIZARD completes processing normally (no trap etc). Used with the "/DependsOn" switch could be used in place of a CRON step to poll for data file changes. If you like the sound of this be sure to also check out the "/Template" switch. ═══ 2.29. /Tabs ═══ Switch /Tabs:TabOption This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. The "TabOption" parameter controls how tabs if found are handled. Valid options are: Ignore Don't do anything, just ignore, this may cause preprocessor to fail (depending on where tabs are located). ToSpaces Each tab is converted to one only space. Warnings Each tab is converted to one only space and a warning is generated. This is the default condition. ═══ 2.30. /Template ═══ Switch /Template:TemplateFile This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. Normally PPWIZARD begins by reading from the input file. This switch modifies this behavior. The name of the "input file" is stored in the variable "" and the file named on this switch is loaded instead. The template file would generally #include or #import the data file. ═══ 2.31. /WarningsIgnore ═══ Switch /WarningsIgnore[:IgnoreWhich] This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. This switch allows you to have individual control of which warning messages you wish to see. If this switch is used more than once the last used invocation is what is used. Warnings can come from PPWIZARD or from the #warning command. To turn off ignoring of warning messages you would not pass a parameter. This would be useful if you have set up a default where some messages are ignored. If you supply a parameter then you can specify one or more strings (each separated by ';', or ':' under unix). If the text of a warning message contains any of the strings (case insensitive check) then the message will not display and the warning return code will not be generated. If a message is dropped then you can still see the message in debug mode as well as the reason it normally gets dropped. The warning message text which is searched includes the line number as well as the warning ID, basically the exact text that you would normally see so you could prevent warnings down to a particular line number if you wish (although this is not recommended). Warning IDs and text are not documented so you need to wait for one to occur before deciding how to drop it. If you wish to see warning messages but still want a zero return code you should check out the /WarningsOk switch. ═══ 2.32. /WarningsOk ═══ Switch /WarningsOk[:YesOrNo] This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. By default when one or more warnings are displayed a return code of 1 will be returned, when this switch is used to indicate that Warnings are OK then a "good" return code of zero will be returned instead. This switch simply indicates that you don't care what warnings were displayed, you do not consider a warning to be an error. You can get more fine tuning with the /WarningsIgnore switch. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise one of the following values is expected: Y N YES NO ═══ 2.33. /**/ ═══ Switch /**/[:YesOrNo] This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. This switch only has affect when /rexx also used to turn on rexx processing. Normally rexx comments on ends of lines are removed. Use this switch to leave them in. Normally there would be no need to leave them in however you might choose to do so to aid runtime debugging. If the "YesOrNo" parameter is not specified then it defaults to "Y", otherwise one of the following values is expected: Y N YES NO ═══ 2.34. /#Include ═══ Switch /#INCLUDE:FileList] This is a PPWIZARD.CMD command line switch. You can set up your own default switches in the "PPWIZARD_OPTIONS" environment variable. This switch allows you to specify one or more files which should automatically be included before any other file processing takes place. To specify more than one they should be separated by a ';' character (or ':' under unix). You could use this if you supply a set of macros in header file and supply a batch file to run the preprocessor. You would then not have to require (or request) a user of your header to '#include' it themselves. Example ppwizard.cmd *.it /output:out\*.htm /CrLf /#Include:Header1.H;Header2.H ═══ 3. The Source Code ═══ The Source Code 1. There is no limit to how long a line may be so the only practical limit will be whatever your editor or other tools impose. You will wish to also check out the following extra details: White Space Commenting Line Continuation Quoted Text - qTextq Quoted Text - qRestq Dependancies 2. There is a range of "Standard Definitions" available for use in your source. You can create your own as well (for example a formatted date/time of your document). 3. You can selectively include or exclude portions of the source code using the "#if" command. 4. Large portions of text (with or without HTML tagging) that you place in multiple places which you feel must be kept in sync can be defined once with "#define" and referenced many times. ═══ 3.1. White Space ═══ White Space By default leading whitespace is ignored. You can use the "KeepIndent" to alter this. Even when not ignored all PPWIZARD commands may be indented from the left if you wish. Trailing whitespace is always removed from a line. If you must have trailing whitespace you could specify one or more "" codes. By default blank lines (after comment removal) are ignored. You can use the "LeaveBlankLines" option to alter this. ═══ 3.2. Commenting ═══ Line Comments By default the commenting character is ';' if a line begins with this character then it is ignored. If the line contains the character doubled up (as in ;;) then everything after the last occurance of this string is considered to be an inline comment and is removed. The line comment character can be modified with the LineComment option. You could add ';;' to the end of a line so that an earlier occurance and everything following does not get removed. You can also use the "" code if required. Note that if the line being dropped is in the middle of a set of continued lines then the the line continuation characters at the end (or not at the end) of the dropped line are not ignored. Commenting Blocks of Lines The easiest way to comment out multiple lines at one time is to use the "#ifdef" command to check for a name that you will ensure never exists such as in the following example: ;--- This is a line comment --- #define Highlight {$Text} ;;Comment here #ifdef xxxx 1st line commented out 2nd line commented out 3rd line commented out #endif ═══ 3.3. Line Continuation ═══ Line Continuation PPWIZARD can handle any length line (subject to any rexx interpreter limitations), however the editor you are using may have limitations or you just might want to format it better, PPWIZARD allows you to specify that a line continues onto the next line. The two or more lines will be merged together. You can continue long lines by placing the line continuation characters (' \' by default) at the end of a line that continues onto the next. The #OneLine command provides an alternative to the use of the line continuation characters and the #DefineRexx command provides a simpler way of formatting rexx code. It is not valid for the last line of a file to contain the line continuation characters, all combined lines must come from the one input file. This capability would be most useful for #define commands. The "LineContinuation" option can be used to disable line continuation or to change the continuation character. When you have a long #define statement that spans lines you can have any commands (such as #if, #elseif and #endif) within a continue block, however these commands themselves NEVER continue on following lines. While line continuation is taking place blank or comment lines are treated no differently from any other lines (that is they are not completely ignored as would normally be the case). If a comment line is found while collecting continued lines it must contain line continuation characters if the continuation is to continue. There are actually a number of line continuation types which make for an easier to read shorthand for other variations. All valid variations are listed below: 1. -\ All trailing whitespace is removed from this line before the next line is added. 2. +\ All trailing whitespace is removed from this line before a space and then the next line is added. 3. \ (space + slash) All trailing whitespace is removed from this line before a single space and the next line is added. 4. %\ All trailing whitespace is removed from this line before a newline code and the next line is added. If the line does not end in one of the above 2 character codes then the continuation character is ignored. Note that '+\' and ' \' currently serve the same purpose, in a future release you will probably be able to set the default continuation type for ' \'. Note that line continuation does not occur when the #AsIs "ON" is used. Example of #if Use Within Line Continuation #define TheSame \Hi, my name is Dennis Bareis and I have \ been using OS/2 and developing for \ #if '<$AtWork>' = 'Y' \ ANZ \ #elseif \ *WRONG INC* \ #endif \ on and off since the original 1.0 version. The above shows the creation of a multi-line macro. It is recommended (and in some cases required) that the definition be formatted as above, that is the line is continued by '\' after the macro name. All other line continuation can be as per your requirements (the above is simple but not ideal...). Example - Good Formatting, Macro Use <$MyMacro \ Parm1=^a parameter^ \ Parm2=^a parameter^ \ Parm3=^a parameter^ \ > ═══ 3.4. Quoted Text - qTextq ═══ Quoted Text - qTextq Many commands require quoted text, the only thing special about the quotes in this program are that they can be almost any character (anything non-alphanumeric), the only restriction are as follows: 1. The same quote character must appear at the start and end of the text. 2. If another parameter follows then there must be at least one space after the end quote character. 3. You can omit the quote characters if the first character is alphanumeric and the the text does not contain spaces. EXAMPLES The following are examples of valid quoted strings: "A string" 'Another string' ^A 'string' which contains "quotes"^ █ABC█ NoQuotesRequired ═══ 3.5. Quoted Text - qRestq ═══ Quoted Text - qRestq Many commands require quoted text, this format of quoted text is only ever used for the last parameter of some commands. This is very similar in function to the "Quoted Text - qTextq" method except that no more parameters are expected after the current one. All "Quoted Text - qTextq" examples are valid. Everything is the same as for "Quoted Text - qTextq" except: 1. The quote character can actually appear within the quoted text. 2. If the value is unquoted the rest of the line (stripped of leading & trailing whitespace) is used. 3. Nothing follows the text. EXAMPLES The following are examples of valid quoted strings: ^A 'string' which contains "quotes"^ "A string with "imbedded" double quotes" ═══ 4. Macros ═══ Macros Macros are collections of text and/or commands and would have to be one of the most important and most used features of this preprocessor. Macros can be created using one of the following methods: 1. #define[+] 2. #evaluate[+] 3. MacroSet() 4. /define The simplest types of macro simply allows you to define text which you will use over and over again. You will want to specify it in one place so that if it ever changes you won't need to hunt up all occurances. The following example shows an email address being defined (this would normally be done in a central place and be accessed with #include): #define MyEmailAddress dbareis@labyrinth.net.au Now that we have defined the email address (once as per example above), in all the html pages that required it we could refer to it as in:
If you have any questions or suggestions for improvements please feel free to email me. There are also a number of "Standard Macros" which always exist, including the following specialised forms: 1. 2. ?RexxVariable> All normal macros are replaced before standard macros. The "" form is never replaced until just before the line is to be written to the output file. The following sections provide more details about macros (please read in order): 1. Simplest Macros 2. Using Standard Definitions + Using REXX Logic 3. Multi Line Macros 4. Macros With Mandatory Parameters 5. Macros With Optional Parameters 6. Macro Parameters without values 7. Positional Parameters (not named) 8. Expand All Unused Parameters 9. Special MACRO Replacement "$$" Commands 10. Special MACRO PARAMETER Replacement "$$" Commands 11. Multi Line Macros With Logic A macro's name (or parameter) can be very long and can contain nearly any character (space and end of macro replacement character are the main exceptions). You will be told if a macro name is invalid when you try to define it. The maximum length of a macro will be approximately 100 characters in OS/2 rexx and unlimited with the regina interpreter. The name of a macro (and it's parameters) are normally case insensitive, however you can make them case sensitive by using the CsReplacement option. When this option is not used all macros and parameters are converted to upper case. ═══ 4.1. Simplest Macros ═══ Simplest Macros The subject of macros is reasonably complex (but well worth learning) please ensure you have at least read the macro introduction before reading this section. The simplest macros don't contain any logic (just text) and are used where there are many places where you wish the same information used. For example you might have an email address which you will refer to from 10 different HTML pages. If this email address changes you do not wish to look for and then change all of these occurrances. Not only would this be a real pain but you could miss one or get the new email address wrong on one (which you might never realise). You have probably got more than one macro you wish to define (others might be web addresses for external links), it is suggested that in general the best place to keep all of them is together in one place. You could add all the macro definitions in one place in a file you create called "MACROS.IH". For example the contents of this file might be: ;--- MY EMAIL Information --------------------------------------------------- #define MyEmailAddress db0@anz.com #define EmailMeGraphic ;--- Standard Graphics ------------------------------------------------------ #define ImgUpdated #define ImgNew #define ImgBarbedWire
;--- External WEB Addresses ------------------------------------------------- #define HttpNetLabsMainPage www.netlabs.org #define HttpNetLabsGimpPage www.netlabs.org/gimp/ #define HttpOs2WarpGuruMainPage www.geocities.com/SiliconValley/Pines/7885/ #define HttpOs2WarpGuruApmPage <$HttpOs2WarpGuruMainPage>DownloadAPM2.html At or near the start of the source for the html page (lets call it "Intro.IT") you would add the following statement to load the macros: ;--- Load all required definitions ------------------------------------------ #include "MACROS.IH" Later on in "INTRO.IT" you could have the following: If you have any questions or suggestions for improvements please feel free to email me. As you may guess from the above example to refer to the macro you place '<$' at the start and '>' at the end of the macro (variables) name. There is now only one place to change if your email address changes. Not only that but if you get the new address wrong it should be immediately apparent as it will be wrong in all locations! So not only have you simplified the process but you have probably improved the quality of your output as well! There are better ways to handle what was demonstrated above but hopefully the example was a simple enough starting point. If you are still confused I suggest that you read the e-Zine! articles written by Chris Wenham (the Senior Editor of OS/2 e-Zine! chris@os2ezine.com). ═══ 4.2. Using Standard Definitions + Using REXX Logic ═══ Using Standard Definitions + Using REXX Logic The subject of macros is reasonably complex (but well worth learning) please ensure you have at least read the macro introduction before reading this section. The following example uses the "#evaluate" command and the "Standard Definition" of "" as well as demonstrating the use of using rexx code to include logic. ;--- Capture some HTML information ------------------------------------------ #evaluate ShortNameHtml "_filespec('name', '')" #evaluate ShortNameHtmlLowerCase "ToLowerCase('<$ShortNameHtml>')" The above defined two macros, the first is the short name of the output file (no path or drive attached) and the second is the same short name but all lower case. A "Problem" Notice that the first parameter to the rexx translate function above is surrounded by single quotes, we could safely do this only because we know that a filename can't contain single quotes! You need to be careful with your use of quotes etc as the macro replacement simply places the correct text where requested. We could have used the PPWIZARD "MacroGet" function if we were not sure about the quote situation as demonstrated below: ;--- Capture some HTML information ------------------------------------------ #evaluate ShortNameHtmlLowerCase "ToLowerCase(MacroGet('ShortNameHtml'))" There is another (probably better way) of handling the quote 'problem' as in: ;--- Capture some HTML information ------------------------------------------ #evaluate ShortNameHtmlLowerCase "ToLowerCase('<$ShortNameHtml $$SQX2>')" ═══ 4.3. Multi Line Macros ═══ Multi Line Macros The subject of macros is reasonably complex (but well worth learning) please ensure you have at least read the macro introduction before reading this section. Sometimes a macro contains quite a bit of text and to make it easier you might wish to spread the definition over a number of lines. This will also allow you to add comments and spacing to allow it to be easy to read. When PPWIZARD sees a multi line macro (formatted in a similar manner to the example below) it breaks it up into multiple lines so that any imbedded PPWIZARD Commands will get executed. ;--- Define the macro ------------------------------------- #define FeedBackParagraphs \ ;---- First paragraph ----------------------------- \
I have put a lot of work into this produce and \ believe it to be of a very high standard. I \ always appreciate feedback which indicates which \ features you use and like and which you don't \ like. \ \ ;---- Second paragraph ---------------------------- \
Please email me \ with tour comments. ;--- Use the macro ---------------------------------------- <$FeedBackParagraphs> Notice that the expanded "<$FeedBackParagraphs>" will refer to our previously defined "MyEmailAddress" macro. It is perfectly legal for a macro definition to refer to any number of other definitions. ═══ 4.4. Macros With Mandatory Parameters ═══ Macros With Mandatory Parameters The subject of macros is reasonably complex (but well worth learning) please ensure you have at least read the macro introduction before reading this section. Back to my previously defined email macro, whenever I use it I still have to duplicate a lot of HTML tagging. What we could do is create an email macro which accepts the text or graphic that the user would click to email me, as below: #define EmailMeLink {$VISIBLE} The above macro accepts a single parameter which must be supplied when the macro is used. The parameter's name is "VISIBLE". The macro refers to a parameter by placing '{$' at the start and '}' at the end of the macro parameters name. To use this macro we could say:
If you have any questions or suggestions for improvements please feel free to <$EmailMeLink VISIBLE="email me">. Note that when you supply the value for a macros parameter you can use virtually any character as a quote not just single or double quotes, for example you could say:
If you have any questions or suggestions for improvements please feel free to <$EmailMeLink VISIBLE=@email me@>. ═══ 4.5. Macros With Optional Parameters ═══ Macros With Optional Parameters The subject of macros is reasonably complex (but well worth learning) please ensure you have at least read the macro introduction before reading this section. Also note that you can create a macro which accepts optional parameters. The "VISIBLE" parameter we have been using up to now is manditory (required), if not supplied the preprocessor will inform you of this fact and stop. To make a parameter optional you assign at least the first occurance of the parameter a default value. You can give each occurance a default value (which may be different), and the last specified default value is remembered for subsequent occurances where a default value is required but not specified. For example to change the email macro to use my email address as the default but allow the specification of alternative addresses I could do the following: #define EmailMeLink {$VISIBLE} You could then say:
If you have any questions or suggestions for improvements please feel free to <$EmailMeLink VISIBLE=@email me@>, I have another <$EmailMeLink VISIBLE=@email address@ EMAIL=$db1@anz.com$> which you might like to try. ═══ 4.6. Macro Parameters without values ═══ Macro Parameters without values The subject of macros is reasonably complex (but well worth learning) please ensure you have at least read the macro introduction before reading this section. A macro reference would normally specify values for all parameters it uses, however there are times when this is not required. PPWIZARD does not require you to set a value, if you don't supply one then the name of the parameter in upper case is used. The definition of the macro would supply a default value in case the parameter (keyword) was not used and would normally do some conditional generation (using #if etc). The following example shows a simple macro with very little validation that simply assumes if the "keyword" "start" was not supplied that the "end" condition is required: ;--- Define the macro --- #define StupidMacro \ #if '{$START=""}' = 'START' \ start stuff \ #elseif \ end stuff \ #endif ;--- Use the macro --- <$StupidMacro start> ;;Start stuff <$StupidMacro> ;;End ═══ 4.7. Positional Parameters (not named) ═══ Positional Parameters (not named) The subject of macros is reasonably complex (but well worth learning) please ensure you have at least read the macro introduction before reading this section. In some cases (especially with simple one parameter macros) you may simply wish to supply a value without bothering to name it. For example one way to implement a HTML comment might be: ;--- Define a macro (takes a parameter called "Text") ---- #define COMMENT ;--- Use the above macro --- <$COMMENT Text="This will become a html comment"> As you can see from the above we had to use "Text=" even though that is all the parameter could be (at least correctly), lets do this again but this time using a positional parameter: ;--- Define a macro (takes a single positional parameter) ---- #define COMMENT ;--- Use the above macro --- <$COMMENT "This will become a html comment"> Now the rules are that positional comments must start with a double quote (as demonstrated above), a single quote or an equal sign. The macro contents refers to the parameters as a '#' followed by a decimal number which indicates it's position (there can be any number of positional parameters). The reason for the equal sign is that it allows you to quote a string with any quote character (otherwise you wouldn't bother). As an example the above "COMMENT" macro could be called as follows: ;--- Use the above macro --- <$COMMENT "Using double quotes"> <$COMMENT 'Using single quotes'> <$COMMENT =@Using any quotes (can then include '" <-- single and double quotes)@> ═══ 4.8. Expand All Unused Parameters ═══ Expand All Unused Parameters The subject of macros is reasonably complex (but well worth learning) please ensure you have at least read the macro introduction before reading this section. This option allows you to create a ppwizard macro for a html tag and process any parameters you wish while expanding any you don't specifically make use of. For example the following is a simplistic "IMG" tag front end: #define IMG Notice the "{$?}" tag above, it will expand all keywords used on a reference except "FILE" and "ALT". If there are specific keywords you don't want included then you should preceed this command with the parameter using '$$IGNORE'. If there were no keywords then nothing is expanded else a space preceeds the resultant keywords. There are actually 2 modes of replacement, the above shows one mode where no "$$" Commands were used, if they were used then the commands are applied to each unused parameter in turn. In general one of the $$ commands would be a "pass" command. Using the $$ commands gives you much more quoting flexability and gives you the option of not passing on the parameters, you may wish to simply memorise them for later use. ═══ 4.9. Special MACRO Replacement "$$" Commands ═══ Special MACRO Replacement "$$" Commands The subject of macros is reasonably complex (but well worth learning) please ensure you have at least read the macro introduction before reading this section. Macros parameter where they were supplied on a reference without a value that and begin with '$$' have special meaning, they are commands to PPWIZARD. The command applies to the complete contents of a macro before and replacement of parameters has occurred. As well as all '$$' commands shown earlier (except the $$PASS ones) these commands are also available: $$ASIS The value of the macro is substituted EXACTLY as it is, there is no substitution of macro parameters etc. Note that this will not prevent any macros the contents refers to from being expanded. $$DSQ You use this command to surround your parameters data with quotes. The quotes used are double or single quotes, if neither can be used ppwizard will terminate. $$SDQ You use this command to surround your parameters data with quotes. The quotes used are single or double quotes, if neither can be used ppwizard will terminate. $$AQ You use this command to surround your parameters data with quotes. The quotes used are double or single quotes, if neither can be used ppwizard will go through a whole list of alternative 'quote' characters, if none of these can be used then ppwizard will terminate. $$HTMLQ The parameter is all or part of a string surrounded by double quotes, any double quotes that exist in the data should be converted to ""e;". $$SQX2 The value is modified such that all single quote characters are doubled up. This can be very useful if you wish to use the value in a rexx string which is surrounded by single quotes as rexx will in this situation treat the two single quotes as a single single quote that does not terminate the string. $$UPPER The parameter will be converted to upper case. $$LOWER The parameter will be converted to lower case. $$ADDCOMMA The parameter will be formatted using AddCommasToDecimalNumber(). $$? If the '$$' command is otherwise unknown you can create your own formatting (ie you can not redefine an existing format). To define a format you need to define a macro which contains the rexx formatting code. The macro must have the name of "REXX_$$" followed by the name of your command, for example to use the command "$$TO_C_STRING" you would create "REXX_$$TO_C_STRING". The value to be formatted is in the "TheValue" variable. If required you can also determine the source of the value (macro or parameter name) as it is stored in "TheName" (for case insensitive items it is in upper case). For macro parameters only the name of the macro being expanded is in the "TheMacro" variable. A simple example where if the "$$SQX2" command were not used that ppwizard would fail (in this case with variable "A" unknown trap): #define TheMacro The value 'A' is in quotes #evaluate "" "call Summary 'VALUE', '<$TheMacro $$SQx2>'" Another example where we wish to add commas to a rexx variable: Value = ?ARexxVariable $$ADDCOMMA> Here is another example which may be useful if you were creating 'C' code and maybe other situations: ;--- Define directory (non 'C' format as used elsewhere) --- #define DIR_NAME C:\DB\PROJECTS\FRED ;--- Define a macro to transform a string into 'C' format --- #DefineRexx REXX_$$TO_C_STRING TheValue = ReplaceString(TheValue, '\', '\\'); TheValue = ReplaceString(TheValue, '"', '\"'); TheValue = ReplaceString(TheValue, d2c(10), '\n'); TheValue = ReplaceString(TheValue, d2c(13), '\r'); TheValue = ReplaceString(TheValue, d2c(7), '\b'); #DefineRexx ;--- Use our defined transformation --- StringC = "<$DIR_NAME $$TO_C_STRING>"; ═══ 4.10. Special MACRO PARAMETER Replacement "$$" Commands ═══ Special MACRO PARAMETER Replacement "$$" Commands The subject of macros is reasonably complex (but well worth learning) please ensure you have at least read the macro introduction before reading this section. Within a macro's data, when referring to a parameter you can specify certain special commands (all begin with '$$'). These commands (there can be more than one) occur immediately preceeding the '}' character, available commands are: $$PASSDSQ The parameter will be quoted as per the $$DSQ command and the parameter name followed by the equal sign will be added to the start. This is handy when one macro uses another and a parameter needs to be passed to the inner macro (parameter has same name in both macros). $$PASSAQ The parameter will be quoted as per the $$AQ command and the parameter name followed by the equal sign will be added to the start. This is handy when one macro uses another and a parameter needs to be passed to the inner macro (parameter has same name in both macros). $$IGNORE The parameter will be "dropped" (a empty string will be substituted). The main reason you might want to do this is to prevent a '"{$?}"' type parameter from including this parameter. $$DSQ You use this command to surround your parameters data with quotes. The quotes used are double or single quotes, if neither can be used ppwizard will terminate. $$SDQ You use this command to surround your parameters data with quotes. The quotes used are single or double quotes, if neither can be used ppwizard will terminate. $$AQ You use this command to surround your parameters data with quotes. The quotes used are double or single quotes, if neither can be used ppwizard will go through a whole list of alternative 'quote' characters, if none of these can be used then ppwizard will terminate. $$HTMLQ The parameter is all or part of a string surrounded by double quotes, any double quotes that exist in the data should be converted to ""e;". $$SQX2 The value is modified such that all single quote characters are doubled up. This can be very useful if you wish to use the value in a rexx string which is surrounded by single quotes as rexx will in this situation treat the two single quotes as a single single quote that does not terminate the string. $$UPPER The parameter will be converted to upper case. $$LOWER The parameter will be converted to lower case. $$ADDCOMMA The parameter will be formatted using AddCommasToDecimalNumber(). $$? If the '$$' command is otherwise unknown you can create your own formatting (ie you can not redefine an existing format). To define a format you need to define a macro which contains the rexx formatting code. The macro must have the name of "REXX_$$" followed by the name of your command, for example to use the command "$$TO_C_STRING" you would create "REXX_$$TO_C_STRING". The value to be formatted is in the "TheValue" variable. If required you can also determine the source of the value (macro or parameter name) as it is stored in "TheName" (for case insensitive items it is in upper case). For macro parameters only the name of the macro being expanded is in the "TheMacro" variable. Note that the quoting routines above do more than just make your code "prettier", without using these commands you have to decide on a quote character yourself and then a parameters value must never contain this character. These special commands won't solve all quoting issues (remember parameter processed left to right - imbedded parameters are not processed first) however they will make life much easier. Lets make sure that parameters 2 and 3 in the following macro get translated to upper case: ;--- Define macro --------- #define SimpleTest P1={$parm1}, P2={$parm2="parm1_default" $$upper}, P3={$parm3 $$upper $$DSQ} ;--- Expand macro --------- <$SimpleTest Parm1='value1' Parm2='value2' Parm3='value3'> ═══ 4.11. Multi Line Macros With Logic ═══ Multi Line Macros With Logic The subject of macros is reasonably complex (but well worth learning) please ensure you have at least read the macro introduction before reading this section. In this example we add some conditional inclusion where the same macro can generate different text based on the environment or parameters that are passed to it. In the following macro the size of the image file is calculated unless a value was passed to it. You might create a macros as follows to display some photos in a table: ;--- Photo macro will either use passed size or work out correct size for you --- #define Photo \ #evaluate+ LocalFileName ^"..\graphics\{$Image}"^ \ #DependsOn INPUT "<$LocalFileName>" \
\ #if "{$Size=''}" <> "" \ #define+ TmpSize {$Size=''} ;;User supplied size \ #elseif \ #evaluate+ TmpSize ^GetImageHeightWidth("<$LocalFileName>")^ \ #endif \ It is then a simple matter to create format and add new photos as follows (note that the image size is automatically calculated): ;--- Create table of photos --------------------------------------------\ \ {$Title}
\ ALT="{$Title}"> \ \═══ 5. Rexx ═══ Rexx REXX is a very powerful interpreted programming language. While you don't need to know much about rexx to use PPWIZARD you will find that you can do so much more if you do. There is a lot of 3rd party support for rexx, not only for OS/2 but for windows as well. This program is written in rexx and has specific commands that allow you to embed rexx code. The following situations allow you to execute rexx code (some other minor situations as well): 1. #if commands. 2. #evaluate commands. 3. #import filters. 4. =RexxExpression> "standard definition". 5. In the CompareReplaceFixed() routine. For OS/2 users an online rexx manual was installed for you (by OS/2 install process). Otherwise you can get a copy of the regina documentation from http://www.lightlink.com/hessling/ There is a DebugLevel option of REXXTRACE that you can turn on or off to control level of debugging output from the rexx commands you execute. Regina's debugging is not as good as OS/2's native debugging but its still a help. The following information provides a very small summary of rexx, for people unfamiliar with programming this may not be enough and you may need to look elsewhere. A good place to ask questions or just sit back and watch is the news group "comp.lang.rexx". Some Examples of Rexx Code Integration Some simple one liners: ;--- Capture some HTML information --- #evaluate ShortNameHtml "_filespec('name', '')" #evaluate ShortNameHtmlLowerCase "ToLowerCase('<$ShortNameHtml>')" ;--- Capture date/time information --- #evaluate DateTime @date('WeekDay') || ' ' || date('Month') || ' ' || substr(date('Sorted'), 7, 2) || ' ' || left(date('Sorted'), 4) || ' at ' || time('Civil')@ More complex example where multi statement rexx is formatted in a very readable manner (using #DefineRexx): #DefineRexx IMPORT_RECORD_FILTER if Column.1 = "Wendy" then Remove='This is "Wendy" record' ;;Don't want this record else Column.1 = translate(Column.1) ;;Make column #1 upper case #DefineRexx #import ImportMe.CMA CMA "" "First
;--- Include all my photos ------------------------------------------ <$Photo Image="lazy.jpg" Title="Watching TV"> <$Photo Image="carback.jpg" Title="New Car (Back Left)"> Pictures
Name" "Surname" "Job" ═══ 5.1. Rexx Resources - Tools & Links ═══ Rexx Resources - Tools & Links 1. REXXIO A free rexx extension for Windows and OS/2. Contains File Functions, Directory Functions, Search Functions, Window Functions, Keyboard/Mouse Event Functions, Rexx Functions, Registry Functions, Global Stem Variable Functions, General Functions, Comms Functions Event Functions. http://www.lestec.com.au/freelibrary.htm. 2. REGUTIL A free rexx extension for unix and windows. It provides access to windows registry as well as some other powerful file and directory features. It was created by Patrick McPhee and is available from http://www.interlog.com/~ptjm/. 3. RexxSQL - SQL ACCESS Another free product for a large range of operating systems. Support covers a very large number of different databases. It is available from http://www.lightlink.com/hessling/. 4. Rexx Tips and Tricks Absolutely a must read for anyone using rexx under OS/2, only available as an OS/2 INF file. Note that a lot of the information is also applicable to other operating systems. You can get it from http://www.cfsrexx.com/pub/welcome.htm#rxtt. 5. Rexx Language Organisation Links to rexx sites and other interested info, available at http://www.rexxla.org/ 6. TCP-IP (RxSock) Tutorial A good short tutorial on using sockets (URL checking etc) is available at http://www2.hursley.ibm.com/rexxtut/socktut1.htm 7. RxSock For Windows Get a windows version of the RxSock.DLL from http://home.hiwaay.net/~abbott/regina/ ═══ 5.2. Rexx Variables ═══ Rexx Variables Rexx unlike many other programming languages does not require its variables to be predefined and there is only one type (string). A number is just a string of characters. Variable names can be any reasonable length and can contain the letters 'A' to 'Z', the digits '0' to '9' or any of "!?_" (digits can't start a variable name). In PPWIZARD you must not try to use the value of a variable which does not exist or it will trap with a "NOVALUE" abort and output diagnostic information which should spell out your problem. I very much recommend that you don't use simple rexx variable names such as "Count". This is dangerous as it may clash with PPWIZARD variables. If this occurs it will probably be very difficult to diagnose and PPWIZARD (and your code) will probably malfunction in unpredictable ways. No PPWIZARD variables start with '_' and for this reason I recommend that you preceed all variable names with this character. For example instead of 'Count' use '_Count'. All rexx variables you define are global, as are those used by PPWIZARD. This gives a lot of its power but it can also be dangerous. Always try to be aware of this fact. You also need to be aware that PPWIZARD may modify the rexx RC or RESULT variables that you believe has been set by an #evaluate command. Do not rely on these variables, set your own (of course within a single #evaluate PPWIZARD will not touch these variables). Some examples of giving rexx variables a value: #evaluate ^^ ^_Count = 1^ ;;Both this and next line set value to the number 1 #evaluate ^^ ^_Count = '1'^ #evaluate ^^ ^_Count = _Count + 1^ ;;Increase value by 1 #evaluate ^^ ^_Array.1 = 'a value'^ #evaluate ^^ ^_Fred = "a value"^ ═══ 5.3. Rexx Expressions ═══ Rexx Expressions The following operators can be used: + Adds values. - Subtracts values. * Multiplies values. / Divides values (5/2 => 2.5). % Divides values, want whole number (5/2 => 2). // Divides values, want remainder (5//2 => 1). Expressions can also make use of PPWIZARD or standard rexx functions. Some examples of expressions being used: #evaluate ^^ ^ResultOfExpression = (10 + 8) / 2^ ;;Value 9 #evaluate ^^ ^ResultOfExpression = (_Count - 1) % $Div^ #evaluate ^^ ^Path = GetEnv('PATH')^ ═══ 5.4. Rexx Conditional Logic ═══ Rexx Conditional Logic The #if command allows you to evaluate any rexx conditional expression to determine whether its true or not. The following tests operators are concidered to be "non-strict" (leading and trailing blanks are ignored as are leading zeros on numbers): = Tests if values are equal. <> Tests if values are not equal. < Tests if left value is less than the right value (can be text or number). <= Tests if left value is less than or equal to the right value (can be text or number). > Tests if left value is greater than the right value (can be text or number). >= Tests if left value is greater than or equal to the right value (can be text or number). The following tests operators are concidered to be "strict": == Tests if values are equal. \== Tests if values are not equal. << Tests if left value is less than the right value (can be text or number). <<= Tests if left value is less than or equal to the right value (can be text or number). >> Tests if left value is greater than the right value (can be text or number). >>= Tests if left value is greater than or equal to the right value (can be text or number). The following logical operators are also useful: & - AND (both must be true) | - OR (either can be true) Some examples follow: #if lines(<$LanguageFile>) = 0 #if Defined('Var1') = 'Y' | Defined('Var2') = 'Y' #if <$TmpHH> < 12 #if translate(GetEnv("PRJSRCDIR")) = "E:\DB\PROJECTS\HOMEPAGE" ═══ 5.5. Rexx Looping ═══ Rexx Looping Loops are one of the complex areas of rexx and most things you will wish to do with PPWIZARD will either not require them or the simpler PPWIZARD loops will be enough. The syntax of rexx loops is as follows: DO [ symbol=start [TO finish] ] [WHILE expression_w] [ [BY step ] ] [ [FOR count ] ] [UNTIL expression_u] [ expression_c ] [FOREVER ] Examples follow (these would need to be integrated with PPWIZARD using the #evaluate command : do 10 /* Do something 10 times */ end do _Count = 1 to 100 /* Do something 100 times (Count given values 1,2,3 to 100) */ end do _Multiple = 0 to 20 by 2.3 /* Loop with _Multiple = all multiples of 2.3 not more than 20 */ end do _Multiple = 0 for 6 by 5.7 /* Loop with _Multiple = the first six multiples of 5.7 */ end _Finished = 'N' do while _Finished = 'N' /* Set _Finished variable to 'Y' to exit loop */ end; do until _Finished = 'Y' & _Fred <> 0 /* Set _Finished variable to 'Y' to exit loop (_Fred must also be non zero) */ end; do 3 until _Answer = "YES" /* Exits loop after 3 times or if _Answer becomes 'YES' */ end do _Count = 1 to 10 until Fred == "" /* Loop 1 to 10 unless condition met */ end do _Count = 1 to 10 /* Looping 1 to 10 */ /* Want to restart loop (don't execute following loop code)? */ if _Restart = 'Y' then iterate; /* Go back to start of loop (_Count incremented) */ /* Want to exit loop early? */ if _Flag = 'Y' | _State = 'R' then break; /* Exit loop */ end ═══ 5.6. Rexx Parsing ═══ Rexx Parsing Parsing is another of rexx's complex areas, a subset of its syntax is summarised here: PARSE [UPPER] LINEIN [template] PARSE [UPPER] NUMERIC template PARSE [UPPER] VAR symbol template PARSE [UPPER] VALUE expression WITH template template -> [firstPosition] assignments [assignments] assignments -> [nextPosition] varlist [stopPosition] varlist -> varname ' ' [varlist] varname -> "non-constant symbol" | '.' firstPosition -> position nextPosition -> position [nextPosition] stopPosition -> position position -> searchPosition | absPosition | relPosition | '(' "expression" ')' searchPosition -> "string constant" absPosition -> "integer" | '=' numexpr relPosition -> '+' numexpr | '-' numexpr numexpr -> "integer" | '(' "integer expression" ')' This is an example of extracting each directory (one at a time) from the path (located in DOS or OS/2 environment): ;--- Get "PATH" from environment #evaluate ^^ ^_Path = GetEnv('PATH')^ ;--- Start list -----------------The path is:
;--- List Components ------------ #{ ;--- Get next directory name - #evaluate ^^ ^parse var _Path _ThisBit ';' _Path^ ;--- Exit if at end of path -- #if _ThisBit = '' & _Path='' #break #endif ;--- Output directory name ---
═══ 5.7. Standard Rexx Routines ═══ SUMMARY OF REXX "BUILT IN" ROUTINES Note that some of the routines listed below may not be available in the rexx version you are using (neither does it list all functions): ABBREV(information,info[,length]) - check for valid abbreviations ABS(number) - return the absolute value B2D(binary) B2X(binary) D2B(decimal) C2X(string) C2D(string[,n]) D2C(decimal[,n]) - convert between data formats D2X(decimal[,n]) X2B(hex) X2C(hex) X2D(hex) CENTER(s,n[,pad]) - centre a string in a field CENTRE(s,n[,pad]) COMPARE(s1,s2[,pad]) - compare two strings COPIES(s,n) - replicate a string DATATYPE(string[,type]) - test datatype. Type can be: A (alphanumeric) B (bits) L (lowercase) M (mixed case) N (number) S (symbol chars) U (upper case) W (whole number) X (hex) DATE([format]) - get date. Format can be: B (base date - days since 1/1/1 AD) C (days in century) D (days in year) E (European) J (Julian) M (month name) N (normal: dd Mon yyyy) O (ordered) S (sorted) U (USA) W (day of week) FORMAT(number [,[before] [,[after] [,[expp] [,expt]]]] ) - format a number as specified FUZZ() - NUMERIC FUZZ setting INSERT(new,target[,[n][,[length][,pad]]]) - insert new string into target JUSTIFY(s,n[,pad]) - justify text to given width LASTPOS(needle,haystack[,start]) - find last occurrence of a string LEFT(string,num[,pad]) - return an initial substring LENGTH(string) - find the length of a string MAX(number[,number...]) - find the maximum of a set MIN(number[,number...]) - find the minimum of a set OVERLAY(new,target[,[n][,[length][,pad]]]) - overlay new string on to target POS(needle,haystack[,start]) - find the first occurance of a string RANDOM([min][,[max][,seed]]) - return a random number REVERSE(string) - find the reverse of a string RIGHT(string,num[,pad]) - return a final substring SPACE(s[,[n][,pad]]) - evenly space words in a sentence STRIP(string[,[opt][,char]]) - remove leading/trailing spaces SUBSTR(string,n[,length[,pad]]) - return a substring SUBWORD(string,n[,k]) - return a substring of words SYMBOL(name) - test to see if a symbol is defined TIME([format]) - get the time. Format can be: C (civil time) N (normal) L (long) H (hours since midnight) M (minutes since midnight) S (seconds since midnight) E (elapsed time) R (elapsed time then reset) TRANSLATE(string[,[tableo][,[tablei][,pad]]]) - translate characters using given tables TRUNC(number[,n]) - truncate floating point number VALUE(s[,[newvalue][,selector]]) - get or set value of a symbol VERIFY(string,reference[,[option][,start]]) - verify string for valid characters WORD(string,n) - return a word from a string WORDINDEX(string,n) - return the position of a word in a string WORDLENGTH(string,n) - return the length of a word in a string WORDPOS(phrase,string[,start]) - find a phrase in a string WORDS(string) - return the number of words in a string XRANGE([a[,b]]) - return a range of characters Some rexx interpreters support functions which are not ANSI standard, others won't support all standard ANSI routines. If you care about operating system portability you will be careful about which routines you use. PPWIZARD has its own routines which may be be used, these should be used in preference to "standard" rexx ones as they will work in all operating systems that PPWIZARD supports. ═══ 5.8. Rexx Fragments - Kick Start ═══ Rexx Fragments - Kick Start This section will show you some small portions of rexx code (not complete) which can be used to quickly get you up to speed in rexx. Note that the examples below are isolated fragments, you could not cut and paste them and run them though PPWIZARD as they are... ;--- Assign a value to a variable --- SomeVariable = 'the cat sat on the mat'; ;--- Convert string to upper case --- UpperCaseString = translate(SomeVariable); ;--- Get first 2 characters of string --- Left2 = left('abcd', 2); ;--- Get last 2 characters of string --- Right2 = right('abcd', 2); ;--- Get middle 2 characters of string (first char at posn 1) --- Middle2 = substr('abcd', 2, 2); ;;Last '2' is length ;--- See if first char of string is 'A' (either case) --- if translate(left(UpperCaseString, 1)) = 'A' then do; ;--- Any number of rexx statements --- end; ;--- Does "SomeVariable" contain the characters "Fred"? --- if pos('Fred', SomeVariable) <> 0 then ;Does var SingleStatement; else do ;--- Any number of rexx statements --- end; ;--- Is the second word of "SomeVariable" the word "the"? --- if word(SomeVariable, 2) = 'the' then SingleStatement; ═══ 5.9. Rexx Extensions ═══ Rexx Extensions Any of these PPWIZARD routines may be used by your rexx code: AddCommasToDecimalNumber() AddInputFileToDependancyList() AddOutputFileToDependancyList() AddressCmd() AsIs() AsIsPrepare() AutoTag() BaseDate() BreakAt() BulkChar2String() BulkChangePrepare() CompareReplaceFixed() DataGet() DataSave() Debug() DebugIndent() Defined() DieIfIoErrorOccurred() EnsureFileHasCorrectCase() Error() ExpandXCodes() GenerateFileName() GetAmPmTime() GetEnv() GetFileLineBeingProcessed() GetFileTimeStamp() GetId() GetIdPrepare() GetImageHeightWidth() GetInputFileNameAndLine() GetLineBeingProcessed() Info() InputComponentLevel() InputComponentLineLevel() IsDebugOn() MacroGet() MacroSet() PadString() ProcessNext() QuoteIt() ReplaceMacros() ReplaceString() ReplaceStringCI() ReverseArray() SetEnv() SetId() SortArray() Summary() ToLowerCase() UrlDecode() UrlEncode() Warning() WriteLineToTmpImportFile() RexGetTmpFileName() _filespec() _SysFileDelete() _SysFileTree() _SysSearchPath() ═══ 5.9.1. AddCommasToDecimalNumber() ═══ AddCommasToDecimalNumber() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function takes a single parameter (a decimal integer) and adds commas as required. ═══ 5.9.2. AddInputFileToDependancyList() ═══ AddInputFileToDependancyList() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function allows you to specify an input dependancy. The function should be called before the file is read for the most accurate result in all circumstances. This routine is an alternative to the "#DependsOn" command. ═══ 5.9.3. AddOutputFileToDependancyList() ═══ AddOutputFileToDependancyList() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function allows you to specify an output dependancy. The function should be called after you have completed all updating of the file. This routine is an alternative to the "#DependsOn" command. ═══ 5.9.4. AddressCmd() ═══ AddressCmd() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This routine will pass the command that you specify to the operating system's command processor. The command will by default by logged when debug is on. This is a major reason why you should use this call. If your command produces some files as output or you create some by redirection you can specify the names of the files as parameter 2 onwards and these will be dumped when debug is on Under OS/2 if the command to be executed is a rexx batch file you should preceed the command with "CMD.EXE /c" or the command will fail. If you don't know what the command is you should preceed all commands with that string to play safe. Stupid Example This example shows a directory commands output going into one file and any error messages into another. If debug is on the contents of both files as well as the return code will be dumped. #evaluate "" ^call AddressCmd "dir /od >dirlist.out 2>error.out", "dirlist.out", "error.out"^ ═══ 5.9.5. AsIs() ═══ AsIs() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function takes a single parameter and will return the string after all "as is" conversion has taken place (see the #AsIs command). Note that this replacement occurs whether or not "as is" mode is currently on, the AsIsPrepare() function can be called to set up exactly what you wish modified. Note that you may not wish to use this routine because of interference you might cause with the use of the #AsIs command, in this case you might find BulkChar2String() useful. This routine is useful where you are reading in data directly rather than using #include or #import commands. You could be using the rexx linein() routine or accessing SQL data. Stupid Example ;--- Setup INTERNATIONAL symbols (2 only for this demo) --- #AutoTagState + #AutoTag 'Д' 'ä' #AutoTag 'Й' 'ë' ;;Only 2 for this example #AsIs SETUP INTERNATIONAL_SYMBOLS #AutoTagState - ;--- Prepare ASIS Tagging ---------------------------- #evaluate "" ^AsIsPrepare("INTERNATIONAL_SYMBOLS")^ ;--- Assign to some variables ------------------------ #evaluate "NoChanges" ^"Й Й Й"^ #evaluate "Changesmade" ^AsIs("Й Й Й")^ ;--- Generate couple of lines ------------------------ BEFORE: <$NoChanges> AFTER : <$Changesmade> ═══ 5.9.6. AsIsPrepare() ═══ AsIsPrepare() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function takes a single parameter made up zero or more "names" previous setup with the "SETUP" command of #AsIs. It basically identifies the tagging you wish to have take place when the AsIs() routine is called. ═══ 5.9.7. AutoTag() ═══ AutoTag() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function takes a single parameter and will return the string after all currently defined #AutoTag replacements have been make. Note that this replacement occurs whether or not "auto tag" mode is currently on. This routine is useful where you are reading in data directly rather than using #include or #import commands. You could be using the rexx linein() routine or accessing SQL data. Stupid Example #AutoTagState + #AutoTag 'FROM' 'TO' #evaluate 'Result' AutoTag('from / FROM'); <$Result> ;;Output saved result. #AutoTagState - ═══ 5.9.8. BaseDate() ═══ BaseDate() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function can be called to work out a basedate (julian day) given a date. The integer will be negative if an error occurred. You can tell how many days apart 2 dates are by subtraction of one from the other. The basedate is the number of days since 1 January 0001. If the returned basedate integer is divided by 7, the remainder will tell you what day of the week it is (where 0=Monday, 6=Sunday). The number returned for a date is compatible with rexx's "date('BaseDate')" call. INPUT DATE The routine takes a single parameter (the date) with the year, month and day of month being supplied in that order. The year should either be supplied as 4 digits or will pivot at 1980. It will take the input in these formats: 1. YYYYMMDD - any following characters ignored. 2. YY/MM/DD or YYYY/MM/DD 3. YY-MM-DD or YYYY-MM-DD 4. YY MM DD or YYYY MM DD 5. If nothing passed (or blank) then todays date is used. Note that it actually does not matter how many digits are supplied for day of month and month, however a resonable amount of validation occurs. EXAMPLE INPUT DATES 1. date('Sorted'); 2. date('Ordered'); 3. "98-2-12" 4. "1998/02/01" 5. "20001230" 6. "20001230235959" ═══ 5.9.9. BreakAt() ═══ BreakAt() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function gets passed a string and ensures that no component is larger than a value you specify. It is useful for automatically breaking up long URLs in tables etc so a column does not get too wide. The function takes the following parameters: 1. Break Length There are 2 formats for this value: A single integer specifies the maximum width of each component. The minimum is a third of this value. You can supply both the minimum & maximum values by separating them with "-" (as in "5-40"). 2. String This is the string we are adjusting. 3. Break At Char List This is a list of chars. We will try and find the longest string less than or equal to "Break Length" that breaks after one of these specified characters, if we can't find one the string is just truncated at the maximum length. If this optional value is not specified then "./:#" is used. 4. Break With Character This specifies the string used to break the string. If this optional value is not specified then "- ?_ThisBit> #} ;--- End list -------------------
" is used. The resultant string is returned. EXAMPLE This example shows a table where the first column contains a URL as a hypertext link to the URL shown. We don't wish the column to be wider than 18 characters (longer URLs will span multiple lines). ;--- Define a macro to (1) Create link (2) split up long URLS --- #define LinkToDisplayedURL \ #evaluate "TmpResult" @BreakAt(18, '{$URL}')@ \ \ <$TmpResult> \ #undef TmpResult ;--- Example of use in a table ----------------------------------═══ 5.9.10. BulkChar2String() ═══ BulkChar2String() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function is used to convert a whole series of single characters into strings. To convert single characters to other single characters you would of course use the rexx translate() routine. This function takes 2 parameters as follows: 1. The name of the source string. 2. The name of a rexx variable which lists each of the characters (in order) which you wish to convert. For each character in this string an element in the array of the same name contains what it should be converted to. The BulkChangePrepare() routine can be used to simplify the creation of the change information. The routine returns the possibly modified source string. When this routine returns the rexx variable ReplaceCount will have been incremented by the number of replacements made. Silly Example ;--- Set up the conversion information ------ #DefineRexx "" call BulkChangePrepare "Conv"; ;;Initialize to empty call BulkChangePrepare "Conv", '&', '&'; call BulkChangePrepare "Conv", '<', '<'; call BulkChangePrepare "Conv", '>', '>'; #DefineRexx ;--- Modify the input string ----------------- #evaluate '' ^say 'MODIFIED = ' || BulkChar2String('AAAA <&> BBBB', 'Conv')^ ═══ 5.9.11. BulkChangePrepare() ═══ BulkChangePrepare() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function is used to prepare the information required by the BulkChar2String() routine. This function takes 1 or 3 parameters as follows: 1. The name of a rexx variable which you will use in the change call. 2. The character to be replaced. 3. The string that will replace the character. To initialize the change information this routine should be called with out the second and third parameters. This routine does not return anything. ═══ 5.9.12. CompareReplaceFixed() ═══ CompareReplaceFixed() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function has 2 main operations as follows: 1. Compare a string against a compare specification. The return specification parameter is not passed by the caller. Returns 0 if not matched and 1 if match. 2. Compare a string against a compare specification. Either return the original string on no match or a new string as specified by the return specification. This is quite a complicated routine and hopefully the examples will clarify things. This routine can be very useful in #AsIs and #AutoTag processing. The function takes 3 parameters as follows: 1. The string to be compared with. 2. The COMPARE specification. This is made up of one or more of the following command sequences (in any order): @Operator,Posn=^CmpText^ The "operator" is a rexx compare operator such as "=" or "<>". The "posn" is the integer position of the substring within the "COMPARE" parameter to compare with "CmpText". If the value is positive then the value refers to a position from the left else it refers to a position from the right. For example "2" indicates the second character from the left while "-2" indicates the second last character. The length of the substring is the same as the length of "CmpText". Any character can be used for a quote character around the "CmpText". ?Operator/CmpText/ The operator should be either "=" or "!". If "=" then we expect to find "CmpText" in the first parameter, otherwise we don't. Any character can be used for a quote character around the "CmpText". !SubCommand The subcommand is one of: - S The following compares are to be case sensitive (each time this routine is called it begins in case sensitive mode). - i The following compares are to be case insensitive (you should supply upper case "CmpText" text). - I Ignore leading and trailing whitespace. Convert multiple spaces into a single space. - B Ignore leading and trailing whitespace. - L Ignore leading whitespace. - T Ignore trailing whitespace. 3. The RETURN specification. If not supplied then we are doing a simple compare operation and returning 1 on match and 0 if not. This parameter determines what string this routine will return. You can extract parts of the first parameter and intermix text of your own. A return command is imbedded in text and begins with the '@' character, the following byte determines the type of command, valid commands are: @ A '@@' indicates that the user wishes a single '@'. This is an escape sequence which allows the '@' character to be specified. $Posn,Len; You wish to extract a string out of the first parameter. You need to specify its position and length. You may supply '*' for the length to indicate that the rest of the string is desired. If the value is positive then the value refers to a position from the left else it refers to a position from the right. For example "2" indicates the second character from the left while "-2" indicates the second last character. =/RexxExpression/ A rexx expression is executed to determine the text to be used, you have access to the first parameter of this routine in the variable "CompareString". This method should be avoided where ever possible as it is significantly slower. Any character can be used for a quote character around the "RexxExpression" parameter. While some validation of the parameters is performed you should be careful with the parameters passed. If invalid parameters are passed you probably will not get the "change" you desire and I'm not ruling out a PPWIZARD trap. Validations are only performed when they will not (greatly) affect performance. Example - Compare Specifications 1. @=,1=^HTML^ To see if a string starts with the characters "HTML" (in that case). 2. @=,1=^HTML^!i@=,-2=^YZ^ To see if a string starts with the characters "HTML" (in that case) and ends with the characters "YZ" (in any case). 3. !B@=,1=^HTML^!i@=,-2=^YZ^ Same as above but leading and trailing whitespace is ignored. 4. @=,1=/HTML/!i@<>,-2=\YZ\ To see if a string starts with the characters "HTML" (in that case) and does not end with the characters "YZ" (in any case). 5. !i?=/HTML/ We expect the compare string to contain "HTML" (in any case). Example - Return Specifications 1. ABCD Return the string "ABCD". 2. AB@@C@@D Return the string "AB@C@D". 3. REM @$1,*; Return the compare string (first parameter) preceeded by "REM ". 4. REM @$1,1;@$3,1;@$-1,1; Return the 1st and 3rd and last characters of the compare string preceeded by "REM ". 5. REM (@=/strip(CompareString)/) Return the line stripped of leading and trailing whitespace surrounded by round brackets and preceeded by "REM ". Stupid Examples ;--- The following compare operation will return "1" as the compare "matches" --- #evaluate ^^ ^say 'Expect to see 1 ==> ' || CompareReplaceFixed('HTML', '@=,1=~HTML~')^ ;--- The following compare matches and the return specification is processed --- #evaluate ^^ ^say 'Expect to see ASDF ==> ' || CompareReplaceFixed('HTML', '@=,1=~HTML~', 'ASDF')^ ═══ 5.9.13. DataGet() ═══ DataGet() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function is used to retrieve a value previously stored away with the DataSave() function. It is OK for the value not to exist, if this is the case the "default" value you specified will be returned. If you wish you can make the "default" value some sort of "invalid value" to detect what you consider to be an error. The function takes 3 parameters as follows: 1. The Application Key. 2. The Key. 3. The default value (optional, default is ''). ═══ 5.9.14. Debug() ═══ Debug() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function is used to output a debug line. The line is only output if debug mode is currently on. The DebugIndent() call can be used to make your output easier to understand. The function takes a single parameter and that is the line to be output. ═══ 5.9.15. DebugIndent() ═══ DebugIndent() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function is passed a single numeric parameter which is positive or negative (normally -1 or 1). A postive value causes a bigger indent on the left of Debug() output. If you increase the indent you should remember to decrease it when finished. ═══ 5.9.16. DataSave() ═══ DataSave() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function is used to save a value away using a 2 part key. If you wish you can make the first part constant. The value can be retrieved using the DataGet() function. The function takes 3 parameters as follows: 1. The Application Key. 2. The Key. 3. The data to store. Note that there is no information returned by this function. WARNING Currently the value you save is kept between compiles, this is not the aim and will be corrected in a future release. Do not code anything that relies on this fact. If you use this routine you will need to consider if you can compile more than one source at a time. ═══ 5.9.17. Defined() ═══ Defined() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function can be called (probably in a #if command) to determine if a variable has been defined with either #define or #evaluate. The return code is either 'N' or 'Y'. You would use this routine in a #if command rather than a #ifdef or #ifndef if you want to do something which involves testing the existance of more than one variable. The parameters are as follows: 1. Define Name This is the name of the variable. EXAMPLE #ifdef Var1 ... #endif #if Defined('Var1') = 'Y' | Defined('Var2') = 'Y' ... #endif ═══ 5.9.18. DieIfIoErrorOccurred() ═══ DieIfIoErrorOccurred() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function can be called to at any time prior to the closing of a file (stream) to determine if any input/output errors have occurred. The routine will display a message and abort PPWIZARD processing if an error has occurred. The parameters are as follows: 1. File Name This is the name of an unclosed file. ═══ 5.9.19. EnsureFileHasCorrectCase() ═══ EnsureFileHasCorrectCase() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This routine takes a filename as its only parameter and adjusts its filename as specified with the "/FileNames" command line switch. Note that while the intention of this routine is to adjust the case of filenames there is no reason why any rexx string can't be passed if you have the need. ═══ 5.9.20. Error() ═══ Error() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This routine is probably most useful in #import filter code and takes from 1 to 10 parameters. Each parameter contains the contents of a line to be displayed. The passed message line(s) will be displayed and PPWIZARD processing terminated. ═══ 5.9.21. ExpandXCodes() ═══ ExpandXCodes() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This routine can be called to expand codes. This routine is passed a single parameter. The codes are expanded and the result returned. ═══ 5.9.22. GenerateFileName() ═══ GenerateFileName() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function returns a filename which is translated in the same way as the "/Output" switch. It also ensures that any directory component of the generated filename exists. The parameters are as follows: 1. Name of a file This is the name of a file that is used as a basic for conversion using the second parameter. 2. Conversion Specification This tells PPWIZARD how to convert the first parameter. Example ;--- For the current input file work out a good name for a debug file --- #evaluate '' ^DebugFile = GenerateFileName('', 'out\*.DBG')^ ═══ 5.9.23. GetAmPmTime() ═══ GetAmPmTime() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function takes no parameters and returns the time including seconds with "am" or "pm" attached. ═══ 5.9.24. GetEnv() ═══ GetEnv() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function returns the value of an operating system environment variable. An empty string is returned if the variable is unknown. The parameters are as follows: 1. Variable Name This is the name of the environment variable. 2. Die if Missing? This optional variable is used to tell ppwizard to abort if the variable could not be found. To tell PPWIZARD to abort pass upper case 'Y'. Example ;--- Lets keep all WORK/HOME conditional logic here ------------------------- #define AtHome translate(GetEnv("PRJSRCDIR", 'Y')) = "E:\DB\PROJECTS\HOMEPAGE\HTML" #define AtWork translate(GetEnv("PRJSRCDIR", 'Y')) <> "E:\DB\PROJECTS\HOMEPAGE\HTML" ... ... ;--- External Links --------------------------------------------------------- #if <$AtHome> #define ExtLink {$VISIBLE=`{$URL}`} #elseif #define ExtLink {$VISIBLE=`{$URL}`}{$URL-} #endif ═══ 5.9.25. GetFileLineBeingProcessed() ═══ GetFileLineBeingProcessed() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function takes no parameters and returns the text of the current line being processed. The line is as read from a file and may or may not be the current line being processed (after macro expansion etc). The line being processed is available using the GetLineBeingProcessed() call. The returned line has been stripped of leading and trailing whitespace. This call would usually be called to remember details about a current situation which you may wish to report at some future stage. If using this call you may also wish to use GetInputFileNameAndLine(), see this section for an example of these calls in use. ═══ 5.9.26. GetFileTimeStamp() ═══ GetFileTimeStamp() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function takes a single parameter (the name of the file we wish the date/time imformation of). If successful this routine returns a decimal number of the form "YYYYMMDDHHMMSS". The returned number can be compared with others to determine the newest file etc. You can substr() etc to transform the result into whatever format you desire. If the call fails (for example if the specified file does not exist) then a WARNING is generated and a return code of "-1" is returned. You can determine the day of the week for the file using the BaseDate routine. Example The following example shows how the date/time of a file can be retrieved and converted into whatever format you wish. Note that in the following macro I was careful not to redefine any variables and that a file not found is treated as a fatal error. #define GetFileDateTime \ #evaluate TmpDateTime ^GetFileTimeStamp("{$File}");^ \ #if <$TmpDateTime> = -1 \ #error ^The file "{$File}" was not found.^ \ #elseif \ #evaluate TmpDate ^substr('<$TmpDateTime>', 7, 2) || '/' || substr('<$TmpDateTime>', 5, 2) || '/' || left('<$TmpDateTime>', 4)^ \ #evaluate TmpHH ^substr('<$TmpDateTime>', 9, 2)^ \ #if <$TmpHH> < 12 \ #define TmpAmPm am \ #elseif \ #define TmpAmPm pm \ #endif \ #if <$TmpHH> > 12 \ #evaluate TmpHHAmPm ^<$TmpHH> - 12^ \ #elseif \ #evaluate TmpHHAmPm ^<$TmpHH>^ \ #endif \ #evaluate TmpTime ^"<$TmpHHAmPm><$colon>" || substr('<$TmpDateTime>', 11, 2) || '<$colon>' || substr('<$TmpDateTime>', 13, 2) || '<$TmpAmPm>'^ \ \ ;--- Output the information ("DD/MM/YYYY at HH<$colon>MM<$colon>SSam") --- \ <$TmpDate> at <$TmpTime> \ #undef TmpDate \ #undef TmpTime \ #undef TmpHH \ #undef TmpHHAmPm \ #undef TmpAmPm \ #endif \ #undef TmpDateTime ;--- Use my macro to get a timestamp ------------------------------------- ;------------------------------------------------------------
;------------------------------------------------------------ http:// Information <$LinkToDisplayedURL URL="www.geocities.com/SiliconValley/Heights/6121/"> Programmer's Info Page. The date/time stamp of "C:\AUTOEXEC.BAT" is "<$GetFileDateTime File="C:\AUTOEXEC.BAT">". ═══ 5.9.27. GetId() ═══ GetId() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function is useful if you wish to ensure that all characters in a string are valid. This can be useful when you wish to use a value as a key of some sort. For the value that you pass, this routine will determine a unique key (or ID) of the format you requested. The routine has a memory and will always return the same ID for the same value. The function takes at least 3 parameters as follows: 1. A handle that was previously prepared with GetIdPrepare(). 2. The type of ID you'd like, valid types being: 2_ Non valid characters are converted to underscores. Leading and trailing underscores are removed. Duplicated underscores are also removed. The upper and lower case characters as well as zero to nine are always valid characters. You may specify additional valid characters in the optional 4th parameter to this function. MAXCHARS The value is first converted in a similar manner to that used for "2_" mode. The leftmost 'x' chars are kept. The upper and lower case characters as well as zero to nine are always valid characters. You may specify additional valid characters in the optional 4th parameter to this function. The optional 5th parameter specifies the maximum number of characters in an ID with the default being 8. This type can be used to generate file names for a 8.3 based file system. C2X Non valid characters are converted to 'x??', where '??' is the characters ASCII code in hexadecimal. The upper and lower case characters as well as zero to nine are always valid characters. You may specify additional valid characters in the optional 4th parameter to this function. 3. The value for which you want an ID generated. This is case sensitive, to make case insensitive simply convert your value to either upper or lower case before calling this routine. 4. Depending on the type of ID being generated there may be a 4th or other parameters. Example ;--- Example #1 --- #evaluate '' ^call GetIdPrepare 'PPW'^ #evaluate '' ^call SetId 'PPW', '#define', "HashDef"^ ;;Set preferred ID #evaluate '' ^say GetId('PPW', 'MAXCHARS', 'define')^ #evaluate '' ^say GetId('PPW', 'MAXCHARS', '#define')^ #evaluate '' ^say GetId('PPW', 'MAXCHARS', 'define it')^ #evaluate '' ^say GetId('PPW', 'MAXCHARS', 'define')^ #evaluate '' ^say GetId('PPW', 'MAXCHARS', 'aaaaaaaaaaaaaaaa',, 10)^ ;;Max 10 chars #evaluate '' ^say GetId('PPW', 'MAXCHARS', 'aaaaaaaaaaaaaaab',, 10)^ #evaluate '' ^say GetId('PPW', 'MAXCHARS', 'aaaaaaaaaaaaaaac',, 10)^ #evaluate '' ^say GetId('PPW', 'MAXCHARS', 'aaaaaaaaaaaaaaaa',, 10)^ ;--- Example #2 --- #evaluate '' ^call GetIdPrepare 'PPW'^ #evaluate '' ^say GetId('PPW', '2_', '#define')^ #evaluate '' ^say GetId('PPW', '2_', '#include', '#')^ ;;Allow Hash to be valid as well ═══ 5.9.28. GetIdPrepare() ═══ GetIdPrepare() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function is used to prepare a handle for use in the GetId() routine. The function takes 2 parameters: 1. The handle to be used in GetId() and SetId(). 2. An optional parameter which if 'Y' means that you wish unique IDs generated by GetId() for what are probably non-unique values (or keys). When you specify unique IDs you are only allowed to use SetId() with a key of '' otherwise you are contradicting yourself! Normally when GetId() is called you pass it a unique key for which you wish a unique ID generated. If you ask for an ID for the same key at some later stage the original ID is returned. When 'Y' is used you intend to pass non-unique keys but YOU ensure or know that each time GetId() is called it is for a different entity even if the key looks identical! GetId() will generate a unique ID each time it is called and will not remember it. This mode can generate "prettier" IDs (at least until the key is duplicated) and without tricky code. The "FTPLIKE.IH" header file uses the "unique" mode. ═══ 5.9.29. GetImageHeightWidth() ═══ GetImageHeightWidth() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function can be used to automatically generate the HEIGHT and WIDTH parameters on a html "IMG" tag. The function takes 3 parameters (the 2nd and 3rd are optional), the parameters are: 1. The name of a file (.GIF or .JPG) 2. The width scaling factor (default = "100%"). 3. The height scaling factor (default = "?"). The scaling factor can be in these formats: A number followed by a percentage sign scales the size by the amount specified. "50%" would halve the size while 200% would double it. A number on its own (such as "100") fixes the size to the value supplied. It would be a common thing for the other sides size to be specified with "?" to have it scaled down in a proportional manner. A "?" causes the side to be sized in the same proportion as the other side. Note that scaling both sizes of an image by "50%" gives you an image a 1/4 of the size. If an error occurs the routine aborts, otherwise a string similar to "WIDTH=10 HEIGHT=20" gets returned. Note that as the image file needs to be read to determine its size this routine will slow down the preprocessing of your files. You could get smart and generate an image header file of sizes (each one #defined) so that a separate slow step generates a header file that html source includes. Example ;--- Photo macro will either use passed size or work out correct size for you --- #define Photo \ #evaluate+ LocalFileName ^"..\graphics\{$Image}"^ \ #DependsOn INPUT "<$LocalFileName>" \
\ #if "{$Size=''}" <> "" \ #define+ TmpSize {$Size=''} ;;User supplied size \ #elseif \ #evaluate+ TmpSize ^GetImageHeightWidth("<$LocalFileName>")^ \ #endif \ ;--- Create table of photos --------------------------------------------\ \ {$Title}
\ ALT="{$Title}"> \ \═══ 5.9.30. GetInputFileNameAndLine() ═══ GetInputFileNameAndLine() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function takes no parameters and returns information about the current "location". It reports the current line number and file being processed. This information is already available in other forms ( & ) however this routine simplifies getting it into a nicely formatted output. If you are interested in this call you should probably also check out the GetFileLineBeingProcessed() and GetLineBeingProcessed() calls. Example This example has been extracted out of the standard PPWIZARD header file NESTCHK.H which can detect and report details of nesting errors such as forgetting a "" tag. #DefineRexx NestingInc_REXX ;--- Ensure ID is valid ------- if symbol('{$ID $$SQx2}_Level') <> 'VAR' then Error('The ID of "{$ID $$SQx2}" is unknown (you must use "NestingInit")!'); ;--- Increase nesting level --- call _valueS "{$ID}_Level", {$ID}_Level + 1; ;--- Record details about current location --- call _valueS "{$ID}_FilePosn.{$ID}_Level", GetInputFileNameAndLine(); call _valueS "{$ID}_CurrLine.{$ID}_Level", GetFileLineBeingProcessed(); #DefineRexx #define NestingInc \ #evaluate '' ^<$NestingInc_REXX ID='{$ID}'>^ The reported output (on nesting errors) looks something like: NESTING ERRORS ~~~~~~~~~~~~~~ Missing 2 end nesting tags on "HTML TABLE tag" * line 8 of "E:\DB\PROJECTS\OS2\ppwizard\1.in" <<$TABLE> COLS=1 blah blah> * line 9 of "E:\DB\PROJECTS\OS2\ppwizard\1.in" <<$TABLE> COLS=2 blah blah> ═══ 5.9.31. GetLineBeingProcessed() ═══ GetLineBeingProcessed() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function takes no parameters and returns the text of the current line being processed. The line returned is after macro expansion and may or may not be as read from the file. The line as read from the file is available using the GetFileLineBeingProcessed() call. The returned line has been stripped of leading and trailing whitespace. This call would usually be called to remember details about a current situation which you may wish to report at some future stage. If using this call you may also wish to use GetInputFileNameAndLine(), see this section for an example of these calls in use. ═══ 5.9.32. Info() ═══ Info() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This routine takes a single parameter which is displayed as if the #Info command was used. ═══ 5.9.33. InputComponentLevel() ═══ InputComponentLevel() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This routine takes a single parameter which is the include level that you are interested in. The full name of the input file at that level is returned. If you don't pass any value then the current level is assumed. If you pass an invalid value the empty string ("") is returned. This rexx routine does a similar job to the "" special variable (but for any level - not just the current one). Stupid Example Simple example in which one file works out who included it and at what line: ;--- Work out who included this file (and what line) --- #evaluate ParentFile ^InputComponentLevel(-1)^ #if '<$ParentFile>' = ''
;--- Include all my photos ------------------------------------------ <$Photo Image="lazy.jpg" Title="Watching TV"> <$Photo Image="carback.jpg" Title="New Car (Back Left)"> Pictures There is no parent file! #elseif #evaluate ParentLine ^InputComponentLineLevel(-1)^
The parent file is: "<$ParentFile>" (line <$ParentLine>) #endif ═══ 5.9.34. InputComponentLineLevel() ═══ InputComponentLineLevel() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This routine takes a single parameter which is the include level that you are interested in. The line number being processed of the input file at that level is returned. If you don't pass any value then the current level is assumed. If you pass an invalid value the empty string ("") is returned. This rexx routine does a similar job to the "" special variable (but for any level - not just the current one). For an example of how it could be used have a look at the InputComponentLevel() routine. ═══ 5.9.35. IsDebugOn() ═══ IsDebugOn() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function can be called to simply determine whether debug is on or off or to determine the level of user debug currently active (see DebugLevel). This function would be useful if you wished to conditionally call Debug() or conditionally generate html comments in your output etc. The function takes either zero or one parameters as follows: No parameters indicates that you simply want a Y/N response to whether or not debug is on (similar to "" variable). If a parameter is supplied it should be a digit (one of 1, 2 or 3). If debug is off this routine will return 0 otherwise it will return the result of the supplied number anded to the value of the user bits (which of course could also result in 0). That is you can check on each bit seperately if you wish. If you simply wish to tell if any user debug state is on then pass 3, if you wish to check the state of one of your flags then pass it's value, a return code of 0 indicates that that level of debug is not on. ═══ 5.9.36. MacroGet() ═══ MacroGet() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function takes a single parameter (the name of a macro) and returns its contents. The macro must already exist (created by #define or #evaluate). The value of the macro is returned, if this contains any macros to be replaced, macro parameters or commands to be executed they are not replaced or executed. If you need parameter substitution you could create unique strings and use ReplaceString() to perform the "substitution" yourself. Note that there is also a MacroSet() routine. ═══ 5.9.37. MacroSet() ═══ MacroSet() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function is used to create a macro. Note that there is also a MacroGet() routine. The function takes 2 or 3 parameters as follows: 1. Name of variable. 2. The macros value. 3. Optional parameter, pass 'Y' if its OK to redefine the macro. ═══ 5.9.38. PadString() ═══ PadString() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function will generate a padded string, it can pad Left, Right or Center the string you supply. The function takes 3 parameters: 1. The string to be padded (never truncated if wanted length too short). 2. The length of the new string. 3. A single character (for Left, Right or Center). ═══ 5.9.39. ProcessNext() ═══ ProcessNext() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. PPWIZARD macros utilize a buffer to hold lines that they generate, these are read before the file is accessed. This function allows you to add data to be processed next. The function takes a single parameter which is the line or lines (for multiple lines they should separated with a newline character). This routine is handy where you may have captured some text, including references to macros etc and you wish to process the data where the data might otherwise be written directly to the output file. ═══ 5.9.40. QuoteIt() ═══ QuoteIt() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function will determine a quote character that is not contained within the string you pass. Processing will abort if it can not do so. The function takes 2 parameters: 1. The string that you wish to quote. 2. An option list of all possible quote characters. If not supplied it defaults to trying double then single quotes. This routine is handy when a macro is passed some information and needs to generate the data in a quoted format. Some languages such as HTML allow information to be quoted with either a single or a double quote. Stupid Example #evaluate '' ~RxQuote=QuoteIt('AS"DF')~ Should be double = ?RxQuote> #evaluate '' ~RxQuote=QuoteIt("AS'DF")~ Should be single = ?RxQuote> #evaluate '' ~RxContainsBothQuotes = 'AS"' || "'DF"~ #evaluate '' ~RxQuote=QuoteIt(RxContainsBothQuotes, '"' || "'^")~ Should be '^' = ?RxQuote> #evaluate '' ~RxQuote=QuoteIt(RxContainsBothQuotes)~ ;;Will die ═══ 5.9.41. ReplaceMacros() ═══ ReplaceMacros() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function takes a single parameter (the string) and will return a new string where all Macros and standard symbols have been replaced. ═══ 5.9.42. ReplaceString() ═══ ReplaceString() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function will convert all occurances of a substring as you specify. The function takes 3 parameters as follows: 1. The string which is to be translated. 2. The FROM string. 3. The TO string. When this routine returns the rexx variable ReplaceCount will have been incremented by the number of replacements made. Note that its faster to use BulkChar2String() to modify a whole lot of characters to strings. Of course converting single characters to other single characters is better done with the rexx translate() routine. If you need to do case insensitive changes then use the ReplaceStringCI() routine. ═══ 5.9.43. ReplaceStringCI() ═══ ReplaceStringCI() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function will convert all occurances of a substring as you specify. The function takes 3 parameters as follows: 1. The string which is to be translated. 2. The FROM string. 3. The TO string. When this routine returns the rexx variable ReplaceCount will have been incremented by the number of replacements made. This routine is very similar to the ReplaceString() except that it is case insensitive and that the "TO" string may contain one or more "{*}" strings which will get replaced with the "FROM" string. ═══ 5.9.44. ReverseArray() ═══ ReverseArray() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function is used to reverse the order of elements in an array. The "array" has numeric indexes with the ".0" element holding the number of elements. The function takes a single parameter which is the name of the array (without dot). The routine returns the number of items in the array. Silly Example ;--- Set up the array ----------------------- #evaluate '' \ ^ \ A.1 = "5345"; \ A.2 = "4123"; \ A.3 = "61743"; \ A.4 = "1678"; \ A.0 = 4; \ ^ ;--- Sort array & Reverse order & display --- #evaluate '' ^call SortArray "A"^ #evaluate '' ^call ReverseArray "A"^ #evaluate '' ^do I = 1 to A.0; say a.i; end;^ ═══ 5.9.45. RexGetTmpFileName() ═══ RexGetTmpFileName() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function returns the name of of currently non-existing file which can be used as a temporary file. If you want some control over the name of the file then you may pass a single parameter which is a filename with '?' in any positions where a "random" digit can be placed (example "IMP_????.TMP"). ═══ 5.9.46. SetEnv() ═══ SetEnv() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function takes two parameters as follows: 1. The name of the environment variable. 2. The new value ("" to delete it). The return value is the original value of the environment variable or "" if it did not exist. This command may be useful to pass information to any filters you may have set up (with /FilterInput or /FilterOutput). ═══ 5.9.47. SetId() ═══ SetId() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function is useful if you wish to ensure that when GetId() is called a specific value for an ID is used. An example of where this might be useful is if you have external entry points into a set of generated html pages. You normally would not care what they are called as long as all the links work, however as soon as you wish externally generated html to link to specific pages you must do something to ensure that the links name does not change. The function takes 3 parameters as follows: 1. A handle that was previously prepared with GetIdPrepare(). 2. The value (KEY) for which you are specifying an ID This is case sensitive, to make case insensitive simply convert your value to either upper or lower case before calling this routine. There is one situation where you may wish to pass a empty key ('') and that is when you specified unique ID mode on GetIdPrepare(). You would do this to pass an ID that you never want returned by GetId(). 3. The ID you wish to give to the value (KEY). Note that this is not validated in any way. It is up to you to ensure its correct. Example #evaluate '' ^call GetIdPrepare 'PPW'^ #evaluate '' ^call SetId 'PPW', '#define', "HashDef"^ ;;Set preferred ID #evaluate '' ^say GetId('PPW', 'MAXCHARS', 'define')^ #evaluate '' ^say GetId('PPW', 'MAXCHARS', '#define')^ ═══ 5.9.48. SortArray() ═══ SortArray() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function is used to sort a rexx array. The "array" has numeric indexes with the ".0" element holding the number of elements. The array can hold numbers or strings. The sort is always ascending. You can use the ReverseArray() routine if required. The function takes 1 or more parameters as follows: 1. The name of the array (don't include the dot). 2. If you wish to sort only over specific columns then the starting column number (first column is 1). 3. If the optional starting column was specified then this specifies the ending column. If not specified then the rest of the string is used. 4. This is an optional parameter. Do you want a strict compare? If you do then pass 'Y'. A strict compare does not ignore leading and trailing whitespace, however it won't correctly sort numbers. The routine returns the number of items in the array. If you are sorting a very large array with a fixed known name then you might wish to have a look at the faster and more powerful PPWSORT.H header file. Silly Example ;--- Set up the array ------------------------ #evaluate '' \ ^ \ A.1 = "ASDFG"; \ A.2 = "4123"; \ A.3 = "61743"; \ A.4 = "1678"; \ A.0 = 4; \ ^ ;--- Sort array & display -------------------- #evaluate '' ^call SortArray "A"^ #evaluate '' ^do I = 1 to A.0; say '"'a.i'"'; end; say ''^ ;--- Sort array (start column 3) & display --- #evaluate '' ^call SortArray "A", 3^ #evaluate '' ^do I = 1 to A.0; say '"'a.i'"'; end; ═══ 5.9.49. Summary() ═══ Summary() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function can be called to add (or remove) details on the displayed summaries. The function takes parameters as follows: 1. The text for the left hand side (before ':'). 2. The text for the right hand side (after ':'). 3. Type of summary line as follows: To see the details on this build's summary only then pass "" (or anything other than valid values shown below). To see the details on this build and all future build's (other files) summaries then pass "A" or "ALL". To see the details on the overall summary for all builds then pass "O" or "OVERALL". To drop summary details whether user or system generated pass "D" or "DROP", in which case parameter 2 is ignored. The text in parameter 1 must EXACTLY match that in a summary line. Example ;--- Don't want to see operating system version --- #evaluate "" "call Summary 'Operating Syst',, 'D'" ;--- Add a summary line to this build ------------- #evaluate "" "call Summary 'Left', 'Right'" ═══ 5.9.50. ToLowerCase() ═══ ToLowerCase() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function takes a single parameter and returns it in lower case. Note that there is no PPWIZARD "upper case" case routine as the standard rexx "translate()" routine with a single parameter does this nicely. ═══ 5.9.51. UrlDecode() ═══ UrlDecode() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function can be called to convert a string (encoded URL) back into its plain text format. The decoded string is returned. The parameters are as follows: 1. Input String This is the string which is to be decoded. 2. Mode Normally occurances of '+' are replaced with spaces. Pass "LEAVE+" to not handle the plus characters. ═══ 5.9.52. UrlEncode() ═══ UrlEncode() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function can be called to convert a string into a valid format for use in a URL. Characters such as '#' are converted to codes as they have special meanings when found within a URL. The new encoded string is returned. This routine should eliminate the need for having to see encoded URLs in your source code. The parameters are as follows: 1. Input String This is the string which is to be encoded. 2. Mode EncodeAll All characters in the input string are encoded, so that it can be called as a poor man's encryption scheme. It can hide stuff (at least from casual browsing) in plain html code etc. A space in not encoded as a plus. To% You need to supply a 3rd parameter which is a list of all characters that you would like to encode. A space in not encoded as a plus. ? If you can tell me a scheme that is required then let me know and I can add it... 3. Mode Dependent Parameters There may be one or more extra parameters depending on the mode. Example #evaluate 'HiddenText' ^UrlEncode("Password", "EncodeAll")^ ═══ 5.9.53. Warning() ═══ Warning() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This routine is probably most useful in #import filter code and takes a two parameters. The first parameter is the message ID and the second is the message text, see the #warning command for more details. The passed warning message will be displayed. ═══ 5.9.54. WriteLineToTmpImportFile() ═══ WriteLineToTmpImportFile() This is a rexx function provided by PPWIZARD. This routine (like all PPWIZARD extensions) can be used with any operating system supported by PPWIZARD. This function takes a single parameter and has no return code (on failure PPWIZARD will terminate). It must only be called while #Import is being processed. You may pass one or more lines of data which will be written to the temporary file that pass one of an import generates. To indicate the end of a line the Linefeed character (decimal 10) should be used the actual characters written to the file are determined by the /CrLf state. For an example have a look at a complex import example. ═══ 5.9.55. _filespec() ═══ _filespec() This is a rexx function provided by PPWIZARD. This routine is named similar to an OS/2 specific call with a similar purpose, this PPWIZARD version works in all operating systems supported by PPWIZARD. This function takes two parameters as follows: 1. The part of the filename to extract. Valid are (note you are also allowed to passed only the 1st character of each command): drive - Drive (example 'C:') path - Path (example '\OS2\') name - Shortname (example 'XCOPY.EXE') location - Location (example 'C:\OS2\') extn - Extension (example 'EXE') withoutextn - No extension (example 'C:\OS2\XCOPY') 2. The name of the file. The return value is the extracted component you requested. It is important to note that a partial filename is not converted to its full name before extraction, the part is extracted from what you supply. It is also assumed that the filename is of a valid format. Example ;--- Capture some HTML information --- #evaluate ShortNameHtml ^_filespec('name', '')^ ═══ 5.9.56. _SysFileDelete() ═══ _SysFileDelete() This is a rexx function provided by PPWIZARD. This routine is named similar to an OS/2 specific call with a similar purpose, this PPWIZARD version works in all operating systems supported by PPWIZARD. This function takes a single parameter which is the filename to delete. This routine returns a non-zero return code on error. ═══ 5.9.57. _SysFileTree() ═══ _SysFileTree() This is a rexx function provided by PPWIZARD. This routine is named similar to an OS/2 specific call with a similar purpose, this PPWIZARD version works in all operating systems supported by PPWIZARD. This function takes two parameters as follows: 1. The name of a file or directory to look for (normally containing wildcard characters appropriate to the operating system being used). In linux specify a directory name with a terminating slash to capture all files or subdirectories in that directory. 2. The name of a rexx stem (array) to place the list of matching files (example "Files"). On return "Files.0" contains the number of files, "Files.1" contains the first filename etc. 3. List of options, supported are: D - Directories only. F - Files only (default). S - Follow subdirectories. If successful a return code of 0 is returned. The contents of the "array" may not be valid if an error occurred so always either check the return code or preset the ".0" element to 0 before making the call. The full (absolute) name of files is always returned, however the names of directories may be absolute or relative depending on what you passed as the first parameter to this routine. ═══ 5.9.58. _SysSearchPath() ═══ _SysSearchPath() This is a rexx function provided by PPWIZARD. This routine is named similar to an OS/2 specific call with a similar purpose, this PPWIZARD version works in all operating systems supported by PPWIZARD. This function takes two parameters as follows: 1. The name of an environment variable which contains a sequence of directories to be searched (such as "PATH"). Unix unix directories should be separated by ':', for all other operating systems the ';' character should be used. 2. The file to be searched for. The return value is the full name of the file or '' if not found. ═══ 6. Dependancies ═══ Dependancies If you know what a make file does then this is basically the functionality PPWIZARD is trying to supply. Once you have built your output files you don't need to rebuild them unless you modify one of your source files. PPWIZARD actually does a very much better job than any make file based process. Lets consider a very complicated example where: 1. The source file is called "INPUT.IT". 2. It #includes "MACROS.IH". 3. For some stupid reason it reads in line one of "CONFIG.SYS". 4. It creates "OUTPUT.OUT" and "ALSO.OUT". 5. You have many other ".IT" files with their own dependancies. The whole process might take a while. You really only want to preprocess the above 3 input files to produce the 2 output files if you need to. PPWIZARD stores information in a dependancy file for each compile which will allow it to check whether a build is required or not. It will detect if any input or output files have changed or if they are missing and begin to rebuild the output. To conditionally make your ".IT" files you could use: ppwizard.cmd *.it /output:out\*.htm /CrLf /DependsOn:Depends\*.dep This command says to make "*.IT" and put all output into the "OUT" directory and creates a "DEPENDS" directory and places dependancy information in this directory. Most dependancies can be handled by the preprocessor but sometimes you need to help identify the input and output files. For example you probably used a rexx linein() command to read from "CONFIG.SYS", you will need to use the #DependsOn command to indicate this one. In a similar manner the example generates 2 output files, if you used the rexx lineout() command to create these then you would again need to use the #DependsOn command to indicate this output dependancy. ═══ 7. Commands ═══ Commands The following commands are available to you when you use the PPWIZARD.CMD Preprocessor: #AsIs #AutoTag #AutoTagClear #AutoTagState #debug #define[+] #DefineRexx[+] #DependsOn #ElseIf #EndIf #EOF #error #evaluate[+] #if #IfDef #IfNDef #import #include #Info #MacroSpace #OneLine #OnExit #option #output #require #RexxVar #UnDef #warning The following commands allow you to perform PPWIZARD looping: #{ #} #break #continue ═══ 7.1. #{ ═══ #{ This command is used to define the start of a loop which ends with the "#}" statement. You may use the #continue to restart at the top of the loop and #break will cause you to exit the loop. Restrictions 1. Both the start and end of a loop must occur within the same input file. 2. Loops can't be nested (within a single file). 3. Since PPWIZARD loads the whole loop without processing lines in between the affect of any intermediate "HashPrefix" option is ignored for the purposes of finding the end of the loop. Example 1 - Loop 12 Times ;--- Output 12 text lines --------------------------------------------------- #RexxVar Count = 1 ;;"#RexxVar" is fastest way to set or update a rexx variable #{ ;--- Output one line ----------------------------------------------------- From Loop #?Count>
;--- Only do 12 times ---------------------------------------------------- #RexxVar Count + 1 #if [?Count> > 12] ;;Note the square brackets to improve performance (since simple test) #break ;;Now done 12 times #endif #}
;;Break sends us here Example 2 - Read File Until End This example is used to load a list of languages and to create a directory for each ones generated html. The languages file looks like: en ;;English it ;;Italian fr ;;French The code to read the above file and create the directories is: ;--- Code written for OS/2 so gain access to rexx extensions ---------------- #evaluate "" "call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'" #evaluate "" "call SysLoadFuncs" ;--- Define some directories ------------------------------------------------ #define site.root C:\sitetest #define site.out.dir <$site.root>\html ;;output root ;--- Make required base directories ----------------------------------------- #evaluate "" "MkDirRc=SysMkDir('<$site.root>')" #evaluate "" "MkDirRc=SysMkDir('<$site.out.dir>')" ;--- Make language directories ---------------------------------------------- #define LanguageFile "LANG.IH" ;;Note in this case would be more CPU efficent if rexx variable #DependsOn INPUT <$LanguageFile> #evaluate "" ^CloseFileRc = stream(<$LanguageFile>, 'c', 'close');^ #{ ;--- Exit on EOF --------------------------------------------------------- #if lines(<$LanguageFile>) = 0 #break #endif ;--- Read the language line, strip out comment and make directory -------- #evaluate "" "MkDirRc=SysMkDir('<$site.out.dir>\' || '=word(linein(<$LanguageFile>), 1)>')" #} #evaluate "" ^CloseFileRc = stream(<$LanguageFile>, 'c', 'close');^ ═══ 7.2. #} ═══ #} This command is used to define the end of a loop the start of which must also occur within the same input file. Please see the "#{" command for an example and more information. ═══ 7.3. #AsIs ═══ #AsIs This command is frequently used to allow you to #include real working code as examples. Any modifications required to get the file (or part of) to display "as is" occurs automatically as programmed by you. Turning on "asis" mode basically allows you to read in text without PPWIZARD getting in the way. More than this is can simplify issues such as the fact that the viewer may not be able to display certain characters unless converted. For example a html viewer may have trouble with '<' characters unless they are converted to '<'. Turning "asis" mode on will modify a number of PPWIZARD #Options so that lines will get passed through "as is". This means blank lines are kept, line comment and continuation is ignored and a number of other options may be modified. Use "#Debug" to see all that are modified. While #AsIs mode is turned on, PPWIZARD commands are still processed. This is fine if your examples either don't include ppwizard commands or you wish to conditionally include parts of the example. If you did not want this you would need to use the "HashPrefix" option or take some other action to prevent it. You may need to do more than this to get the effect you desire. For example to have have the lines appear in a HTML browser as they do in your source you will need to do more work (or blank lines get removed and long lines wrap etc). The minimum you would require for HTML is to use&tags around the lines. Using "" as mentioned above only handles part of your issues with a HTML browser, any html tags such as "" will get interpreted by the browser and generate a new paragraph. This is fine if that was your intention however you probably wish to see the characters "
" in the browser. You could make use of the "#AutoTag" or "#AsIs" autotagging facility to convert all occurrances of "<" to "<". Its normally more flexible to have basic autotagging such as that mentioned for the "<" character handled by this command and any extensions to the fundamental changes handled by the "#AutoTag" command. You would also wish to check out the "#AutoTagClear" & "#AutoTagState" commands. There are some tricky bits that you may need to handle - such as how do you tell PPWIZARD where the end of the example code is. If you are not careful any end of example marker you place could get autotagged in such a way that PPWIZARD will not recogise it! This can be tricky, to see examples of how this can be handled, see my "OL_DOC.DH" header file which handles examples for IPF and HTML examples. All AsIs tagging is performed before "#AutoTag" tagging. As mentioned earlier it can be difficult or impossible (in some situations) to escape out of an "example" mode that you set up. It will help you to remember that all autotagging is case sensitive and only occurs on data as it is read from a file (not on lines from memory/macros). If you don't get the results you expect you will need to use "#debug" or "/debug" to watch what occurs. In debug mode lines from a file are show in a similar manner to "0012:" where a line from memory could be shown as "####:". Like autotagging you must be very careful in the order that you tag things for example specifing that '<' gets replaced with '<' and then that '&' gets replaced with '&' is wrong as you would be tagging the '<' from the first replacement. For the example given here you would need to swap the order, in other cases you may need to use an intermediate 'unique' string and convert it back as the last change. If possible try and group changes so that all single character changes are together this allows PPWIZARD to perform faster replacments as it can make good use of the BulkChar2String() routine. Syntax [WhiteSpace]#AsIs ["]SETUP["] ["]NAME["] OR [WhiteSpace]#AsIs ["]OFF["] OR [WhiteSpace]#AsIs ["]ON["] [["]NAME1["] ...]> The "SETUP" command is used to store all currently defined "#AutoTag" commands under the "NAME" you supply. The existing AutoTags are cleared. The "OnOrOffCommand" specifies whether or not "asis" mode is on. When turning #AsIs mode on you may specify one or more named sets of tags that were previously set up with "SETUP". Example - SETUP ;--- Setup minimum tagging for IPF lines --------------------------------- #AutoTagState + ;;Lets not effect current tags #AutoTag "&" "&." #AutoTag ":" "&colon." #AsIs SETUP IpfAsIsChanges ;;Copy tags and clear (name tags "IpfAsIsChanges") #AutoTagState - ;;Restore Original AutoTag state Example - Including Example File The following is an example of a macro which will display an example file with a nice border and title (in a table). The included file does not contain conditional commands etc (or if it does we want to see it as part of the example). This is one example of a macro you could use: #define IncludeExampleFile \
{$TEXT} \ |
---|
\
\ \ #AsIs ON HtmlAsIsChanges \ #AutoTag ON \ #option PUSH HashPrefix="#$@!" \ #$@!include "{$FILE}" \ #$@!option POP ;;Restore Prefix \ #AutoTag OFF \ #AsIs OFF \ \\ |
Paragraph before barbed wire. <$ImgBarbedWire>
Paragraph after barbed wire. Example 2 - Parameters Used ;--- Define an image ------------------------------------------------------- #define AnImage ;--- Refer to image twice, each with different size ------------------------
Image at Size 1 = <$AnImage WIDTH="100" HEIGHT="33">
Image at Size 2 = <$AnImage WIDTH='200' HEIGHT=|66|> ;--- Define an image ------------------------------------------------------- #define AnImage2 > ;--- Refer to the image supplying any and all parameters -------------------
Image = <$AnImage2 All=/ALT="{An Image}" WIDTH="100" HEIGHT="33"/> ;--- Refer to the image supplying NO parameters ----------------------------
Image = <$AnImage2 All="">
Example 3 - Contains Logic
;--- Define a macro that can be used to include my example files -----------
#define IncludeExampleFile \
{$TEXT} \ |
---|
\
\ \ #AsIs ON \ #include "{$FILE}" \ #AsIs OFF \ \\ |
Hi, my name is Dennis Bareis and I have been using OS/2 and developing for \ #if ['<$AtWork>' = 'Y'] \ ANZ \ elseif \ *WRONG INC* \ endif \ on and off since the original 1.0 version. ═══ 7.19. #ifdef ═══ #ifdef A #ifdef command (like #if and #ifndef) can be used to conditionally include lines of text, this can be any other type of line or command except #elseif or #endif. #if commands can be nested to any level and there need not be any lines between a #if command and a #endif or #elseif command. Note that this command only checks on a single variable, for more complex requirements you will need to use a #if command along with calls to the Defined() routine. For performance reasons its recommended that you use #ifdef and #ifndef commands where possible. Syntax [WhiteSpace]#ifdef VariableName The "VariableName" specifies a variable that should exist for the test to evaluate to true. Example #define Fred FredsValue #ifdef Fred ... #endif ═══ 7.20. #ifndef ═══ #ifndef A #ifndef command (like #if and #ifdef) can be used to conditionally include lines of text, this can be any other type of line or command except #elseif or #endif. #if commands can be nested to any level and there need not be any lines between a #if command and a #endif or #elseif command. Note that this command only checks on a single variable, for more complex requirements you will need to use a #if command along with calls to the Defined() routine. For performance reasons its recommended that you use #ifdef and #ifndef commands where possible. Syntax [WhiteSpace]#ifndef VariableName The "VariableName" specifies a variable that should NOT exist for the test to evaluate to true. Example #define Fred FredsValue #ifndef Fred ... #endif ═══ 7.21. #import ═══ #import Many programs and databases (Microsoft Excel or Access, Lotus 123 etc) allow you to export data in many different formats. The #import command allows you to import the most common formats and generate output to your specification. The default output format for quite a few of the import types is a HTML table. Not only don't you need to generate a table at all, you also have a lot of fine tuning parameters if you wish to remain with a table but just wish to tweek its look (give certain columns a special background color etc). I have seen people generate a whole series of #define and #include commands to generate a separate html page for each record (from a product database). This command might seem complicated at first (and in actual fact it is!), I recommend you actually try the examples (cut and paste as required). If you are having problems working out what is going on I highly recommend the use of debugging (/debug or #debug) as this has been designed not just for debugging but for training as well. Note I recommend that if debugging you cut your database down to a few test records so that you won't be swamped with output. Import Processing Details All import types get handled in two distinct passes as follows: 1. The imported file is read, processed (including calls to your rexx filter code if defined) and the output is generated to a temporary file. If you have a filter then in some advanced applications you may need to use the WriteLineToTmpImportFile() routine. An example of this is if you wished to generate PPWIZARD commands such as #output. 2. The temporary file is read in and processed in exactly the same manner as any file that you yourself might include with a #include command. This is where any macros you may have referenced as expanded. If debug is not on then after pass two completes the temporary file is deleted. Turn debug on an examine the temporary file if things are not going to plan! Syntax [WhiteSpace]#import ["]File2Import["] ["]T2H|WRAP["] ["]DefineName["] OR [WhiteSpace]#import ["]File2Import["] ["]ImportType[-]["] ["]DefineName["] ["]FieldInfo1["] ... The parameters are as follows: 1. File2Import This is the name of the file to be imported. Blank lines are ignored (is this causing anyone problems?). 2. ImportType This describes the format of the data to be imported. If the type has "-" appended then the first lines of the file are dropped (default is one line). The currently supported types are: SQL PPWIZARD does not support SQL directly but it doesn't need to as it can interface to any database if a rexx interface is available. CMA[-] All fields are comma delimited (fields can't contain commas unless quoted). Fields may be empty. Blank trailing fields may be missing. TAB[-] As above except a tab (ascii 9) is the delimiter. ???[-] As above except you specify the exact delimiter you want. For example "^^^" indicates that you wish a delimiter of "^". FIX[-] Unlike all previous types there is no delimiter. Items appear in fixed columns in the file. While you can play with "FieldInfo" there is not much point as you can specify all the fields you want in the order you want them. ML Each record spans multiple lines and ends with a blank line. Each field takes up a line and specifies a field name and a value separated by a user defined delimiter ('=' by default). T2H This is a text to HTML type import. WRAP This is a specialised import facility. You get passed a line at a time and you decide how to handle it. 3. DefineName This parameter gives you a lot of control over how your output is generated. The value you supply here is used as a prefix for all your import options. As an example, if you specified "FRED" as a value then some import types would look for a #define of "FRED_DROP_BLANK_LINES" to see if you wished to override the default handling of blank lines. The exact #define options which are available will differ depending on the import type. If you specified a blank value for the prefix a default is used. The name of the default also varies with import type but for the common types is "IMPORT". In some cases such as when HTML tables are generated there are multiple levels of defaults and changing a lower level one may have no effect if you also override a higher one. This is because the lower level values became the default values for the higher level. As an example there is no point specifying that record columns should have a background color of green and then overriding the record generation default! Again the use of debugging support will generally make this clear as it will show PPWIZARD looking for all options and display the value PPWIZARD has decided to use. ═══ 7.21.1. #import - SQL DATABASES ═══ #import - SQL DATABASES This example shows you how to access data using the "mSQL" (free) database program. The database we will process is called "supersite" and the table we will access is "link". This example makes use of Mark Hessing's RexxSQL library to access the database program. It's free and is available for multiple operating systems and can access many different database programs. Its available from "http://www.lightlink.com/hessling/". You may want to have a look at the #evaluate routines AsIs() and AutoTag(). mSQL EXAMPLE ;--- Very simplistic start of HTML ------------------------------------------
{$title}: {$description} ;;HTML for each record (note that it would be more efficient (but less "clean") to just pick up rexx variable names here ;--- Enable PPWIZARD to make use of external SQL library -------------------- #evaluate '' "call RXFuncAdd 'SQLLoadFuncs', 'rexxsql', 'SQLLoadFuncs'" #evaluate '' "call SQLLoadFuncs;" ;--- Connect to the data base ("supersite" on local machine) ---------------- #evaluate 'ConnectRc' "SQLConnect('PPW',,, 'supersite', 'localhost')" ;--- Perform a database query (on the table "link") ------------------------- #evaluate+ 'QueryRc' ^SQLCommand('RxLink', 'SELECT * FROM link WHERE category = <$QueryCategory>')^ #info 'QueryRc = <$QueryRc>' #info 'Number of records is ?RxLink.url.0>' ;--- Generate the html (for simple list) ------------------------------------
" (preformated text) mode is set up. Modify or set to blank (to do nothing) if you wish. DefineName_AFTER These tags are used to set up any tags that are required after the file is included. This normally undoes anything you started using the previous define. DefineName_BLANK_LINES_TO When text is processed in "PRE" mode (see above) you want to leave blank lines as they are. If however you set up the before tags to be "" and cleared the after tags then you could convert blank lines to "
, in this way a blank line indicates the end of a paragraph. DefineName_ASIS_TAGGING This option can be used to adjust the conversion of what may be problem characters (such as '<' in HTML). By default importing does not handle/convert international characters such as umlauts to html symbols but there is nothing preventing you from doing so. Note that you will probably need to override this value (maybe others as well) if you wished to expand any macros that the imported data might contain (by default this is not done). DefineName_TAB_CHAR Normally tabs are ignored by the import process. This variable allows you to replace them with something else. DefineName_HTTP_LINK The import mode looks for "http:" type web addresses and by default converts the URL into a hypertext link. You may not wish this so you could clear this variable. You might wish to simply highlight the URL. DefineName_FTP_LINK The import mode looks for "ftp:" type ftp addresses and by default converts the URL into a hypertext link. Otherwise as per the "_HTTP_LINK" option. DefineName_RECORD_FILTER This option allows you to modify records before they are written to the intermediate file for processing. The value you supply for this option is a rexx expression that can be interpreted. You could use this to simply drop lines or the data can be modified by you. The following rexx variables are relevant: - Remove If this variable is set to any non blank value then the line will be dropped, the variables value is shown when debugging so it is recommended that the value be the reason for dropping the record. If the contents starts with 'EOF:' then the current record and ALL following are dropped. - T2hLineNumber This is the line number of the current line. Do not modify this variable. - T2hFileLine This is the line as read from the file. Do not modify this variable. - T2hNewLine This is the read in line converted to something that will display well in HTML. May have had email addresses etc tagged. This variable may be modified. - T2hFilter If you don't need to do any more filtering then you can clear this variable. This will improve performance. DefineName_PROTECT_START By default will be set to the value . If you have filter code that wants to generate PPWIZARD commands then you will need to override this value. Have a look at the multiple HTML pages example. DefineName_PROTECT_END By default will be set to the value . EXAMPLE This example imports a file and also extends the translation it will perform to include 2 international characters. For no real reason we will also prevent email addresses becoming "mailto" links and simply highlight email addresses in a different color. ;--- Save current Autotag state, set up international conversion, restore state --- #AutoTagState + #AutoTag 'Д' 'ä' #AutoTag 'Й' 'ë' ;;Only 2 for this example #AsIs SETUP INTERNATIONAL_SYMBOLS #AutoTagState - ;--- Update option so as to use the international chars as well as usual conversions - #define T2H_ASIS_TAGGING IMPORT_HTML_BASIC \ IMPORT_HTML_BOXGRAPHIC_TO_BOXTEXT \ INTERNATIONAL_SYMBOLS ;--- Simply for demonstrate puroses, remove email links and make "olive" --- #define T2H_MAILTO_LINK {$Url} ;--- Import the text file --- #import README.TXT T2H "" ═══ 7.21.6. #import - WRAP ═══ #import - WRAP This is a specialised #import facility. WRAP DEFINITIONS/OPTIONS These definitions are specific to the "WRAP" import mode. If you can't understand how they work then I suggest you try using /debug or #debug to watch what variables the import uses etc. DefineName_DROP_BLANK_LINES You can specify whether or not blank lines (or lines where all fields are blank) are significant. The default is 'Y' to drop blank lines, specify 'N' to prevent this. DefineName_TAB_CHAR Normally tabs are ignored by the import process. This variable allows you to replace them with something else. DefineName_ASIS_TAGGING This option can be used to adjust the conversion of what may be problem characters (such as '<' in HTML). By default importing does not handle/convert international characters such as umlauts to html symbols but there is nothing preventing you from doing so. Note that you will probably need to override this value (maybe others as well) if you wished to expand any macros that the imported data might contain (by default this is not done). DefineName_RECORD_FILTER This option switches between 2 alternative ways of handling each line of data as follows: 1. Option Not used The macro you identify with the "DefineName" parameter is passed each line in turn (line passed as the macro parameter "Line"). The line is passed as a rexx statement which when executed will restore the line. Your macro can do anything it likes as it determines what if anything get generated. 2. Option used The rexx code that you specify is called for each line. The following rexx variables are relevant: - Remove If this variable is set to any non blank value then the line will be dropped, the variables value is shown when debugging so it is recommended that the value be the reason for dropping the record. If the contents starts with 'EOF:' then the current record and ALL following are dropped. - WrapLineNumber This is the line number of the current line. Do not modify this variable. - WrapLine This is the line as read from the file. You would normally modify this variable. Example of WRAP Import Assume "PEOPLE.TXT" contains people data of the following form (each record spans 3 lines with blank lines being ignored and little validation of data): Harry 18 male Lisa 20 female Then we could create a simple HTML table as follows: ;--- Define some macros to handle the imported data ---------------------- #define InitMultiLineFieldImport \ #RexxVar RxFieldCount = 0 #define TermMultiLineFieldImport \ #if [RxFieldCount <> 0] \ #error "Incorrectly specified record, have ?RxFieldCount> of 3 fields" \ #endif #define EachLine \ ;--- "read" the line (no blank lines) ------- \ #evaluate+ '' ^ThisLine = strip({$Line})^ \ \ ;--- Save information ----------------------- \ #RexxVar RxFieldCount + 1 \ #RexxVar RxField_?RxFieldCount> = ThisLine \ \ ;--- If end of record then output it -------- \ #if [RxFieldCount = 3] \
?RxField_1> is ?RxField_3> and ?RxField_2> years old \ #RexxVar RxFieldCount = 0 \ #endif ;--- Start the table ----------------------------------------------------- <$InitMultiLineFieldImport>
<$TermMultiLineFieldImport> ═══ 7.22. #include ═══ #include A #include can be used to include another file for processing. This allows you to split a very large complicated html file into smaller logical pieces or more commonly to include standard 'header' files which contain all or most of the common definitions/text. You can nest to any level however each level adds to the number of open files (unless you use the /Inc2Cache switch) so in reality the nesting level is system dependant. Another problem may be that the rexx intrepreter will have its own limit on how far you can nest files. On OS/2 (and probably other operating systems) there are mechanisms for increasing the numbers of file handles if required. For example on OS/2 version 4 fixpack 6 onwards to increase the numbers of available handles by 30 add "SET SHELLHANDLESINC=30" to your config.sys file. The convention for extensions that I use are as follows: .IT - Internet Text (source code) .IH - Internet Header (source code) .HTM - Generated HTML .D - Document Main (source code) .DH - Document Header (source code) It is possible for a header file to validate the release of a preprocessor if it needs to use a feature which may not be available in older release, please see the example. Note that there are times when you might wish to share a file between 'C' code and PPWIZARD, you might just wish access to some of the values defined with #define statements. If you can't ensure that all commands (and their parameters) that the 'C' code uses are valid in PPWIZARD then you could: 1. Conditionally include portions (example "#ifndef _PPWIZARD_"). Note that "_PPWIZARD_" is automatically defined by PPWIZARD. 2. Use the #autotag commands to modify the contents on the file to convert invalid statements to valid ones (bit of a hack but would work). It is also possible to include a part of the identified file if you can identify some text which marks the start and end of the parts you wish. Note that if an input file can't be located (relative to the current directory), the following environment variables paths will also be searched (in order): 1. PPWIZARD_INCLUDE 2. INCLUDE After searching the above locations the directory PPWIZARD is located in is also examined. Syntax [WhiteSpace]#include ["|']FileName["|'] [["]Fragment["]] OR [WhiteSpace]#include ;--- Import the data (leaving default at dropping blank lines) ----------- #import "PEOPLE.TXT" WRAP EachLine ;--- End The table -------------------------------------------------------
[["]Fragment["]] The "FileName" specifies the file to be included. If the filename is or contains #defined variables they will be replaced. Note that the "<" & ">" quoted form is to make it compatible with existing "C" headers so you can use these if you require. The optional "Fragment" parameter can be used to indicate the start and end of the portion of an included file you wish to process. The text must exist on the line immediately before and immediately after the part you need. Note that the comparison is case sensitive on unfiltered text. This parameter allows you to create a single include file from what might have been tens of very small files (fragments). I will use this parameter to contain all my example code for my documentation. Example #include "common.ih" #include 'common.ih' ^ ^ #include ═══ 7.23. #Info ═══ #Info A #Info command allows you to display an informative message to the user. Similar commands are: 1. #Error 2. #Warning Syntax [WhiteSpace]#Info [']InfoMessage['] The "InfoMessage" specifies the text to be displayed. Example Stupid example follows: #Info "The value "fred" is fine." ═══ 7.24. #MacroSpace ═══ #MacroSpace A #MacroSpace command allows you to add or drop rexx procedures from the rexx macro space. This can be useful if you have some rexx code which you frequently call in #if or #Evaluate commands as they should execute faster if they are available in the macro space. Syntax [WhiteSpace]#MacroSpace ["]Command["] ["]RexxSourceFile["] [["]FunctionName["] ]> The "Command" should be "ADD" to add to the macro space or "DROP" to remove. It is not an error to ADD or DROP the same code more than once (even in a row). Also note that unless you perform a drop when you have finished using it it will take up space until you reboot OS/2. The "RexxSourceFile" is the name of a rexx source file. It should be a relative or absolute filename that currently exists. The path is not searched. If the optional "FunctionName" is not supplied then the function name is the "RexxSourceFile" without path or extension. Example ;--- Load macro (routine called "ConfigInf" - any case) ----------------- #MacroSpace ADD "CMD\CONFIGINF.CMD" #if ConfigInf('TCPIP_ADDRESS') = '' #Error "A TCPIP address is not available...." #endif ═══ 7.25. #OneLine ═══ #OneLine This command provides a simple way to spread a long line of over many lines without the need for line continuation characters at the end of each line. Basically you define a block, within this block all lines are combined with the character(s) you chose used to separate the lines. Note that if some lines within the block need different line separators, you can still use the normal line continuation characters for these lines! It is recommended that you do not use this command to handle rexx code, use the #DefineRexx command instead. Note that the restriction of on long imbedded ppwizard command mentioned in the line continuation section also applies here. Syntax [WhiteSpace]#OneLine [["]Separator["] [["]EndBlockMarker["]]>]> If the Separator parameter is supplied it defines the zero or more characters that separate each line within the block. The default separator is a space. If the EndBlockMarker parameter is supplied this determines the text that marks the end of the block, this can be any text and by default is "#OneLineEnd" (note that the current prefix is used). Lines are combined until this text is located (in this exact case). EXAMPLE #OneLine #define SomeWords The rain in sp -\ ain falls mainly on the plain #OneLineEnd ;;Marks end of block! #OneLine '' '@@' T h e rain @@ ;;Marks end of block! ═══ 7.26. #OneLineEnd ═══ #OneLineEnd There is no such command although it may at first glance appear so. The text "#OneLineEnd" is simply the default end of #OneLine block marker if no alternative was specified. ═══ 7.27. #OnExit ═══ #OnExit This command allows you to register some text which after all other processing is itself processed as if it were read from a file. This command is useful in standard header files where rather than requiring a user to use a macro before exiting it can be done automatically. An example of this might be in a common html header file where you use this command to automatically generate a standard footer at the end of your html. This command may be used any number of times, the "on exit" processing occurs in the order that the commands were executed. Note that the processing does not occur if a fatal error was detected. Syntax [WhiteSpace]#OnExit TheText The text can be anything (macro reference etc). The parameter(s) are not expanded until exit processing occurs. The following is used in one of my header files: ;--- Register checking macro --- #OnExit <$NestingCheck> ═══ 7.28. #option ═══ #option This command is used to change the state of all the PPWIZARD options that you might wish to modify within a compile. Other options which are global and can't be modified can be specified on the command line. The command allows you to save and restore the current state as well as update one or more options at a time. Most if not all options allow you to reset to the default value, this can either be a value determined by PPWIZARD or overriden by you with the /option switch. Note that to restore the original values you should use the 'PUSH' and 'POP' options. Note that since you can define options using the /option switch and default switches can be set up in the environment, you can simply override any PPWIZARD defaults you don't like without having to change your source code (or even your command line!). Syntax #1 - Saving + Restoring State [WhiteSpace]#option PUSH | POP This form of the command saves or restores all options controlled by the #option command. This allows you to make the required option changes and restore the original situation if required (for example in a header file). Syntax #2 - Setting An Option [WhiteSpace]#option OptionName[WhiteSpace]=[WhiteSpace]["]NewValue["] ... You may have any number of options specified on one statement. While not shown in the syntax diagram above you can specify "PUSH" any number of times as well. The following options are currently available: AllowPack AllowSpell AtChangeType CsReplacement DebugLevel DefineMacroReplace ExtraIndent ExpandX HashPrefix KeepIndent LeaveBlankLines LineComment LineContinuation MacroParmTags Replace ReplacementTags WhiteSpace Example #option PUSH ;;Save Current state (we don't need to know what it was - EXCEPT '#' = command prefix!) #define FRED **** <$Fred> ;;Fred will be subsituted here #option ReplacementTags="[]$?" [$Fred] ;;Fred will be substituted here <$Fred> ;;Fred will NOT be subsituted here #option POP ;;Restore original state ═══ 7.28.1. AllowPack ═══ AllowPack=OnOrOff This #option command allows you indicate lines of code which are not allowed to be packed. The default is that packing is allowed. This option can not be used to turn packing on, it simply identifies areas that should not be packed when packing is enabled. Packing can be enabled using the /Pack switch when generating rexx code or when you begin a #DefineRexx block. This command is useful where there are some non-obvious reasons why code should not be packed, for example if a bug in the rexx interpreter causes the code to fail when packed. If the "OnOrOff" parameter is empty then it defaults to the current default value, otherwise one of the following is expected: ON OFF YES NO ═══ 7.28.2. AllowSpell ═══ AllowSpell=OnOrOff This #option command allows you indicate lines of code which are or are not allowed to be spell checked. The default is that spelling is allowed. This option would allow you to indicate that spelling should not occur when you generate javascript etc. Note that there are currently some inter related restrictions: 1. You can only turn spell checking on or off for whole lines. 2. This option may not work in a macro depending on your macro. If the "OnOrOff" parameter is empty then it defaults to the current default value, otherwise one of the following is expected: ON OFF YES NO ═══ 7.28.3. AtChangeType ═══ AtChangeType=["]ChangeType["] This #option command lets you alter the way #AsIs and #AutoTag commands will perform replacements. The default method is a simple case sensitive replacement of text. Note that this command actually changes the way the #AutoTag stores the change and will only affect the replacement of those changes defined after this option was used. This command allows new alternative search and replace mechanisms to be slotted in without affecting any existing ones (clashing syntax etc). This method was chosen so that PPWIZARD could remain as fast as possible (it is written in rexx and so keeping performance reasonable sometimes takes compromises). The "ChangeType" parameter can be one of the following: 1. "" (blank) This returns to the "default" mode. 2. CaseSensitive The ReplaceString() routine is used. This is PPWIZARD's default mode as its also the fastest. 3. CaseInsensitive The ReplaceStringCI() routine is used. 4. Fixed The CompareReplaceFixed() routine is used. If you have some fantastic free PURE REXX search and replace code then I can include it as a new PPWIZARD extension if you send me the code! Example 1 #AutoTag "AAAA" "XXXX" ;;Change upper case "AAAA" only (assuming default mode) ;--- Use ReplaceStringCI() --------------- #option PUSH AtChangeType=CaseInsensitive #AutoTag "BBBB" "YyYy" ;;Change "bbbb" in any case #AutoTag "CCCC" "({*})" ;;If "cccc" in any case is found then surround it by brackets ;--- Use CompareReplaceFixed() ----------- #option AtChangeType="FIXED" #AutoTag '@=,1=^HTML^@=,5=+x+' 'REM CS->@$1,*;' ;;Case sensitive compare for "HTML" then "x" #AutoTag '!i@=,1=^HTML^!S@=,-1=+x+' 'REM CI->@$1,*;' ;;Case insensitive comapre for "HTML" + sensitive compare for "x" #AutoTag '!L!i@=,1=^HTML^!S@=,5=+x+' 'REM CI+spaces->@$1,*;' ;;Same as above but ignoring whitespace (leading) #option POP ;;Restore mode (PUSH/POP useful where original mode unknown etc) ═══ 7.28.4. CsReplacement ═══ CsReplacement=OnOrOff This #option command lets you alter the way ppwizard performs macro replacement. By default ppwizard macro names and macro parameter names are case insensitive. This command allows you to specify that case matters. This will give ppwizard more flexability when generating certain languages (such as XML). Note that Standard Definitions and rexx variable names are always case insensitive. You will need to be careful how you use this option (if not used early in the piece). Any macros created while this option was off were created in upper case, while any parameters within the definition don't matter until the replacement takes place. If the "OnOrOff" parameter is empty then it defaults to the current default value, otherwise one of the following is expected: ON OFF YES NO Example #option CsReplacement=ON #define AAAA 1111 #define aaaa 2222 ;--- Test Macro Replacement --- 1. <$AAAA> ;;Expect "1111" 2. <$aaaa> ;;Expect "2222" 3. <$AAaa> ;;Expect ppwizard to fail here ═══ 7.28.5. DebugLevel ═══ DebugLevel=["]Command1,Command2,...["] This #option command allows you to modify the output generated by /debug and #debug. PPWIZARD generates quite a bit of debug information when debug is on, this is fine for small source files but could easily become hundreds of thousands of lines in more complex situations. If you are debugging a specific issue you may want to turn off debugging of unrelated events (this could also speed things up). Of course being more selective about placement of #debug commands is another very good option (why debug the whole process?). Note that you can turn off almost all debugging output, doing so could make it very difficult to determine what is going on as statements such as #AutoTag could transform lines in what appears to be a magical manner. Its up to you to determine what level you require. The Commands You may specify any numbers of commands, each separated by a comma. A command may begin with a '-' (to turn off) or '+' (turn on - default) the debug facility. By default all debug output is generated. Valid debug facilities are: ALL This represents all debug options. This less "USER?" is the default situation when PPWIZARD starts. CONDITIONAL #if, #endif output etc. FOUNDVAR Output to do with individual processing of your macros. FOUNDVARPARMS Output to do with individual processing of your macro's parameters. FOUNDSTDVAR Output to do with processing of individual Standard Macros. AFTERREPLACE All display of lines after some sort of replacement such as that by #AsIs commands or your macros. OPTIONS Any output related to #option command. OPSYS Debug commands executed by operating system. DEFINING Output related to defining variables/macros. MACROVALORDEF PPWIZARD allows some things to be defined via a macro, there is usually a default value. This debugs these situations. SPELLING Show all spelling related output? ASIS Debug the #AsIs command. AUTOTAG Debug the #AutoTag command. IMPORT Debug any IMPORT statements PPWIZARD performs. This will also automatically adjust "MACROVALORDEF". INTERPRET Debug any INTERPRET statements PPWIZARD performs. PPWIZARD does not trace all but will show ones from #if and #evaluate commands. EVALUATE This debugs PPWIZARD functions that can be used in #evaluate or #if commands etc. REXXVAR Debug the #RexxVar command. REXXTRACE Turn on rexx's inbuilt tracing for the execution of any rexx code that gets executed by commands such as #if, #evaluate and #import. This can be quite extensive so you might want to turn it off or lower its level (see below) for general debugging. The format of the output is described below. The PPWIZARD macro "REXXTRACE" can be used to control the level of rexx debugging. The default level is "INTERMEDIATES" with "RESULTS" generating less output while still being useful. The value you specified is used in the rexx "TRACE ???" command. Preceeding the value with '?' (as in "?Results") turns on interactive trace. You can execute any rexx commands to display or modify values. USER1 & USER2 Nothing in ppwizard itself makes use of these debug states, you can make use these for your own purposes. You can use these two flags either as a number (ranging from 0 to 3) for as 2 options (on or off). To test the current state you need to call IsDebugOn(). The value of USER bit one is 1 and USER bit two is 2. Note that you could define your own debug "flags" using "/define depending on the type of debug. The disadvantage on using these bits is the mimimum extra debug output is the contents of each line as it is processed. REXXTRACE Output This debug output is supplied by the rexx interpreter. The output from Regina is much inferior to that of OS/2 however its still very useful. The following can be used as a guide to understanding the output: Every clause traced will be displayed with automatic formatting (indentation) according to its logical depth of nesting and so on, and the results (if requested) are indented an extra two spaces and are enclosed in double quotation marks so that leading and trailing blanks are apparent. All lines displayed during tracing have a three-character prefix to identify the type of data being traced. The prefixes and their definitions are the following: - *-* Identifies the source of a single clause, that is, the data actually in the program. - +++ Identifies a trace message. This can be the nonzero return code from a command, the prompt message when interactive debug is entered, an indication of a syntax error when in interactive debug, or the traceback clauses after a syntax error in the program. - >>> Identifies the result of an expression (for TRACE R) or the value assigned to a variable during parsing, or the value returned from a subroutine call. - >.> Identifies the value assigned to a placeholder during parsing. - >C> The data traced is the name of a compound variable, traced after substitution and before use, provided that the name had the value of a variable substituted into it. - >F> The data traced is the result of a function call. - >L> The data traced is a literal (string or constant symbol). - >O> The data traced is the result of an operation on two terms. - >P> The data traced is the result of a prefix operation. - >V> The data traced is the contents of a variable. Example Lets turn off all optional debugging except CONDITIONAL and OPTIONS: #option DebugLevel=~-ALL,+CONDITIONAL,OPTIONS~ ═══ 7.28.6. DefineMacroReplace ═══ DefineMacroReplace=OnOrOff This #option command allows you to modify the way #define and #DefineRexx commands are processed. Normally no replacement of any macros within it's parameters are performed. This has its good points (which is why its the default) but at times you may wish to override this behavior. Apart from anything else in some cases this may speed things up. If the "OnOrOff" parameter is empty then it defaults to the current default value, otherwise one of the following is expected: ON OFF YES NO Example #define AAAA ValueAAAAOld #define BBBB <$AAAA> ;;Macro AAAA was not replaced #option DefineMacroReplace=ON ;;When #define command executes replace any references to macros straight away. #define CCCC <$AAAA> ;;Macro AAAA was replaced #define+ AAAA ValueAAAANew ;;Change Value of "AAAA" #option DefineMacroReplace='' ;;Set to the default value ;--- Use macros defined above ----------------------------------------------- <$BBBB> ;;Will generate "ValueAAAANew" <$CCCC> ;;Will generate "ValueAAAAOld" Example - Overcoming PPWIZARD Hang The following is a fragment of a rexx program that supports a number of standard rexx operators (but not all). It is trying to build up a list of valid operators to display if the user chooses an unsupported one. Because of the fact that by default a #define does not replace macros the following example would fail with an infinite loop (if the #option commands were removed). /*--- Now compare --------------------------------------------*/ #define CompRepOperator \ when sr_Operator = '{$Operator}' then %\ srCompRc = sr_bit {$Operator} sr_CompWith; -\ #ifndef CSR_ValidList -\ #define CSR_ValidList {$Operator} -\ #elseif -\ ;--- Careful or this line causes infinite loop --- -\ #define+ CSR_ValidList <$CSR_ValidList>, {$Operator} -\ #endif select /*--- Test for supported compare operators ---------------------------*/ #option PUSH DefineMacroReplace="ON" ;;Used push/pop - Making no assumptions about current state <$CompRepOperator Operator='='> <$CompRepOperator Operator='<>'> <$CompRepOperator Operator='=='> <$CompRepOperator Operator='\=='> #option POP /*--- Not Valid ------------------------------------------------------*/ otherwise Die("Unsupported operator of '" || sr_Operator || "' used", 'ONLY "<$CSR_ValidList>" are valid'); end; ═══ 7.28.7. ExtraIndent ═══ ExtraIndent=["]IndentCmd["] Whenever "KeepIndent" mode is on the current indent value is added to the start of each line. The default extra indent is none. The "IndentCmd" parameter is a rexx command which produces a string value which will be used for extra indenting. Example The following command would increase any indenting by 10 spaces for following lines: #option ExtraIndent=^copies(' ', 10)^ KeepIndent=ON ═══ 7.28.8. ExpandX ═══ ExpandX=["]CompleteList["] Normally codes are only expanded just before the data is written to the file (ie "LATE"). You may wish to vary when the replacement occurs. You can choose "COMMAND" to have replacements occur when a PPWIZARD command's parameters are expanded or "EARLY" to expand early on lines that are not PPWIZARD commands. The CompleteList parameter is a complete list of all the locations you wish expandion to occur on (COMMAND,EARLY,LATE) or "NONE" to completely turn off the expansion or "" to use default state. Example ;--- Turn off all expansion --- #option ExpandX="NONE" ;--- Expand everywhere -------- #option ExpandX="EARLY,LATE,COMMAND" ;--- Just expand early -------- #option ExpandX="EARLY" ═══ 7.28.9. HashPrefix ═══ HashPrefix=["]NewPrefix["] This #option command allows you to modify the characters which tell PPWIZARD that a line contains a ppwizard command. The default is that PPWIZARD commands begin with '#'. The NewPrefix parameter if empty sets the default value or specifies the new character or characters that preceed all commands. This command is useful if the language or file you are processing already uses the '#' character for its own reasons. Rather than using many codes it is much easier to move PPWIZARD out of the way. Example #include "FILE1.IH" #option hashprefix='!' ;;Set prefix to '!' !include "FILE2.IH" !option hashprefix='' ;;Set prefix to default value #include "FILE3.IH" ═══ 7.28.10. KeepIndent ═══ KeepIndent=OnOrOff This #option command lets you determine whether or not leading whitespace is removed from lines that are read from a file. If you wish to keep whitespace you can also use the ExtraIndent option to indent each line if you wish. An alternative to this command is to use "" to create whitespace as required. If the "OnOrOff" parameter is empty then it defaults to the current default value, otherwise one of the following is expected: ON OFF YES NO Example #Option keepindent=ON Want Indent on this line As well as this line #Option keepindent=OFF Example - Alternative way The way demonstrated here can make it easier to format your source code so its easy to read. The following example will generate the same 2 lines as the previous example: Want Indent on this line As well as this line ═══ 7.28.11. LeaveBlankLines ═══ LeaveBlankLines=OnOrOff This #option command lets you determine whether or not blank lines are ignored. By default they are. If the "OnOrOff" parameter is empty then it defaults to the current default value, otherwise one of the following is expected: ON OFF YES NO Example #Option LeaveBlankLines=ON ;;Don't drop blank lines ═══ 7.28.12. LineComment ═══ LineComment=["]ASingleChar["] This #option command allows you to specify an alternative character (to ';') for starting comments. If NULL is specified for ASingleChar then comment removal is disabled. An empty value will set it back to the default, otherwise the character becomes the new comment character. The same character doubled up becomes the inline comment indicator. Example ;--- This is a comment --- ;;Make the following text appear bold #option linecomment='@' @@Remove the bold attribute @--- This is a comment --- ;--- This is NO LONGER a comment --- @--- Restore default value (without hard coding it) --- #option linecomment='' @@Better way is to use push/pop ;--- This is a comment (no comments after the following line executed) --- #option linecomment='NULL' ;;Better way is to use push/pop ;--- This IS NOT a comment as comments disabled above -------------------- ═══ 7.28.13. LineContinuation ═══ LineContinuation=["]FullOrPartialSpecification["] This #option command allows you to alter the current Line Continuation characters or indeed turn it off altogether. The "FullOrPartialSpecification" parameter can be one of the following: 1. NULL In this case line continuation is turned off. 2. "" An empty value means use the default value. 3. exactly one character A single character value replaces the meaning of the '\' character. 4. exactly five characters This replaces all special characters used for line continuation as follows: a. Replacement for '\'. b. Replacement for down arrow character. c. Replacement for '-'. d. Replacement for '+'. e. Replacement for space. See the Line Continuation section of this document for more details. Your editor may not like the low ascii down arrow character (or you may hate it!), this option allows you to easily change it to another character of your choice. Example 1 We just wish to change the '\' so that we use '~' instead, so that we would use '-~' etc: #option LineContinuation="~" Example 2 Get rid of the down arrow variation, otherwise stick with defaults: #option LineContinuation="\@-+ " ;;'@\' now used for "newline" continuation Example 3 This example changes the down arrow character to the ASCII character decimal 20, no real reason however it does demonstrate a more complex possibility: #evaluate NewDownArrow 'd2c(20)' #option LineContinuation=%\<$NewDownArrow>-+ ^ ═══ 7.28.14. MacroParmTags ═══ MacroParmTags=["]NewTags["] This #option command is used to control the tags used within a macro definition to specify the location where a parameter replacement occurs. Use with care. You would normally only use once at the start of your code - think about the impact on any existing macros. If an empty parameter is supplied then the default is restored otherwise the parameter must have exactly 3 characters in it. The characters are in order: 1. Replacement for '{'. 2. Replacement for '}'. 3. Replacement for '$'. Example #option MacroParmTags="()%" ;;Parameters now start with '(%' and end with ')' #option MacroParmTags="" ;;Set to default values ═══ 7.28.15. Replace ═══ Replace=OnOrOff This #option command lets you to temporarily suspend replacement of definitions (and symbols). This allows you to pass through some complex lines without having to spend ages working out how you can tag it so as not to expand out (or fail trying). It is recommended that you turn off substitution for as short a time as you require it. Use with care. This command could be very handy if you needed to create a variable with a "#evaluate" command but you didn't want all the variables in the contents replaced straight away. If the "OnOrOff" parameter is empty then it defaults to the current default value, otherwise one of the following is expected: ON OFF YES NO Example The following is extracted out of a real macro that I had to set up, I was having trouble with '<$endExample>' expanding out when what I really want is the literal text: #Option REPLACE=OFF \ #AutoTag '<$endExample>' '~$endExample>' \ #AutoTag '<' '' \ #AutoTag '#' '#' \ #AutoTag '~$endExample>' '<$endExample>' \ #Option REPLACE=ON \ ═══ 7.28.16. ReplacementTags ═══ ReplacementTags=["]NewTags["] This #option command is used to control the tags that are required to tell PPWIZARD that you wish macro substitution to occur. Use with care. You would normally only use once at the start of your code - think about the impact on any existing macros. If an empty parameter is supplied then the default is used otherwise the parameter must have exactly 4 characters in it. The characters are in order: 1. Replacement for '<'. 2. Replacement for '>'. 3. Replacement for '$'. 4. Replacement for '?'. Example #define FRED **** <$Fred> ;;Fred will be subsituted here #option ReplacementTags="[]$?" [$Fred] ;;Fred will be subsituted here <$Fred> ;;Fred will NOT be subsituted here #option ReplacementTags="" ;;Set to default values ═══ 7.28.17. WhiteSpace ═══ WhiteSpace=["]ExtraWhiteSpaceCharacters["] This #option command can be used to adjust the characters that PPWIZARD treats as whitespace. A space is always treated as whitespace. Each extra character you define will be converted to a real space as lines are read from files. The default whitespace for unix will ensure that PC based files whose lines end with carriage return then linefeed and may have end of file characters embedded in the file can be read without conversion. Example The following example shows how to define the "~" and form feed (hex code '0C') characters as whitespace. In a unix environment we have removed the default whitespace conversions. PPWIZARD INPUT.IT /Option:WhiteSpace="{x0C}~" ═══ 7.29. #output ═══ #output In most situations you would read one or more input files to generate a single output file. There are situations where you'd like more control so that you can generate multiple files. You can nest to any level as only one output file is open at any time so file resources are not wasted. Syntax [WhiteSpace]#output ["]OutputName["] [AsIs] [Append] [HTML|REXX|OTHER] If "AsIs" was specified then the "OutputName" specifies the name of the output file otherwise the value is passed through the output specification provided with the "/Output" switch. If the "OutputName" parameter is not specified at all then the previous output file is restored. Note that files specified for use "AsIs" do not have their case adjusted as specified on the /FileNames switch, if you require the case to be adjusted you will need to make use of the EnsureFileHasCorrectCase routine. If "Append" was specified then the output file is not deleted if it already exists. In some circumstances you may wish to generate a new file in a different processing mode to the current one, if this applies to you then choose on of "HTML", "REXX" or "OTHER". When a previous file is restored (no parameters) then new data is appended, otherwise the file is erased before writing the first line. Example Line 1 of file 1 Line 2 of file 1 #output '2nd' Line 1 of file 2 Line 2 of file 2 #output 'c:\path\3nd.ext' AsIs Line 1 of file 3 #output Line 3 of file 2 #output Line 3 of file 1 Example - Relative Filenames The following example show how you can calculate filenames which are relative to the directory where output normally goes (as determined by the /OUTPUT switch: ;--- Macro to calculate filename relative to output directory --------------- #evaluate "" ^OutputDir = EnsureFileHasCorrectCase(_filespec('location', ''))^ ;;Only need to determine once! #define FileRelativeToOutputDir ?OutputDir>{$File} ;--- Test macro ------------------------------------------------------------- InOutput.OUT = <$FileRelativeToOutputDir FILE="InOutput.OUT"> SubDir\InOutput.OUT = <$FileRelativeToOutputDir FILE="SubDir\InOutput.OUT"> ..\Parents.OUT = <$FileRelativeToOutputDir FILE="..\Parents.OUT"> Example - Dropping output There may be time when you wish to drop some lines, for example you might be processing a file in a number of passes, this shows how you can do this under windows and OS/2: #output "NUL" ASIS APPEND ;;Drop output! This line gets dropped #output ;;Stop dropping output! ═══ 7.30. #Require ═══ #Require This is a simple command (Y2000 safe) which checks that the PPWIZARD preprocessor is capable of processing your code. You would probably put this command in a header file that you distribute to users. It will validate that the preprocessor they are using is new enough to handle your header file. Syntax [WhiteSpace]#Require ["]MinVersion["] The "MinVersion" specifies the minumum version number of PPWIZARD. The preprocessing will abort if the preprocessor is too old. Example #require 98.216 ;;Want PPWIZARD version 98.216 or greater ═══ 7.31. #RexxVar ═══ #RexxVar This command allows you to manipulate rexx variables. You can assign values to rexx variables, save them on a stack or give them the result of simple expressions which can be calculated much faster than with a #evaluate command. Note that you should try to pick unusual rexx variable names otherwise you might overwrite one that PPWIZARD uses. It could cause very strange behaviour. Syntax #1 - Set Up "X" Variable [WhiteSpace]#RexxVar ["]VariableName["] =x= [']ItsValue['] This is the only supported way to define "" codes. The "VariableName" parameter is the name of the 'x' variable and can contain virtually any character. The "ItsValue" parameter is the value which the rexx variable is to contain. Unlike the "#evaluate" command the new value is not first interpreted. It is taken as is. In practice I recommend using a quote character such as "^" as its unlikely to appear in the text, this may make it easier to follow in debug mode etc. This parameter can be a variables name (if unquoted). Syntax #2 - Assign to Rexx Variable [WhiteSpace]#RexxVar ["]VariableName["] = [']ItsValue['] This form of the command lets you assign text directly to a rexx variable. It is very useful in macros as you don't have to worry about quote issues while manipulating the data. For example you would find it very difficult to uppercase some text (probably passed as a macro parameter) if it contained both a single quote and a double quote and in fact how would you know which if any it contained? The "VariableName" parameter is the full name of the rexx variable to be set. The "ItsValue" parameter is the value which the rexx variable is to contain. Unlike the "#evaluate" command the new value is not first interpreted. It is taken as is. In practice I recommend using a quote character such as "^" as its unlikely to appear in the text, this may make it easier to follow in debug mode etc. This parameter can be a variables name (if unquoted). Syntax #3 - Save/Restore Variable on Stack [WhiteSpace]#RexxVar Operator ["]VariableName1["] ... ;;New Format [WhiteSpace]#RexxVar ["]VariableName["] Operator ;;Old Format The "VariableName" parameter(s) are the names of all variables being pushed or popped (saved or restored). The "Operator" parameter should be one of the following: 1. PUSH, Save rexx variable on stack. 2. POP, get last saved value from stack. For each variable pushed there must be a corresponding pop. It allows you to use the same variable names in multiple places without danger of the value getting modified (say by a #included file). The variable parameters of the pop command are processed in reverse order so that if you have push and pop commands with the more than one variable the variable lists do not need to be reversed by you! Syntax #3 - Simple Variable Manipulation [WhiteSpace]#RexxVar ["]VariableName["] Operator Value2 [SourceValue1]> This form of the command lets you perform some simple operations. These will be much faster than performing the same operation using #evaluate. The "VariableName" parameter is the full name of the rexx variable. In this format the variable will be given the result of a simple expression. The value is calculated as follows: VariableName = SourceValue1 {Operator} Value2; The "Operator" parameter should be one of the following: 1. +, Addition. 2. -, Subtraction. 3. *, Multiply. 4. /, Divide. 5. //, Divide, want remainder. 6. %, Divide, want whole number. 7. || Concatenate. The "Value2" is the value which would be added, subtracted etc from the source value. The "SourceValue1" parameter is the the source value. By default the value comes from "VariableName". Both Value2 & SourceValue1 can be one of the following: A rexx number. A rexx variable. A rexx literal. Example The following is sets the rexx variable "MyVar" to the literal "ABC" (as its quoted): #RexxVar 'MyVar' = /ABC/ The following is sets the rexx variable "MyVar" to the contents of the variable "ABC" (as its unquoted): #RexxVar 'MyVar' = ABC The following two lines both set the rexx variable "MyVar" to the value 0: #RexxVar 'MyVar' = 0 #RexxVar MyVar = '0' The following is sets the rexx variable "MyVar" to the 3 chars (single quote, space then double quote): #RexxVar 'MyVar' = "' "" Notice that in the above example double quotes are used to contain a value that contains a double quote. This is a common reason for using the "#RexxVar" command when accepting parameters in a macro. The following is one line out of a larger macro, note that we have absolutely no idea what text the parameter may expand to (for example it could easily contain single quotes): #RexxVar 'MyVar' = '{$Text}' The following lines all add one to the "Counter": #RexxVar Counter + 1 ;;Counter = Counter + 1 #RexxVar Counter + 1 Counter ;;Counter = Counter + 1 #RexxVar Counter - "-1" ;;Counter = Counter - -1 A stupid example: #RexxVar Three + 1 2 ;;Three = 2 + 1 The following lines append to the end of the rexx variable "Grow": #RexxVar Grow || ", a string" ;;Grow = Grow || ", a string" #RexxVar Grow || AVariable ;;Grow = Grow || AVariable The following lines could be used in a rexx header file to skip over any subroutines the header contains after all header initialization has taken place: ;--- Initialization --------------------------------------------------------- HeaderVar1 = "Value1"; HeaderVar2 = "Value2"; ;--- Jump around code ------------------------------------------------------- #RexxVar "SkipName" = "SkipSubroutine__" signal ?SkipName>; ;;Jump past functions #RexxVar PUSH "SkipName" ;;Save name of label HeaderFunction1: return('Value'); ;---------------------------------------------------------------------------- ;--- End of code ------------------------------------------------------------ ;---------------------------------------------------------------------------- #RexxVar POP "SkipName" ;;Restore saved value ?SkipName>: ;;Create label to mark end of code ═══ 7.32. #undef ═══ #undef A #undef command allows you to remove a definition so that it can be redefined without producing the warning message it normally will generate. Syntax [WhiteSpace]#define Variable The "Variable" indicates which variable is to be removed. Example #define Fred Its value #undef Fred; #define Fred Its new value ═══ 7.33. #Warning ═══ #Warning A #Warning command is used to inform the user of an unusual situation. You would probably have extracted information (maybe from an environment variable) and found that all is not right. This command allows you to warn the user but continue processing (you will get a return code of 1). The #Error command is similar but halts processing. Syntax [WhiteSpace]#Warning [']WarningId['] [']WarningMessage['] The "WarningId" parameter specifies a warning ID which can be used to help identify message (for example if you wished to use the /WarningsIgnore switch). You can supply an empty ID in case no ID is used. An ID can be as short or long as you wish. The "WarningMessage" parameter specifies the text of the warning to be displayed. Example #if GetEnv('FRED') <> 1 & GetEnv('FRED') <> 2 #Warning ^IV00^ "Invalid value for variable 'FRED', processing will continue" #endif ═══ 8. Standard Definitions ═══ Standard Definitions There are a number of "standard" definitions which have been predefined and can be placed almost anywhere in your source code. The variables can be in any case, they are: ?RexxVariable> =RexxExpression> Note that you can define your own variations of "standard" variables with the "#evaluate" command, for example to create an alternative way to display the Compile Time. EXAMPLES OF CREATING VARIABLES ;--- Capture some HTML information ------------------------------------------ #evaluate ShortNameHtml "_filespec('name', '')" #evaluate ShortNameHtmlLowerCase "translate('<$ShortNameHtml>', 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" ;--- Capture date/time information (<$DateTime> --> Friday March 27 1998 at 7<$colon>46pm --- #evaluate DateTime @date('WeekDay') || ' ' || date('Month') || ' ' || substr(date('Sorted'), 7, 2) || ' ' || left(date('Sorted'), 4) || ' at ' || time('Civil')@ ;--- Create YY.DDD Version # (example "98.107") -------------------------------------- #evaluate YYDDD ~substr(date('Sorted'),3,2) || '.' || date('Days')~ ;--- Outputs the size of a file (takes parameter "File") -------------------- #define SizeOfFile \ #evaluate+ LocalFileName ^ReplaceString("../{$File}", "/", "\")^ \ #DependsOn INPUT "<$LocalFileName>" \ #evaluate+ TmpFileSize ^AddCommasToDecimalNumber(stream("<$LocalFileName>", "c", "query size"))^ \ #if "<$TmpFileSize>" = "" \ #error $Failed getting size of "<$LocalFileName>"$ \ #endif \ <$TmpFileSize> #define SizeOfFileInSmallFont {$Before=""}<$SizeOfFile File=*{$File}*> bytes{$After=""} #define (SizeOfFileInSmallFont) <$SizeOfFileInSmallFont File=*{$File}* Before='(' After=')'> ;--- Outputs the date (Ausi format... YES!) (takes parameter "File") -------- #define DateOfFile \ #evaluate+ LocalFileName ^ReplaceString("../{$File}", "/", "\")^ \ #DependsOn INPUT "<$LocalFileName>" \ #evaluate+ TmpFileTime ^stream("<$LocalFileName>", "c", "query datetime")^ \ #if "<$TmpFileTime>" = "" \ #error $Failed getting date/time of "<$LocalFileName>"$ \ #endif \ #evaluate+ TmpFileDate ~substr('<$TmpFileTime>', 4, 2) || '/' || left('<$TmpFileTime>', 2) || '/' || substr('<$TmpFileTime>', 7,2)~ \ <$TmpFileDate> #define DateOfFileInSmallFont {$Before=""}<$DateOfFile File=*{$File}*>{$After=""} ═══ 8.1. ?RexxVariable> ═══ ?RexxVariable> It is possible to access rexx variables without first obtaining a copy of their value with the "#evaluate command. Any symbol that starts with ? and ends with > is a command to get the value of the rexx variable between. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). Example The following is an example which creates ,
HTML tagging etc: #RexxVar HeadingLevel = 1 ;;Create a rexx variable (set to 1) #RexxVar HeadingLevel + 1 ;;Increase value by 1
>A heading > ;;Use it ═══ 8.2. =RexxExpression> ═══ =RexxExpression> A "variable" of this type allows you to evaluate a rexx expression, without using a separate #evaluate command. Each time you use it a relatively slow rexx "interpret" command is required, so for performance reasons it is recommended that you: Use "?RexxVariable>" to obtain the contents of a single rexx variable. Use a single "#evaluate" command and store result for reuse rather than using the same rexx "variable" expression multiple times. The rexx expression has the limitation that it must not contain the ">" character! This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). Example ;--- 5 '*' chars ---- =copies('*',2)||copies('*',3)> ;--- Next line is invalid (compile will fail) --- =copies('*',2)||copies('>',3)> ═══ 8.3. ═══ This variable expands to the following 2 lines: 1. Content-type: text/html 2. Blank line This is required at the start of all CGI output. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.4. ═══ This variable contains the date and time the compile started. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.5. ═══ This variable will tell you whether debug is currently on or off by returning 'Y' (it's on) or 'N'. You could use this to add comments to generated output when debug is on etc. You could also use the IsDebugOn() to obtain similar information. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.6. ═══ This variable will indicate the character used to separate components of a path. For most operating systems this will be '\' however UNIX uses '/' instead. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.7. ═══ This variable will be replaced by a '$' character. You may need to use it in some situations, for example in some cases where you wish to place '<$'. This symbol actually expands to a code and not the '$' character directly. In some cases this may not be what you wish and you should either define your own alternative or use some other method (#define may be suitable in a lot of cases) depending on your need. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.8. ═══ This variable will be replaced by a '#' character. This symbol actually expands to a code and not the '#' character directly. In some cases this may not be what you wish and you should either define your own alternative or use some other method (#define may be suitable in a lot of cases) depending on your need. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.9. ═══ This variable will be replaced by a current hash prefix character(s). This is whatever was set with the 'HashPrefix' option. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.10. ═══ This variable contains the level of file inclusion starting at 1. For each #include it goes up by one and goes back down by 1 when processing of that file completes. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.11. ═══ This variable contains the full filename of the input file currently being processed. If you need to access the name of an input file other than the current one, then you will need to use the InputComponentLevel() routine. If you need the name of the base source file (determined from the InputMask specified on the command line) and you are obtaining the information within your standard header files you will need to use "" instead. If you require the path or short name component then use the "#evaluate" command to subdivide the full name. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.12. ═══ This variable contains the current line number of the input file currently being processed. If you need to access the line number of other included files, then you will need to use the InputComponentLineLevel() routine. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.13. ═══ This variable contains the full filename of the base input file that was specified on the command line. This definition is useful to extract this information in your standard header files as "" could return the name of the header file! If you require the path or short name component then use the "#evaluate" command to subdivide the full name. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.14. ═══ This variable will return the newest source files date/time (so far) allowing you to date/timestamp your output with this information and not the date/time of the compile. Note that the "compiler" (PPWIZARD) is considered to be a source file as it also determines the format of the output. If the variable is used after the last #include to be processed then the value returned must be the date/time of the latest file (so unless you are added the timestamp information near the end of your output you may not be able to make use of this variable). The information is returned in the same format as that returned by the "GetFileTimeStamp()" routine (except that -1 is not possible). Also have a look at it's example as the macro it shows could be used with very minor modification. It is possible to work out the day of the week if you use the basedate routine. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.15. ═══ This variable forces following text onto the next line. It can be useful if you need to pass the generated html through other tools which can't handle long lines. In macros (created with "#define") this is the only way to ensure that multiple lines are generated. Note that this variable is the only way to ensure that the line is terminated correctly as the "/CrLf" switch (and others) may vary the appropriate codes that need to be generated. This symbol actually expands to a code and not the 'newline' character directly. In some cases this may not be what you wish and you should either define your own alternative or use some other method (#define may be suitable in a lot of cases) depending on your need. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.16. ═══ This variable indicates the operating system you are running on and is one of the following values: OS/2 DOS WINNT WIN98 WIN95 UNIX If you need to know which version of a platform you will need to do more work yourself. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.17. ═══ This variable contains the full filename of the current output file. If you require the path or short name component then use the "#evaluate" command to subdivide the full name. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.18. ═══ This variable contains the output nesting level. When its '1', the output goes to the default output file, each #Output with filename adds one while a #output without file subtracts one. This variable would be handy in complex macro sets where #output commands are automatically generated. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). Example This line is at Output Level 1 #output '2nd' This line is at Output Level 2 #output 'c<$colon>\path\3nd.ext' AsIs This line is at Output Level 3 #output This line is at Output Level 2 #output This line is at Output Level 1 ═══ 8.19. ═══ This variable contains the line number of the next line to be generated ("this line") into the current output file. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.20. ═══ This variable contains the name of the developer of the PPWIZARD program. Use if you wish to make mention of PPWIZARD on your homepages. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.21. ═══ This variable contains the email address of the developer of the PPWIZARD program. Use if you wish to make mention of PPWIZARD on your homepages. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.22. ═══ This variable contains the internet address of the computer home page of the developer of the PPWIZARD program. Use if you wish to make mention of PPWIZARD on your homepages. Note that I recommend that if you point to other pages of mine that you either use a #evaluate on this variable to obtain the base path or validate that it contains what you expect (and fail with #error if it doesn't). This way if I change my homepage you will be informed via a new version of PPWIZARD. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.23. ═══ This variable contains the default HTML meta tags for this program. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.24. ═══ This variable contains the current processing mode, that is one of the following: 1. HTML 2. REXX 3. OTHER The mode can be set or specified in these situations: 1. /REXX 2. /HTML 3. /OTHER 4. #output This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.25. ═══ This variable contains the address of this programs HTML home page. Use if you wish to make mention of PPWIZARD on your homepages. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.26. ═══ This variable expands to one or more commands that ensure that following lines are protected from change by PPWIZARD. As examples, this prevents leading whitespace removal and text such as "#define" as being treated as commands. This is similar to the "#AsIs" command except that no "as is" tagging is performed and that PPWIZARD commands are not precessed. Note that this does not do any extra tagging such as that required to ensure that the text appears the same in a browser or ipf viewer etc. This must be taken care of by you ("#AutoTag"). You must use "" at the end of the lines you wish to protect. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.27. ═══ Please see "" for details. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.28. ═══ By the time PPWIZARD macro replacement has taken place its already decided that the line does not contain a PPWIZARD command. If you wish to dynamically generate PPWIZARD commands you need to use this variable at the start of every command (you could have more than one). Another possible reason for using this define is that PPWIZARD expands definitions in a single pass from left to right. This means that you could not build up a reference to a variable from components unless you include this define. PPWIZARD will stop replacement of macros etc as soon as it has expanded the first define of this type on the line so its position on a line can greatly affect the way expansion occurs. The use of this variable could cause other unwanted affects, it is up to you to test to ensure you are obtaining the results you require. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). Example In this example the intention is to create the macro variable "X": ;--- "Command" contains the command we want executed --- #define Command #define X XXXXXXXXXXXXXXXXXXXXX Attempt 1 - Fails ~~~~~~~~~~~~~~~~~ <$Command> Attempt 2 - Works ~~~~~~~~~~~~~~~~~ <$Command> Test Definition ~~~~~~~~~~~~~~~ Number of x's ==> <$X> ═══ 8.29. ═══ This symbol is used in conjunction with the "" symbol to simplify the "skipping" of subroutines within a rexx header file. A header file will frequently include some initialization code followed by some routines. The recommended place to include header files is at the start of your mainline code module. To be able to hold common procedures in the header file you must skip over them after you have performed any required initialization. You could simply use a "signal EndRexxHeader" before the procedures and "EndRexxHeader:" after, however then you need to create a new label every time and it becomes difficult to include a header file more than once. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). Example - EXAMPLE.XH /*--- Initialization for "EXAMPLE.XH" ---*/ call InitStuff; InitStuff: ... return; MoreCode: ... return; /*--- End of rexx header ---*/ ═══ 8.30. ═══ This symbol is used in conjunction with the "" symbol to simplify the "skipping" of subroutines within a rexx header file. Every use of "" must be followed by the use of the "" symbol. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). Example See . ═══ 8.31. ═══ This variable will be replaced by a single semicolon (;) character. It could be useful if you have the odd line that must begin with a semicolon. The semicolon is the default character to begin a line comment. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.32. ═══ This variable will be replaced by a single space, it is most useful for ensuring that you have required spaces on lines that were continued using the '\' character. This symbol actually expands to a code and not the ' ' character directly. In some cases this may not be what you wish and you should either define your own alternative or use some other method (#define may be suitable in a lot of cases) depending on your need. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.33. ═══ If the "/Template" switch was not specified then this variable will return an empty value, otherwise the name of the data file is returned (the template typically processes this file). By using this variable a header file could determine whether or not template processing is occurring. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.34. ═══ This variable contains the total line number of lines generated into all output files. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.35. ═══ This variable will be replaced by a Unique number every time it is used. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). ═══ 8.36. ═══ This variable will be replaced by the version number of the program. The version number is in the form "YY.DDD", examples are "98.001" (first day of 1998) and "00.123" (123rd day of 2000). This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). Example The following code shows how you could ensure that a general purpose header file can only be used if the preprocessors version number is greater than a particular value. You would do this if the header file requires a particular feature which only became available in a specific release. /*--- Get PPWIZARD version # as YYYY.DDD ------------------------------------*/ #if < 98.000 #evaluate PPWizardVersion "2000.00 + "; #elseif #evaluate PPWizardVersion "1900.00 + "; #endif /*--- Validate PPWIZARD VERSION (Y2K safe) ----------------------------------*/ #define DEFINEIT_MIN_PPWIZARD_VERSION 1998.188 ;;Rely on changes made in specific PPWIZARD release #if <$PPWizardVersion> < <$DEFINEIT_MIN_PPWIZARD_VERSION> #error 'PPWIZARD.CMD version of at least <$DEFINEIT_MIN_PPWIZARD_VERSION> is required, you have <$PPWizardVersion>' #endif ═══ 8.37. ═══ Any variable which starts with 'x' has a special characteristic in that they are not replaced until just before a line is written to the output file. The only invalid character in the name of the variable is '>'. The replacements are made in a single pass from left to right. The replacement contents may not itself contain codes you wish to be interpreted in any way as the text will be output as specified. You have some control over when the replacement occurs, see the ExpandX option. The name of the symbol represents a variable whose contents was previously defined with the '=x=' operator of the #RexxVar command. For complex values you may need to first use #evaluate to calculate the value. Variables of this type are useful if you wish to use characters that can't be entered by the editing tool you are using. They also provide an emergency way out which might get you past instances where the character might otherwise be interpreted in a manner other than you wish. For example if you must have the string "" in your output (and not have it replaced by the version number)! Another example is that "" is the only way to get a tab into the generated output. This is a Standard Definition which always exists (you don't need to #define it). Note that you can create your own variations or completely new ones (see the examples). Codes to The 256 rexx variables "x00" to "xFF" have been preset to represent their ASCII character codes. This means that "" would get replaced with a tab character and "" would get replaced with "A". You could if you wished change the appropriate rexx variables to change the replacement value. For example you could decide the code for "<" gets replaced by "<" instead. Note that it would generally be better to "name" your ASCII codes as they would then be easier to understand, for example "xTAB" is a lot easier to understand than "x09"! It is highly recommended that you do not use "" codes to generated newlines, you should use "". Example - Using Predefined ASCII Codes #define Tab Col1<$Tab>Col2<$Tab>Col3 Example - Creating Your Own Codes #evaluate 'Tab' "d2c(9)" #RexxVar "TAB" =x= "<$Tab>" ;;TAB Char #RexxVar "LA" =x= "<" ;;'<' Char #RexxVar "RA" =x= ">" ;;'>' Char Col1Col2Col3 = Less than = Greater than ═══ 9. PPWIZARD Extensions ═══ PPWIZARD Extensions You may not wish to use some of these headers but it would pay you to look at them purely from the point of view of examples. ═══ 9.1. FTPLIKE.IH - Make "FTP" Like Listings ═══ FTPLIKE.IH - Make "FTP" Like Listings This header file will scan the specified directory (and optionally its subdirectories) and by default produce a FTP like set of html pages. It is very simple for you to modify any part of the look and feel, so for example it would be simple to add your own headers, footers, backgrounds and display all information in whatever format or font you wish. This header could also be used to automatically process photo directories producing thumbnails (with extra software) etc automatically. Example - Creating Directory Listing The following code is all that is required to generate a complete HTML page of all files in a single directory. Note that file descriptions are read out of ".DIZ" files if available (the DIZ files themselves are not displayed). ;--- Complete code to generate a HTML page for the directory "C:\TMP" --- #define FTPLIKE_DIRECTORY C:\TMP #define FTPLIKE_DIRECTORY_WEB file:///C|TMP ;;Note: for web "downloads/tmp" might normally be more appropriate #define FTPLIKE_FOLLOW_SUBDIRECTORIES #define FTPLIKE_USE_LONG_FILENAMES ;;When generating web pages for subdirectories (default is 8.3) #define FTPLIKE_HTML_EXTN html ;;When generating web pages for subdirectories (".htm" is default) #include "FTPLIKE.IH" Example - WPS URL Objects to HTML I keep all my WPS URL objects off a main URL folder, I then create HTML pages from this so I can effectively access my URL objects from anywhere via the internet (pages at http://www.labyrinth.net.au/~dbareis/bookmark.htm). This is the code I use: #define Title "Dennis' Personal Bookmarks" #define AddToDescription Dennis' Personal Bookmarks, straight from OS/2 WPS URL Objects #include "computer.ih" ;--- Initialization --------------------------------------------------------- #if ['' <> 'OS/2'] #error "Sorry but you will need to modify this file to work on operating systems other than OS/2!" #endif #evaluate "" "call RxFuncAdd 'SysGetEA', 'RexxUtil', 'SysGetEA'" ;--- Title ------------------------------------------------------------------ <$BackgroundMainWindows> <$PageTitle TITLE="Dennis' Personal Bookmarks"> ;--- Routine used to format "thin" URL -------------------------------------- #define ThinUrl \ #evaluate @@ @ThinUrl = BreakAt(14, '{$HTTPURL}')@ -\ ?ThinUrl> ;--- Save values of this pages info (they get modified below!) -------------- #ifndef VERSION_PUSHPOPM_H #include "PushPopM.H" #endif <$MacroPush Macro='ShortNameHtml'> <$MacroPush Macro='ShortNameHtmlLowerCase'> ;--- Override images my footer macro normally uses for these pages ---------- #define+ LinkImgFooter -\ <$ImgMadeWithPpwizardAndreaResmini ALT="Made with PPWIZARD using FTPLIKE.IH"> -\ ;--- Override "normal" FTPLIKE options (no need to change header!!!!) ------- #DefineRexx REXX_GETURL ;--- First line of WPS URL file contains the URL ---------------- CloseRc = stream(FtpFile, 'c', 'close'); eUrl = linein(FtpFile); CloseRc = stream(FtpFile, 'c', 'close'); #DefineRexx #DefineRexx REXX_GETCOMMENT ;--- Comment is stored in OS/2 Extended Attributes -------------- if SysGetEA(FtpFile, ".COMMENTS", "eComment") <> 0 then eComment = ''; else eComment = substr(eComment, 11); ;;Drop EA Type info eComment = ReplaceString(eComment, '0D0A'x, '
'); #DefineRexx #DefineRexx REXX_REALNAME ;--- Long name is stored in OS/2 Extended Attributes ------------ if SysGetEA(FtpFile, ".LONGNAME", "eShort") <> 0 then eShort = ''; else eShort = substr(eShort, 5); ;;Drop EA Type info if eShort = '' then ;;Play safe! eShort = FtpOutput; ;;Use what we have! else eShort = ReplaceString(eShort, '0D0A'x, '
'); #DefineRexx #define FTPLIKE_DIR_HANDLER \ #evaluate+ '' ^FtpFile=FtpDir;<$REXX_REALNAME>;<$REXX_GETCOMMENT>^ -\-\ #define FTPLIKE_FILE_HANDLER \ #evaluate+ "" "FtpOutput = _filespec('name', FtpFile)" -\ #evaluate+ '' ^<$REXX_GETURL>;<$REXX_REALNAME>^ -\-\ ;--- Link to HTML page we will create --- -\ <$FTPLIKE_LINK2DIR Url="<$FtpDirId>.<$FTPLIKE_HTML_EXTN>"> -\ ?eShort> ;;Just output short name -\ -\ -\-\ -\-\
-\ #if [eComment <> ''] -\-\ -\?FtpSubdirTotalFileCnt> url(s) -\ #if FtpSubdirTotalDirCnt <> 0 -\?FtpSubdirTotalDirCnt> folder(s) -\ #endif -\
?eComment> ;;Comment from EAs -\ #endif -\;;Start New File row %\ ;;End this File row #define FTPLIKE_END_PAGE_ABOVE_FOOTER \ <$ImgBarbedWire> -\;;Start filename cell %\ -\ ?eShort> ;;Just output short name -\ %\ ;;End cell \;;Start filename cell %\ <$ThinUrl HTTPURL="?eURL>"> -\ ;;End cell #define FTPLIKE_FILE_DETAILS_HANDLER \ #evaluate '' ^<$FTPLIKE_FILE_ATTRIBUTE_HANDLER_REXX>^ -\;;Start file details cell %\ ?FtpDay> ?FtpMon> ?FtpYear> \ ?FtpHour>:?FtpMinute>:?FtpSecond> \ #evaluate "" ^<$REXX_GETCOMMENT>^ -\ #if [eComment <> ''] -\ ;;End cell %\
?eComment> ;;Comment from EAs -\ #endif -\-\ -\ -\Creating These Book Mark Pages
-\This page was automatically created from \ OS/2 WPS URL objects created with Netscape 4.04 \ onwards. \ The free tool used was \ PPWIZARD using \ -\ this source code \ . -\ -\
All URLs are checked periodically using the \ URL checking tool that comes with PPWIZARD. #define FTPLIKE_NO_HEADER_FOOTER_ON_1ST_PAGE #define FTPLIKE_FOLLOW_SUBDIRECTORIES #define FTPLIKE_USE_LONG_FILENAMES #define FTPLIKE_BODY_TAG <$BackgroundMainWindows> #if <$AtHome> #define FTPLIKE_DIRECTORY E:\DB\URLS ;;HOME: Location of Base WPS URL folder #else #define FTPLIKE_DIRECTORY ..\HOME_URL ;;WORK: Copied here from home #endif #define FTPLIKE_DIRECTORY_WEB #define FTPLIKE_NEWHTML_PREFIX bookmark_ #define FTPLIKE_HEADER <$PageTitle TITLE="{$Title}"> #define FTPLIKE_FOOTER \ #evaluate+ ShortNameHtml "_filespec('name', '')" -\ #evaluate+ ShortNameHtmlLowerCase "translate('<$ShortNameHtml>', 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" -\ <$EndHtmlWithStandardFooter> ;--- Include FTPLIKE support (creates all HTML pages based on options above) --- #include "FTPLIKE.IH" ;--- Restore this pages information and output footer and end of HTML ------- <$MacroPop Macro='ShortNameHtmlLowerCase'> <$MacroPop Macro='ShortNameHtml'> <$EndHtmlWithStandardFooter> FTPLIKE.IH This shows the contents of the header file (supplied with PPWIZARD) that provides the generic "FTP like" support: ;---------------------------------------------------------------------------- ; MODULE NAME: FTPLIKE.IH ; ; $Author: Dennis_Bareis $ ; $Revision: 1.8 $ ; $Date: 25 Nov 1999 17:57:06 $ ; $Logfile: E:/DB/PVCS.IT/OS2/PPWIZARD/FTPLIKE.IHV $ ; ; DESCRIPTION: This allows you to create FTP like pages without ; having to do a lot of work. Simply add the file ; to a directory will get it onto the correct HTML ; page. ; ; It would be wise to generate pages into their own ; directory on the off chance that this header file ; picks a name for a directories file which matches ; one of yours! ; ; Note that most of the code below is tricky only ; because I made it generic (ie very configurable), ; a specific implementation would be much smaller ; and much much easier to write as well! ; ; The whole look and feel of the generated data may ; be modified. ; ; It would be simple to have your normal look and feel ; items such as headers, footers backgrounds etc ; integrated into the generated output. ; ; Description file support (.diz) is available for both ; files and directories. The directory DIZ file should ; reside in the directory its describing. Note that the ; file can (and probably should) contain normal HTML ; formatting tags - by default anyway. If you have a ; file called "stuff.zip" this header will look for ; "stuff.zip.diz" and "stuff.diz". ; ; You should not modify the value of any definition ; that begins with an "_", you can modify virtually ; anything else. ; ; Note that dependancy checking does not make sense ; in this type of situation as files can appear simply ; by matching the wildcard. For this reason I do not ; bother with using the "#dependsOn INPUT" command for ; each file I process. ; ; ; NOT COMPLETE ; ~~~~~~~~~~~~ ; I don't really like the way file date, time and size ; are displayed, if you have any better ideas please ; let me know. ; ; ; SUPPORTED OPERATING SYSTEMS ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ; It is intended that all operating systems that PPWIZARD ; supports can also use this header, if you find that ; it does not work then please send me the output when ; you have used the "/debug" command line switch. Please ; also include a directory listing of the directory(s) you ; are processing. ; ; ; EXAMPLE - LINUX ; ~~~~~~~~~~~~~~~ ; #define FTPLIKE_FOLLOW_SUBDIRECTORIES ; #define FTPLIKE_USE_LONG_FILENAMES ; #define FTPLIKE_DIRECTORY /home/dennis/ ; #define FTPLIKE_DIRECTORY_WEB http://ftp ; #include "ftplike.ih" ; ; ; EXAMPLE - OS/2, WINDOWS ; ~~~~~~~~~~~~~~~~~~~~~~~ ; #define FTPLIKE_FOLLOW_SUBDIRECTORIES ; #define FTPLIKE_USE_LONG_FILENAMES ;;Remove this definition for 8.3 names ; #define FTPLIKE_DIRECTORY C:\TMP\ASM_MAC ; #define FTPLIKE_DIRECTORY_WEB file:///C|TMP/ASM_MAC ;;Local testing ; #include "FTPLIKE.IH" ; ; ; HELP WANTED ; ~~~~~~~~~~~ ; I use "find" under linux, is there a expression that ; I can pass to "-name" to display all files/directories? ; ;---------------------------------------------------------------------------- ;--- First time through? ---------------------------------------------------- #ifndef _FTPLIKE_INITIALIZED ;--- Define the version number of this header file ----------------------- #define+ VERSION_FTPLIKE_IH 99.325 #require 99.325 ;--- Check prerequisites ------------------------------------------------- #ifndef FTPLIKE_DIRECTORY #error ^You must define the "FTPLIKE_DIRECTORY" value (local directory)!^ #endif #ifndef FTPLIKE_DIRECTORY_WEB #error ^You must define the "FTPLIKE_DIRECTORY_WEB" value (web location)!^ #endif ;--- Include macro push/pop support -------------------------------------- #ifndef VERSION_PUSHPOPM_H #include "PushPopM.H" #endif ;--- Use same date time on all generated pages --------------------------- #ifndef FTPLIKE_DATETIME #evaluate FTPLIKE_DATETIME @date('WeekDay') || ' ' || date('Month') || ' ' || substr(date('Sorted'), 7, 2) || ' ' || left(date('Sorted'), 4) || ' at ' || time('Civil')@ #endif ;--- Total numbers accross FTP pages ------------------------------------- #RexxVar FtpTotalDirCnt = 0 ;;Number of directories #RexxVar FtpTotalFileCnt = 0 ;;Number of files ;--- Remember the output level where it all began! ----------------------- #Rexxvar FtpStartLevel = ;--- Work out what filemasks users wants --------------------------------- #ifndef FTPLIKE_FILE_MASKS ;--- Default is to process all files ----------------------------- #if ['' = 'UNIX'] #define FTPLIKE_FILE_MASKS #else #define FTPLIKE_FILE_MASKS *.* #endif #endif #ifndef FTPLIKE_DIR_MASKS ;--- Default is to process all directories ----------------------- #if ['' = 'UNIX'] #define FTPLIKE_DIR_MASKS #else #define FTPLIKE_DIR_MASKS *.* #endif #endif ;--- Do best we can for input dependancies ------------------------------- #ifdef FTPLIKE_FOLLOW_SUBDIRECTORIES #DependsOn INPUT ^*FILES=+<$FTPLIKE_DIRECTORY><$FTPLIKE_DIR_MASKS>^ #elseif #DependsOn INPUT ^*FILES=<$FTPLIKE_DIRECTORY><$FTPLIKE_DIR_MASKS>^ #endif ;--- Allow user to easily support frames etc ----------------------------- #ifndef FTPLIKE_LINK2DIR #define FTPLIKE_LINK2DIR #endif #ifndef FTPLIKE_LINK2FILE #define FTPLIKE_LINK2FILE ;;Probably would not want to override this #endif ;--- Prepare for generating HTML page names ------------------------------ #ifdef FTPLIKE_FOLLOW_SUBDIRECTORIES ;--- Prepare for generating html page names (unique names!) ------ #evaluate '' ^call GetIdPrepare 'FTPLIKE', 'Y'^ ;--- Don't generate filename same as current "base" file! -------- #evaluate '' ^call SetId 'FTPLIKE', '', EnsureFileHasCorrectCase(_filespec('W', _filespec('Name', '')))^ #endif ;--- Now work out the output directory ----------------------------------- #evaluate+ 'FtpGenDir' ^_filespec('location', '')^ ;--- Work out the full name of this header file -------------------------- #RexxVar FtpLikeFile = '' ;--- Relative web directory ---------------------------------------------- #define _FTPLIKE_DIRECTORY_WEB_RELATIVE ;--- Work out what user wants to call the "root" dir --------------------- #ifndef FTPLIKE_DISPLAY_DIR #define FTPLIKE_DISPLAY_DIR / #endif ;--- Work out extension to use ------------------------------------------- #ifndef FTPLIKE_HTML_EXTN #define FTPLIKE_HTML_EXTN htm #endif ;--- User want specific prefix for generated filenames ------------------- #ifndef FTPLIKE_NEWHTML_PREFIX #ifdef FTPLIKE_USE_LONG_FILENAMES #define FTPLIKE_NEWHTML_PREFIX FtpLike_ #elseif #define FTPLIKE_NEWHTML_PREFIX ;;No prefix #endif #endif ;--- Define Simple HEADERS & FOOTERS ------------------------------------- #ifndef FTPLIKE_HEADER #define FTPLIKE_HEADER
#endif #ifndef FTPLIKE_FOOTER #define FTPLIKE_FOOTER \ {$Title}
%\%\ %\ <$FTPLIKE_DATETIME> %\ %\ %\