;---------------------------------------------------------------------------- ; MODULE NAME: NESTCHK.H ; ; $Author: Dennis_Bareis $ ; $Revision: 1.4 $ ; $Date: 13 Nov 1999 13:39:22 $ ; $Logfile: E:/DB/PVCS.IT/OS2/PPWIZARD/NESTCHK.H_V $ ; ; REQUIRES: Regina 0.08f onwards, or you get clause length problems. ; ; DESCRIPTION: This is a header file for generic handling of ; nesting checking. This is where you must have matching ; "whatevers" such as a matching "" for a ; "" etc. ; ; "TABLE" checking is a good example as are "FRAMESET" ; statements as the Netscape browser will not display ; an incorrectly nested page (common cause of "blank" ; pages). This header file can be used to detect these ; errors while still developing the pages rather than ; HOPING that testing will show up the errors. ; ; Because these macros are generic you would usually have ; your own header file to front end them, for example your ; header could begin with: ; ; ;--- Prepare table nesting checking code --- ; #include "NESTCHK.H" ; <$NestingInit Id="HTMLTAG_TABLE" DESC="HTML TABLE tag"> ; #define TABLE \ ; -\ ; <$NestingInc Id="HTMLTAG_TABLE"> ; #define /TABLE \ ;
-\ ; <$NestingDec Id="HTMLTAG_TABLE"> ; ; Your code would then always use the table macros defined ; above rather than the HTML table tags directly, example: ; ; <$TABLE BORDER=5 CELLPADDING=10> ; ;;Could validate TD /TD etc! ; ... ; ; <$/TABLE> ; ; You would probably do more that just "TABLE" tags in the ; above example! Notice that the only difference in your ; actual code is an extra '$'! ; ; Macro "HtmlNesting" ; ~~~~~~~~~~~~~~~~~~~ ; ; This header file now allows easy creation of macros such ; as the "TABLE" and "/TABLE" shown above. For example to ; create nest checking macros for "TABLE", "/TABLE", "TH", ; "/TH", "TD" and "/TD" you would use: ; ; <$HtmlNesting TAG="TABLE"> ; <$HtmlNesting TAG="TH"> ; <$HtmlNesting TAG="TD"> ; ; ; Macro "NestingInit" ; ~~~~~~~~~~~~~~~~~~~ ; ; This macro takes the following parameters: ; ; ID ; ~~ ; Manditory. Short name to describe what we wish ; to check. Must contain only characters which ; are valid in rexx variable names (no checking of ; this is done). ; ; DESC ; ~~~~ ; A description which is displayed if a nesting ; error is found. ; ; ; Macro "NestingInc" ; ~~~~~~~~~~~~~~~~~~ ; ; This macro takes the following parameters: ; ; ID ; ~~ ; Manditory. Matches that used on "NestingInit". ; You are increasing the level of nesting. ; ; ; Macro "NestingDec" ; ~~~~~~~~~~~~~~~~~~ ; ; This macro takes the following parameters: ; ; ID ; ~~ ; Manditory. Matches that used on "NestingInit". ; You are decreasing the level of nesting. ; ; ; Macro "NestingLevel" ; ~~~~~~~~~~~~~~~~~~~ ; ; This macro takes the following parameters: ; ; ID ; ~~ ; Manditory. Matches that used on "NestingInit". ; Returns the name of the variable which contains ; the level (0= neutral, 1 = down one etc). ; ;---------------------------------------------------------------------------- ;--- Only include this header once! ----------------------------------------- #ifndef VERSION_NESTCHK_H ;--- Define the version number of this header file -------------------------- #define VERSION_NESTCHK_H 99.317 #require 99.317 ;--- Register checking macro ------------------------------------------------ #OnExit <$NestingCheck> ;--- Currently not tracking nesting of anything ----------------------------- #RexxVar NestingIdCount = 0 ;--- Define macro to keep track of items ------------------------------------ #DefineRexx NestingInit_REXX ;--- Ensure ID is valid (needs to be valid rexx var format) ----- if symbol('{$ID $$SQx2}') = 'BAD' then Error('The ID of "{$ID $$SQx2}" contains invalid characters!', 'It must be in the format of a valid rexx variable name'); if symbol('{$ID $$SQx2}_Level') = 'VAR' then Error('The ID of "{$ID $$SQx2}" has already been initialized!'); ;--- Remember ID details -------------------------- NestingIdCount = NestingIdCount + 1; call _valueS "NESTINGID.NestingIdCount.ID", '{$ID $$SQx2}'; call _valueS "NESTINGID.NestingIdCount.DESC", '{$DESC}'; call _valueS "{$ID $$SQx2}_DESC", '{$DESC}'; ;--- Initialize level counter --------------------- call _valueS '{$ID $$SQx2}_Level', 0; #DefineRexx #define NestingInit \ #evaluate '' ^<$NestingInit_REXX ID='{$ID}' DESC='{$DESC}'>^ ;--- We are going down one level of nesting --------------------------------- ; [SaveSourceAndLocnInfo] (Ignore this - this bit used to include section into doco) #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}'>^ ; [SaveSourceAndLocnInfo] (Ignore this - this bit used to include section into doco) ;--- We are going up one level of nesting ----------------------------------- #DefineRexx NestingDec_REXX ;--- Ensure ID is valid ------- if symbol('{$ID $$SQx2}_Level') <> 'VAR' then Error('The ID of "{$ID $$SQx2}" is unknown (you must use "NestingInit")!'); ;--- Decrease nesting level --- NewLevel = {$ID}_Level - {$DecreaseBy="1"}; if NewLevel < 0 then call Error "Too many end tags for " || {$ID}_DESC; ;--- Record updated details --- call _valueS "{$ID}_Level", NewLevel; #DefineRexx #define NestingDec \ #evaluate '' ^<$NestingDec_REXX ID='{$ID}' {$?}>^ ;--- Allow user to access the counter variable ------------------------------ #define NestingLevel \ {$ID}_Level ;--- Check nesting of all ID's ---------------------------------------------- #DefineRexx NestingCheck_REXX ;--- Loop though all registered "nesting" items --- NestingError = 0; ;;No errors found yet do CheckIndex = 1 to NestingIdCount; ;--- Get basic information about item --- _ID = NESTINGID.CheckIndex.ID; _DESC = NESTINGID.CheckIndex.DESC; _Level = _valueG(_ID || "_Level"); if _Level <> 0 then; do; if NestingError = 0 then; do; say ''; say 'NESTING ERRORS'; say '~~~~~~~~~~~~~~'; end; NestingError = NestingError + 1; if _Level < 0 then; say 'Have ' || abs(_Level) || ' too many end nesting tags on "' || _DESC || '"'; else; do; ;--- display nesting info --- say 'Missing ' || _Level || ' end nesting tag(s) on "' || _DESC || '"'; do _ThisLevel = 1 to _Level; say ' * ' || _valueG(_ID || "_FilePosn._ThisLevel"); say ' ' || _valueG(_ID || "_CurrLine._ThisLevel"); end; end; end; end; #DefineRexx #define NestingCheck \ #evaluate '' ^<$NestingCheck_REXX>^ \ #if [NestingError <> 0] \ #error ^NestingCheck(): Found nesting error(s) as described above^ \ #endif ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ;%%%[ The following macros allow you to easily define HTML tag Nesting ]%%% ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ;--- This is the only tag of the following you should use! ---------------- #define HtmlNesting \ ;--- Initialization for this tag --- -\ <$NestingInit Id="HTML_{$TAG}" \ DESC='HTML {$TAG} tag nesting' -\ > -\ -\ #evaluate ^^ ^<$REXX_HTML_NESTING TAG=^{$TAG}^ Type="Inc">^ -\ #evaluate ^^ ^<$REXX_HTML_NESTING TAG=^{$TAG}^ Type="Dec">^ ;--- Define GENERIC macros for TAG and /TAG (use pseudo parameters) ------- #define _HTML_NESTING_Inc \ <[Tag]{$?}> -\ <$NestingInc Id="HTML_[Tag]"> #define _HTML_NESTING_Dec \ -\ <$NestingDec Id="HTML_[Tag]"> ;--- Define code which creates TAG start/end macros ----------------------- #DefineRexx REXX_HTML_NESTING ;--- Get GENERIC Macro (START or END) --- TagMacro = MacroGet('_HTML_NESTING_{$Type}'); ;--- Replace pseudo parameters --- TagMacro = ReplaceString(TagMacro, '[Tag]', '{$TAG $$SQx2}'); ;--- Create START or END html tag macro --- if '{$Type}' = 'Inc' then HtmlTag = '{$TAG $$SQx2}'; else HtmlTag = '/{$TAG $$SQx2}'; call MacroSet HtmlTag, TagMacro; #DefineRexx ;--- Only include this header once! ----------------------------------------- #endif