GetBetween: Get text in between two markers in a file

From NSIS Wiki
Jump to navigationJump to search
Author: Afrow UK (talk, contrib)


Description

This function for vbgunz gets text from between two markers in a file. It returns the text from between the first occurrences of the markers and then stops searching. It works even if the markers are or are not on the same line.

Usage

${GetBetween} "This" "And This" "$INSTDIR\In_This.txt" "$R0"
; $R0 = output (text between "This", "And This").

The Macro and Function

!macro GetBetween This AndThis In Return
Push "${This}"
Push "${AndThis}"
Push "${In}"
 Call GetBetween
Pop "${Return}"
!macroend
!define GetBetween "!insertmacro GetBetween"
 
Function GetBetween
 Exch $R0 ; file
 Exch
 Exch $R1 ; before this (marker 2)
 Exch 2
 Exch $R2 ; after this  (marker 1)
 Exch 2
 Push $R3 ; marker 1 len
 Push $R4 ; marker 2 len
 Push $R5 ; marker pos
 Push $R6 ; file handle
 Push $R7 ; current line string
 Push $R8 ; current chop
 
 FileOpen $R6 $R0 r
 
 StrLen $R4 $R2
 StrLen $R3 $R1
 
 StrCpy $R0 ""
 
 Read1:
  ClearErrors
  FileRead $R6 $R7
  IfErrors Done
  StrCpy $R5 0
 
 FindMarker1:
  IntOp $R5 $R5 - 1
  StrCpy $R8 $R7 $R4 $R5
  StrCmp $R8 "" Read1
  StrCmp $R8 $R2 0 FindMarker1
   IntOp $R5 $R5 + $R4
   StrCpy $R7 $R7 "" $R5
 
  StrCpy $R5 -1
  Goto FindMarker2
 
 Read2:
  ClearErrors
  FileRead $R6 $R7
  IfErrors Done
  StrCpy $R5 -1
 
 FindMarker2:
  IntOp $R5 $R5 + 1
  StrCpy $R8 $R7 $R3 $R5
  StrCmp $R8 "" 0 +3
   StrCpy $R0 $R0$R7
  Goto Read2
  StrCmp $R8 $R1 0 FindMarker2
   StrCpy $R7 $R7 $R5
   StrCpy $R0 $R0$R7
 
 Done:
  FileClose $R6
 
 Pop $R8
 Pop $R7
 Pop $R6
 Pop $R5
 Pop $R4
 Pop $R3
 Pop $R2
 Pop $R1
 Exch $R0
FunctionEnd

-Stu

Patch for the above Function

Please note and track the stack action for the above function. Calling it repeatedly will mung your registers, as shown by the step through below.

!macro GetBetween This AndThis In Return
Push "${This}" ; This + Stack
Push "${AndThis}" ; AndThis + This + Stack
Push "${In}" ; In + AndThis + This + Stack
Call GetBetween
Pop "${Return}"
!macroend
!define GetBetween "!insertmacro GetBetween"
 
Function GetBetween
Exch $R0 ; $R0_Old + AndThis + This + Stack
Exch ; AndThis + $R0_Old + This + Stack
Exch $R1 ; $R1_Old + $R0_Old + This + Stack
Exch 2 ; This + $R0_Old + $R1_Old + Stack
Exch $R2 ; $R2_Old + $R0_OLD + $R1_Old + Stack
 
## ERROR IS HERE.
Exch 2 ; R1 R0 R2 + stack
Push $R3 ; R3 R1 R0 R2 + stack
## Careful inspection of the rest of the function, 
## shows zero stack maniplation to somehow fix
## the linear re-pop of the register list 8-0
 The correction at the noted error is to add two lines before pushing $R3:
Exch $R2                     ;$R2_Old + $R0_OLD + $R1_Old + Stack
Exch 2                       ; $R1_Old + $R0_OLD + $R2_Old + Stack
Exch                         ; $R0_Old + $R1_OLD + $R2_Old + Stack
Exch 2                       ; $R2_Old + $R1_OLD + $R0_Old + Stack
; Now push $R3
 Pending user-group agreement; I suggest patching the original code before removing my    comments.  - Andrew Wallo