Wilson WindowWare Tech Support

WinBatch WinBatch+Compiler WebBatch
Home | Tech Database | Tech BBS | White Papers | Purchase


Code: A string 'externalizer'

Keywords: 
This program reads a WinBatch program and creates a second program that is essentially the same but has all literal strings 'externalized'.

Externalized means that in the code, all literals have been replaced by newly generated variable names. A special subroutine named LITERALS will be generated and appended to your code. Here, all assignments from your former literals to the new variables are performed.


; StrExtrn.WBT
; ============

; A String Externalizer
; by M. Meron, June 18, 1998.
; Public domain.
; Disclaimer: This is a sample 'user-to-user' program.
;             No guarantees whatsoever.
; For example, the code line..
;    text="Hi there!"
; ..will become..
;    text=q0001
; ..where q0001 will be declared in the LITERALS sub:
;    q0001="Hi there!"

; This lets you easily re-use your code for another
; international version (i.e. language), or for any
; other purpose you like.

; CAUTION !!!
; This program isn't really too smart.
; For example, it is not aware of comments (;like this).
; So be sure to carefully verify the resulting code.

; All suggestions welcome (MMeron@csi.com).

; Initialization.
nPrevErrMode=ErrorMode(@CANCEL)
sTitle="String Externalizer"     ; program title
Debug(KeyToggleGet(@SCROLLLOCK)) ; (this line is just a habit)

sQuotes=StrCat("'´`", '"')   ;all possible quote characters
sVarPfx="q"                  ;prefix for new variable names
nVarCtr=0                    ;counter for new variable names
nMinLitLen=4                 ;do not externalize shorter literals

; Get input and output file names.
sPrompt="Select the input file for %sTitle%"
sTyps="WIL Files|*.wbt;*.mnu"
sTyps="%sTyps%|Text Files|*.txt|All Files|*.*|"
sDftDir=DirGet()
sDftFil=""
sInFil=AskFileName(sPrompt, sDftDir, sTyps, sDftFil, 1)
sPrompt="Select the OUTPUT file for %sTitle%"
sDftFil=FileMapName(sInFil, "*--Externalized.wbt")
sOutFil=AskFileName(sPrompt, sDftDir, sTyps, sDftFil, 0)

; Get a name for a temporary file.
sTmpDir=Environment("TEMP")
sTmpFil="%sTmpDir%\$$temp.wb2"

; Open all files. Abort immed on problems.
hfilIn=FileOpen(sInfil, "READ")
If !hfilIn
   sMsg="Could not open file '%sInFil%' for READ"
   Message(sTitle, sMsg)
   GoTo DONE
EndIf
hfilTmp=FileOpen(sTmpfil, "WRITE")
If !hfilTmp
   sMsg="Could not open temp file '%sTmpFil%' for WRITE"
   Message(sTitle, sMsg)
   GoTo DONE
EndIf
hfilOut=FileOpen(sOutfil, "WRITE")
If !hfilOut
   sMsg="Could not open file '%sOutFil%' for WRITE"
   Message(sTitle, sMsg)
   GoTo DONE
EndIf

; Make sure that the new code will call the :LITERALS
; subroutine we're going to create.
sLine="; Move the following line to where you do initializations"
FileWrite(hfilOut, sLine)
sLine="GoSub LITERALS"
FileWrite(hfilOut, sLine)
FileWrite(hfilOut, "")

; Read all lines sequentially till end of file.
sLine=FileRead(hfilIn)
While sLine != "*EOF*"
   
   nLen=StrLen(sLine)
   
   ; Get string literal, if any, and write to temp file.
   nPos1=StrScan(sLine, sQuotes, 1, @FWDSCAN)
   If nPos1  &&  (nPos1 < nLen)
      sChr=StrSub(sLine, nPos1, 1)
      nPos2=StrIndex(sLine, sChr, nPos1+1, @FWDSCAN)
      If nPos2 && (nPos2-nPos1-1) >= nMinLitLen

         ; We have found a literal to be substituted.
         ; The opening quote is at nPos1, the closing
         ;   one is at nPos2.

         ; Get a new variable name for the literal we're
         ;   going to externalize.
         nVarCtr=nVarCtr+1
         sVarNam=StrCat(sVarPfx, StrFixLeft(nVarCtr, "0", 4))

         ; Extract the literal from the line of code.
         sLiteral=StrSub(sLine, nPos1, nPos2-nPos1+1)

         ; Replace it with the variable name we prepared.
         sLine=StrReplace(sLine, sLiteral, sVarNam)

         ; Append '= to the temp file.
         sLine2=StrCat(sVarNam, "=", sLiteral)
         sLine2=StrCat(sLine2, " ; ", StrLen(sLiteral)-2)
         FileWrite(hfilTmp, sLine2)

         ; Do not yet write the line to the output file
         ;   because there may be yet another literal
         ;   to be processed.
         Continue

      EndIf
   EndIf

   ; Dump the line we've just read (and eventually changed)
   ; to the output file.
   FileWrite(hfilOut, sLine)

   ; Get next line from the infile (i.e. original code).
   sLine=FileRead(hfilIn)

EndWhile

; Close the infile because we don't need it any longer.
; Close the temp file, too, for the moment.
FileClose(hfilIn)
hfilIn=0
FileClose(hfilTmp)
hfilTmp=0

; Re-open the temp file, this time for read.
hfilTmp=FileOpen(sTmpfil, "READ")
If !hfilTmp
   sMsg="Could not open temp file '%sTmpFil%' for WRITE"
   Message(sTitle, sMsg)
   GoTo DONE
EndIf

; Append the assignment equations to the output file
; as a subroutine.
FileWrite(hfilOut, "")
sDivider=StrCat(";", StrFill("=", 40))
FileWrite(hfilOut, sDivider)
FileWrite(hfilOut, ":LITERALS")
FileWrite(hfilOut, "")
sLine=FileRead(hfilTmp)
While sLine != "*EOF*"
   FileWrite(hfilOut, sLine)
   sLine=FileRead(hfilTmp)
EndWhile
FileWrite(hfilOut, "")
FileWrite(hfilOut, "Return")

; That's all folks.

:CANCEL
:DONE
If IsDefined(hfilIn)
   If hfilIn  Then FileClose(hfilIn )
   If hfilOut Then FileClose(hfilOut)
   If hfilTmp Then FileClose(hfilTmp)
EndIf
sMsg="Externalization of %sInFil% to %sOutFil% "
sMsg="%sMsg%completed successfully."
Message(sTitle, sMsg)
GoTo EXIT

:EXIT
Exit

Note that something like:
        xx = "hello %name%!"
would not work. It should be...
        xx = Strcat("hello ",name,"!")
The script won't work until all inline %var% references are expands to strCat()...
Article ID:   W13769
Filename:   Code - A String Externalizer.txt