I wrote some handy NSIS functions for C Programmers
NSIS, unlike Python, does not have a List Type and this is good because it makes the language more like Assembly and therefore faster. However, the handy dandy C functions strtok and strchr allow list-like operations on pure strings. This IMHO goes well beyond the quite limited functionality of SPLIT_STRING and allows arbitrary delimiters, sets of delimiters (i.e. use ",.!? $\n$\t$\r" to split the input as words) and can be called repeatedly until all tokens are found. The resulting list should be tested for "" to terminate any loop. Here is the code:
; StrTok works just like ISO C strtok, where input is modified as in that function
; Parameter 2 is popped and it is the delimiter to split the string with
; Parameter 1 is then popped and it is the string to parse
; The resulting remaining part of input is pushed onto the stack
; The resulting substring is pushed onto the stack
;
; Example:
; Push $Input
; Push $Delim
; Call StrTok
; Pop $0
; Pop $Input
; MessageBox MB_OK "My next token is $0"
; MessageBox MB_OK "The remaining text is $Input"
;
; StrChr works just like ISO C strchr, where DELIM must be 1 char long and error is returned if DELIM is not found
; Parameter 2 is popped and it is the delimiter to split the string with
; Parameter 1 is then popped and it is the string to parse
; The resulting integer offset is pushed onto the stack
;
; Example:
; Push $Input
; Push $Delim
; Call StrChr
; Pop $0
; StrCmp $0 error +3
; MessageBox MB_OK "Delimiter found at offset $R0"
; goto +2
; MessageBox MB_OK "Delemiter not found"
Function StrTok
; Get the Delimiter ($R0)
Exch $R0
; Get the Input ($R1)
; This is second on the stack so switch it to the first and then $R0 becomes second
Exch 1
Exch $R1
; Need 2 more variables
Push $R2 ; A Character from the Input
Push $R3 ; An index into the Input
StrCpy $R3 -1
; Loop
StrTokLoop:
IntOp $R3 $R3 + 1
StrCpy $R2 $R1 1 $R3
StrCmp $R2 "" StrTokBreak
Push $R0 ; Delimiter
Push $R2 ; Character to find in the Delimeter
Call StrChr
Pop $R2 ; The position of old $R2 in the Delimeter
StrCmp $R2 error StrTokLoop
StrTokBreak:
Push $R5
StrCpy $R5 $R0 ; Store the Delimeter in $R5
StrCpy $R0 $R1 $R3 ; $R0 now has the parsed string
; Need to find all the delimeter and delete them
StrTokIsDelim:
IntOp $R3 $R3 + 1
StrCpy $R2 $R1 1 $R3
StrCmp $R2 "" StrTokDone
Push $R5 ; Delimiter
Push $R2 ; Character to find in the Delimeter
Call StrChr
Pop $R2 ; The position of old $R2 in the Delimeter
StrCmp $R2 error "" StrTokIsDelim
StrTokDone:
Pop $R5 ; Don't need the Delimeter copy anymore
StrCpy $R1 $R1 "" $R3 ; $R1 now has the rest of the input
Pop $R3 ; Reversal
Pop $R2 ; Reversal
Exch $R1 ; Push Input back on Stack where $R1 is
; Swap Input with stored $R0 and swap it for the result
Exch 1
Exch $R0 ; Result
FunctionEnd
Function StrChr
; Get the Delimiter ($R0) (What you're looking for)
Exch $R0
; Get the Input ($R1)
; This is second on the stack so switch it to the first and then $R0 becomes second
Exch 1
Exch $R1
; Need 2 more variables
Push $R2 ; A Character from the Input
Push $R3 ; An index into the Input
StrLen $R3 $R0 ; $R2 has the String Length
StrCmp $R3 1 +3
; Error -- Delim has to be 1 char
StrCpy $R0 error
Goto StrChrDone
StrCpy $R3 -1
; Loop
StrChrLoop:
IntOp $R3 $R3 + 1
StrCpy $R2 $R1 1 $R3
StrCmp $R2 "" "" +3
; Error -- Delim not found
StrCpy $R0 error
Goto StrChrDone
StrCmp $R2 $R0 "" StrChrLoop
; End Loop
; Need to move result to $R0
StrCpy $R0 $R3
StrChrDone:
Pop $R3 ; Reversal
Pop $R2 ; Reversal
Pop $R1 ; Reversal
Exch $R0 ; Result
FunctionEnd