Archive: Find file in a list of paths


Find file in a list of paths
Hi,

I had the problem that I had to find a file in a list of paths. My solution requires the "IndexOf" implementation from the Wiki.

Here's the source. Any suggestions?

Function IndexOfAny
Exch $R0
Exch
Exch $R1
Push $R2
Push $R3
Push $R4
Push $R5
Push $R6
StrCpy $R5 -1
StrCpy $R6 0
StrLen $R3 $R1
NextChar:
IntCmp $R3 0 NotFound
IntOp $R3 $R3 - 1
StrCpy $R4 $R1 1 $R3
${IndexOf} $R2 $R0 $R4
IntCmp $R2 -1 NextChar
IntCmp $R6 0 ForceSet
IntCmp $R5 $R2 NextChar NextChar 0
ForceSet:
StrCpy $R5 $R2
StrCpy $R6 1
GoTo NextChar
NotFound:
StrCpy $R0 $R5
Pop $R6
Pop $R5
Pop $R4
Pop $R3
Pop $R2
Pop $R1
Exch $R0
FunctionEnd

!macro IndexOfAny Var Str Chars
Push "${Chars}"
Push "${Str}"
Call IndexOfAny
Pop "${Var}"
!macroend
!define IndexOfAny "!insertmacro IndexOfAny"

; IN: Path list
; OUT: Remaining path list
; Path entry
Function ExtractPathFromList
Exch $R0
Push $R1 ; Index of found delimiter
Push $R2 ; Found path entry
Push $R3 ; Remaining path entries
Push $R4 ; Found character
Push $R5
Push $R6
Push $R7
Push $R8

StrCpy $R7 '" '
StrCpy $R8 '"'

StrCpy $R2 ""
StrCpy $R3 $R0

CheckAgain:
${IndexOfAny} $R1 $R3 $R7
IntCmp $R1 -1 ReturnRemaining

StrCpy $R4 $R3 1 $R1 ; Get found delimiter
StrCpy $R5 $R3 $R1 ; Get text until delimiter (excl.)
IntOp $R1 $R1 + 1
StrCpy $R3 $R3 "" $R1 ; Get remaining text
StrCpy $R2 "$R2$R5" ; Combine with ...

StrCmp $R4 $R8 FoundQuote
GoTo Finished

FoundQuote:
${IndexOf} $R1 $R3 $R8
IntCmp $R1 -1 ReturnRemaining

StrCpy $R4 $R3 1 $R1 ; Get found delimiter
StrCpy $R5 $R3 $R1 ; Get text until delimiter (excl.)
IntOp $R1 $R1 + 1
StrCpy $R3 $R3 "" $R1 ; Get remaining text
StrCpy $R2 "$R2$R5"
GoTo CheckAgain

ReturnRemaining:
StrCpy $R2 $R0
StrCpy $R3 ""

Finished:
StrCpy $R1 $R2
StrCpy $R0 $R3

Pop $R8
Pop $R7
Pop $R6
Pop $R5
Pop $R4
Pop $R3
Pop $R2
Exch $R1
Exch
Exch $R0
FunctionEnd

!macro ExtractPathFromList VarEntry VarRemaining Paths
Push '${Paths}'
Call ExtractPathFromList
Pop "${VarRemaining}"
Pop "${VarEntry}"
!macroend
!define ExtractPathFromList "!insertmacro ExtractPathFromList"

; IN: Paths
; File name
; OUT: Path+FileName
Function FindFileInPaths
Exch $R0
Exch
Exch $R1
Push $R2
Push $R3

check_next:
${ExtractPathFromList} $R2 $R1 $R1
StrCmp $R2 "" not_found

StrCpy $R2 "$R2\$R0"
IfFileExists "$R2" 0 check_next

StrCpy $R0 $R2
GoTo finished

not_found:
StrCpy $R0 ""

finished:
Pop $R3
Pop $R2
Pop $R1
Exch $R0
FunctionEnd

!macro FindFileInPaths Var FileName Paths
Push '${Paths}'
Push "${FileName}"
Call FindFileInPaths
Pop "${Var}"
!macroend
!define FindFileInPaths "!insertmacro FindFileInPaths"


The main idea is to implement an "IndexOfAny" which searches for the first occurrence of one of the given characters. The next step is to extract the first path from a "list" of paths that are divided by a SPC (ASCII 32) character. It also takes care of all quotation marks ('"').

Example usage:
  ${FindFileInPaths} $R0 "hh.exe" 'C:\WINDOWS C:\ "C:\Program Files"'
MessageBox MB_OK $R0



This is my first NSIS script *g*.

Regards,
Mark

Name "Output"
OutFile "Output.exe"

Section
locate::Open /NOUNLOAD "C:\" "/D=0 /G=0 /N=file1.ext|file2.ext|file3.ext /P=C:\WINDOWS|C:\Program Files" .r0
StrCmp $0 -1 0 loop
MessageBox MB_OK "Error" IDOK close

loop:
locate::Find /NOUNLOAD .r0 .r1 .r2 .r3 .r4 .r5
StrCmp $0 '' close

MessageBox MB_OKCANCEL '$$0 "path\name" =[$0]$\n\
$$1 "path" =[$1]$\n\
$$2 "name" =[$2]$\n\
$$3 "size" =[$3]$\n\
$$4 "time" =[$4]$\n\
$$5 "attributes =[$5]$\n\
$\n\
Find next?' IDOK loop
close:
locate::Close
SectionEnd
http://nsis.sourceforge.net/Locate_plugin