Menu

#1070 Problem with LogicLib LoopUntil

2.0 Series
closed-rejected
nobody
Scripting (211)
5
2013-07-14
2013-05-09
Alastair
No

Using ANSI NSIS 2.46, writing a script to populate a combobox with strings from an INI file, I have found that LogicLib isn't handling LoopUntil properly.

Here's a snippet:

Push $0 ; Index
Push $1 ; Value
ClearErrors
StrCpy $0 0
${Do}
    IntOp $0 $0 + 1
    ReadINIStr $1 "$EXEDIR\Strings.ini" "Strings" "String$0"
    ${IfNot} ${Errors}
        ${NSD_CB_AddString} $MyComboBox "$1"
    ${Else}
        MessageBox MB_OK " Error for index $0"
    ${EndIf}
${LoopUntil} ${Errors}
Pop $1
Pop $0

Now, when you run that you won't have the INI file and the error flag will be set immediately for Index 1, which is fine for testing. You can comment out the line using ${NSD_CB_AddString}, it doesn't affect the symptoms of this issue. What you'll see is the message box pop up because an error was detected for index 1, but then the outer loop will continue indefinitely.

If you remove the inner ${IfNot}, then the problem magically goes away:

Push $0 ; Index
Push $1 ; Value
ClearErrors
StrCpy $0 0
${Do}
    IntOp $0 $0 + 1
    ReadINIStr $1 "$EXEDIR\Strings.ini" "Strings" "String$0"
${LoopUntil} ${Errors}
Pop $1
Pop $0

Now the loop breaks properly, and you're no longer stuck in an infinite loop.

There is an example of using Do, LoopUntil Errors in the Examples folder, and the syntax is similar. Nothing in LogicLib.nsh seems to call ClearErrors directly.

What gives?

Discussion

  • Marshall

    Marshall - 2013-05-11

    See the documentation: Calling IfErrors CLEARS the error flag.

    Not intuitive, I agree, but not a bug.

     
  • Amir Szekely

    Amir Szekely - 2013-07-14
    • Description has changed:

    Diff:

    --- old
    +++ new
    @@ -2,36 +2,38 @@
    
     Here's a snippet:
    
    -Push $0 ; Index
    -Push $1 ; Value
    -ClearErrors
    -StrCpy $0 0
    -$\{Do\}
    -IntOp $0 $0 + 1
    -ReadINIStr $1 "$EXEDIR\Strings.ini" "Strings" "String$0"
    -$\{IfNot\} $\{Errors\}
    -$\{NSD\_CB\_AddString\} $MyComboBox "$1"
    -$\{Else\}
    -MessageBox MB\_OK " Error for index $0"
    -$\{EndIf\}
    -$\{LoopUntil\} $\{Errors\}
    -Pop $1
    -Pop $0
    +    :::nsis
    +    Push $0 ; Index
    +    Push $1 ; Value
    +    ClearErrors
    +    StrCpy $0 0
    +    ${Do}
    +        IntOp $0 $0 + 1
    +        ReadINIStr $1 "$EXEDIR\Strings.ini" "Strings" "String$0"
    +        ${IfNot} ${Errors}
    +            ${NSD_CB_AddString} $MyComboBox "$1"
    +        ${Else}
    +            MessageBox MB_OK " Error for index $0"
    +        ${EndIf}
    +    ${LoopUntil} ${Errors}
    +    Pop $1
    +    Pop $0
    
     Now, when you run that you won't have the INI file and the error flag will be set immediately for Index 1, which is fine for testing. You can comment out the line using $\{NSD\_CB\_AddString\}, it doesn't affect the symptoms of this issue. What you'll see is the message box pop up because an error was detected for index 1, but then the outer loop will continue indefinitely.
    
     If you remove the inner $\{IfNot\}, then the problem magically goes away:
    
    -Push $0 ; Index
    -Push $1 ; Value
    -ClearErrors
    -StrCpy $0 0
    -$\{Do\}
    -IntOp $0 $0 + 1
    -ReadINIStr $1 "$EXEDIR\Strings.ini" "Strings" "String$0"
    -$\{LoopUntil\} $\{Errors\}
    -Pop $1
    -Pop $0
    +    :::nsis
    +    Push $0 ; Index
    +    Push $1 ; Value
    +    ClearErrors
    +    StrCpy $0 0
    +    ${Do}
    +        IntOp $0 $0 + 1
    +        ReadINIStr $1 "$EXEDIR\Strings.ini" "Strings" "String$0"
    +    ${LoopUntil} ${Errors}
    +    Pop $1
    +    Pop $0
    
     Now the loop breaks properly, and you're no longer stuck in an infinite loop.
    
    • Group: --> 1.x Legacy series (discontinued)
     
  • Amir Szekely

    Amir Szekely - 2013-07-14
    • status: open --> closed-rejected
    • Group: 1.x Legacy series (discontinued) --> 2.0 Series
     

Log in to post a comment.