diff --git a/Examples/LogicLib.nsi b/Examples/LogicLib.nsi index bd65a75c..0f21c5fc 100644 --- a/Examples/LogicLib.nsi +++ b/Examples/LogicLib.nsi @@ -1,109 +1,290 @@ Name "NSIS LogicLib Example" OutFile "example.exe" -SilentInstall silent +ShowInstDetails show +;!define LOGICLIB_VERBOSITY 4 !include "logiclib.nsh" -!define MsgBox "MessageBox MB_OK" Section + ; if..endif + StrCpy $R1 1 + StrCpy $R2 "" + ${If} $R1 = 1 + StrCpy $R2 $R2A + ${EndIf} + ${If} $R1 = 2 + StrCpy $R2 $R2B + ${EndIf} + ${If} $R1 < 2 + StrCpy $R2 $R2C + ${EndIf} + ${If} $R1 < -2 + StrCpy $R2 $R2D + ${EndIf} + ${If} $R1 > 2 + StrCpy $R2 $R2E + ${EndIf} + ${If} $R1 > -2 + StrCpy $R2 $R2F + ${EndIf} + ${If} $R1 <> 1 + StrCpy $R2 $R2G + ${EndIf} + ${If} $R1 <> 2 + StrCpy $R2 $R2H + ${EndIf} + ${If} $R1 >= 2 + StrCpy $R2 $R2I + ${EndIf} + ${If} $R1 >= -2 + StrCpy $R2 $R2J + ${EndIf} + ${If} $R1 <= 2 + StrCpy $R2 $R2K + ${EndIf} + ${If} $R1 <= -2 + StrCpy $R2 $R2L + ${EndIf} + ${If} $R2 == "ACFHJK" + DetailPrint "PASSED If..EndIf test" + ${Else} + DetailPrint "FAILED If..EndIf test" + ${EndIf} + ; if..elseif..else..endif - StrCpy $R1 1 ;change to test the following if statement - ${if} $R1 = 1 - MessageBox MB_OK "if: R1=1" - ${elseif} $R1 = 2 - MessageBox MB_OK "ifelse: R1=2" - ${else} - MessageBox MB_OK "else: R1=$R1" - ${endif} + StrCpy $R1 A + StrCpy $R2 "" + ${If} $R1 == A + StrCpy $R2 $R2A + ${ElseIf} $R1 == B + StrCpy $R2 $R2B + ${ElseUnless} $R1 != C + StrCpy $R2 $R2C + ${Else} + StrCpy $R2 $R2D + ${EndIf} + ${If} $R1 == D + StrCpy $R2 $R2D + ${ElseIf} $R1 == A + StrCpy $R2 $R2A + ${ElseUnless} $R1 != B + StrCpy $R2 $R2B + ${Else} + StrCpy $R2 $R2C + ${EndIf} + ${If} $R1 == C + StrCpy $R2 $R2C + ${ElseIf} $R1 == D + StrCpy $R2 $R2D + ${ElseUnless} $R1 != A + StrCpy $R2 $R2A + ${Else} + StrCpy $R2 $R2B + ${EndIf} + ${If} $R1 == B + StrCpy $R2 $R2B + ${ElseIf} $R1 == C + StrCpy $R2 $R2C + ${ElseUnless} $R1 != D + StrCpy $R2 $R2D + ${Else} + StrCpy $R2 $R2A + ${EndIf} + ${If} $R2 == "$R1$R1$R1$R1" + DetailPrint "PASSED If..ElseIf..Else..EndIf test" + ${Else} + DetailPrint "FAILED If..ElseIf..Else..EndIf test" + ${EndIf} ; ifthen..|..| - StrCpy $R1 1 ; change to test ifthen statement. - ${ifthen} $R1 = 1 ${|} MessageBox MB_OK "R1=1" ${|} + StrCpy $R1 1 + StrCpy $R2 "" + ${ifthen} $R1 = 1 ${|} StrCpy $R2 $R2A ${|} + ${ifthen} $R1 = 2 ${|} StrCpy $R2 $R2B ${|} + ${If} $R2 == "A" + DetailPrint "PASSED IfThen test" + ${Else} + DetailPrint "FAILED IfThen test" + ${EndIf} ; ifcmd..||..| - StrCpy $R1 "example.nsi" ; change to test ifcmd statement - ${ifcmd} IfFileExists "example.nsi" ${||} MessageBox MB_OK "IfFileExists: R1=$R1" ${|} + StrCpy $R2 "" + ${ifcmd} MessageBox MB_YESNO "Please press Yes" IDYES ${||} StrCpy $R2 $R2A ${|} + ${ifcmd} MessageBox MB_YESNO|MB_DEFBUTTON2 "Please press No" IDYES ${||} StrCpy $R2 $R2B ${|} + ${If} $R2 == "A" + DetailPrint "PASSED IfCmd test" + ${Else} + DetailPrint "FAILED IfCmd test" + ${EndIf} - ; select..case..case2..case3..case4..case5..case_else..endselect - StrCpy $R1 1 ;change to test the following if statement - ${select} $R1 - ${case} "1" - MessageBox MB_OK "case: R1=1" - ${case} "2" - MessageBox MB_OK "case: R1=2" - ${case2} "3" "4" - MessageBox MB_OK "case2: R1=3 or 4, R1=$R1" - ${case_else} - MessageBox MB_OK "caseelse: R1=$R1" - ${endselect} + ; select..case..case2..case3..case4..case5..caseelse..endselect + StrCpy $R1 1 + StrCpy $R2 "" + ${Select} $R1 + ${Case} "1" + StrCpy $R2 $R2A + ${Case} "2" + StrCpy $R2 $R2B + ${Case2} "3" "4" + StrCpy $R2 $R2C + ${CaseElse} + StrCpy $R2 $R2D + ${EndSelect} + ${Select} $R1 + ${Case} "2" + StrCpy $R2 $R2A + ${Case} "3" + StrCpy $R2 $R2B + ${Case2} "4" "5" + StrCpy $R2 $R2C + ${CaseElse} + StrCpy $R2 $R2D + ${EndSelect} + ${Select} $R1 + ${Case} "3" + StrCpy $R2 $R2A + ${Case} "4" + StrCpy $R2 $R2B + ${Case2} "5" "1" + StrCpy $R2 $R2C + ${CaseElse} + StrCpy $R2 $R2D + ${EndSelect} + ${Select} $R1 + ${Case} "4" + StrCpy $R2 $R2A + ${Case} "5" + StrCpy $R2 $R2B + ${Case2} "1" "2" + StrCpy $R2 $R2C + ${CaseElse} + StrCpy $R2 $R2D + ${EndSelect} + ${If} $R2 == "ADCC" + DetailPrint "PASSED Select..Case*..EndSelect test" + ${Else} + DetailPrint "FAILED Select..Case*..EndSelect test" + ${EndIf} - ; for..exitfor..next - ${for} $R1 1 5 - MessageBox MB_OK "for: R1=$R1" - ${next} - - ; foreach..exitfor..next - ${foreach} $R1 10 1 - 1 - MessageBox MB_OK "foreach: R1=$R1" - ${next} + ; for[each]..exitfor..next + StrCpy $R2 "" + ${For} $R1 1 5 + StrCpy $R2 $R2$R1 + ${Next} + ${ForEach} $R1 10 1 - 1 + StrCpy $R2 $R2$R1 + ${Next} + ${For} $R1 1 0 + StrCpy $R2 $R2$R1 + ${Next} + ${If} $R2 == "1234510987654321" + DetailPrint "PASSED For[Each]..Next test" + ${Else} + DetailPrint "FAILED For[Each]..Next test" + ${EndIf} ; do..exitdo..loop StrCpy $R1 0 - ${do} + StrCpy $R2 "" + ${Do} + StrCpy $R2 $R2$R1 IntOp $R1 $R1 + 1 - MessageBox MB_YESNO "Do..Loop statement test, iteration $R1.$\nDo you want to stop?" IDYES 0 IDNO +2 - ${exitdo} - ${loop} + ${If} $R1 > 10 + ${ExitDo} + ${EndIf} + ${Loop} + ${If} $R2 == "012345678910" + DetailPrint "PASSED Do..ExitDo..Loop test" + ${Else} + DetailPrint "FAILED Do..ExitDo..Loop test" + ${EndIf} - ; do..exitdo..loopuntil + ; do..exitdo..loopuntil StrCpy $R1 0 - ${do} + StrCpy $R2 "" + ${Do} + StrCpy $R2 $R2$R1 IntOp $R1 $R1 + 1 - ${loopuntil} $R1 >= 5 ; Change to test loop until - MessageBox MB_OK "do..loopuntil: R1=$R1" + ${LoopUntil} $R1 >= 5 + ${If} $R2 == "01234" + DetailPrint "PASSED Do..ExitDo..LoopUntil test" + ${Else} + DetailPrint "FAILED Do..ExitDo..LoopUntil test" + ${EndIf} ; dountil..exitdo..loop StrCpy $R1 0 - ${dountil} $R1 >= 5 ; Change to test loop until + StrCpy $R2 "" + ${DoUntil} $R1 >= 5 + StrCpy $R2 $R2$R1 IntOp $R1 $R1 + 1 - ${loop} - MessageBox MB_OK "dountil..loop: R1=$R1" + ${Loop} + ${If} $R2 == "01234" + DetailPrint "PASSED DoUntil..ExitDo..Loop test" + ${Else} + DetailPrint "FAILED DoUntil..ExitDo..Loop test" + ${EndIf} - ; exitdo statement test + ; nested do test StrCpy $R1 0 StrCpy $R2 0 - ${do} + StrCpy $R3 "" + ${Do} + StrCpy $R3 $R3$R1$R2 IntOp $R1 $R1 + 1 - IntCmp $R1 5 +2 +2 0 - ${exitdo} + ${If} $R1 > 5 + ${ExitDo} + ${EndIf} StrCpy $R2 0 - ${do} + ${Do} + StrCpy $R3 $R3$R1$R2 IntOp $R2 $R2 + 1 - MessageBox MB_OK "loop1: $R1$\nloop2: $R2" - IntCmp $R2 5 0 +2 0 - ${exitdo} - ${loop} - ${loop} - MessageBox MB_OK "loopR1: $R1$\nloop2: $R2" + ${If} $R2 >= 5 + ${ExitDo} + ${EndIf} + ${Loop} + ${Loop} + ${If} $R3 == "00101112131415202122232425303132333435404142434445505152535455" + DetailPrint "PASSED nested Do test" + ${Else} + DetailPrint "FAILED nested Do test" + ${EndIf} - ; break..continue labels + ; while..exitwhile..endwhile (exact replica of dowhile..enddo} StrCpy $R1 0 - ${do} - StrCpy $R2 0 - ${do} - IntOp $R2 $R2 + 1 - MessageBox MB_YESNO "Do..Loop1: $R1.$\nDo..Loop2: $R2.$\n$\nDo you want to stop Loop2?" IDYES ${_Break} IDNO ${_Continue} - ${loop} + StrCpy $R2 "" + ${While} $R1 < 5 + StrCpy $R2 $R2$R1 IntOp $R1 $R1 + 1 - MessageBox MB_YESNO "Do..Loop1: $R1.$\nDo..Loop2: $R2.$\n$\nDo you want to stop Loop1?" IDYES ${_Break} IDNO ${_Continue} - ${loop} + ${EndWhile} + ${If} $R2 == "01234" + DetailPrint "PASSED While..ExitWhile..EndWhile test" + ${Else} + DetailPrint "FAILED While..ExitWhile..EndWhile test" + ${EndIf} - ; while..exitwhile..endwhile - StrCpy $R1 0 - ${while} $R1 < 5 ;change to test while statement. - IntOp $R1 $R1 + 1 - ${endwhile} - MessageBox MB_OK "while: R1=$R1" + ; kinds of if other than "value1 comparison value2" + ClearErrors + FindFirst $R1 $R2 "$PROGRAMFILES\*" + ${Unless} ${Errors} + ${Do} + ${Select} $R2 + ${Case2} "." ".." + ; Do nothing + ${CaseElse} + DetailPrint "Found $PROGRAMFILES\$R2" + ${EndSelect} + FindNext $R1 $R2 + ${LoopUntil} ${Errors} + FindClose $R1 + ${EndUnless} -SectionEnd \ No newline at end of file + StrCpy $R1 "example.xxx" + ${If} ${FileExists} "${__FILE__}" + DetailPrint 'Source file "${__FILE__}" still exists' + ${Else} + DetailPrint 'Source file "${__FILE__}" has gone' + ${EndIf} + +SectionEnd diff --git a/Include/LogicLib.nsh b/Include/LogicLib.nsh index 29c2fc75..fcd3db5d 100644 --- a/Include/LogicLib.nsh +++ b/Include/LogicLib.nsh @@ -1,7 +1,10 @@ ; NSIS LOGIC LIBRARY - logiclib.nsh -; Version 2.2 - 10/07/2003 -; Questions/Comments - dselkirk@hotmail.com -; Special thanks to eccles for Push/Pop Logic! +; Version 2.3 - 12/06/2003 +; By dselkirk@hotmail.com +; and eccles@users.sf.net +; +; Questions/Comments - +; See http://forums.winamp.com/showthread.php?s=&postid=1116241 ; ; Description: ; Provides the use of various logic statements within NSIS. @@ -11,48 +14,83 @@ ; - Structure redesign based upon version by eccles. ; - No statement limitations. ; - Following statements are now available. -; if..elseif..else..endif +; if/unless..elseif/unless..else..endif/unless ; - Conditionally executes a group of statements, depending on the value of an expression. ; ifthen..|..| ; - Conditionally executes an inline statement, depending on the value of an expression. ; ifcmd..||..| ; - Conditionally executes an inline statement, depending on a True value of the provided NSIS function. -; select..case..case2..case3..case4..case5..case_else..endselect +; select..case..case2..case3..case4..case5..caseelse..endselect ; - Executes one of several groups of statements, depending on the value of an expression. -; for..exitfor..next +; for..exitfor..continue..break..next ; - Repeats a group of statements a specified number of times. ; foreach..exitfor..continue..break..next ; - Repeats a group of statements a specified number of times stepping in order specified. ; do..exitdo..continue..break..loop ; - Repeats a block of statements until stopped. +; dowhile..exitdo..continue..break..loop +; - Repeats a block of statements while a condition is True. ; dountil..exitdo..continue..break..loop ; - Repeats a block of statements until a condition is True. +; do..exitdo..continue..break..loopwhile +; - Repeats a block of statements while a condition is True. ; do..exitdo..continue..break..loopuntil ; - Repeats a block of statements until a condition is True. ; while..exitwhile..continue..break..endwhile -; - Executes a series of statements as long as a given condition is True. +; - Same as dowhile..loop. ; ; Usage: ; See example.nsi ; ; History: -; 1.0 - 09/19/2003 - Initial release. -; 1.1 - 09/20/2003 - Added simplified macros and removed NAME requirement. -; 1.2 - 09/21/2003 - Changed library name to LogicLib. -; - Allow for 5 statements deep without use of name variable. -; - Added If..ElseIf..Else..Endif statements. -; 1.3 - 09/22/2003 - Fixed maximum allow statements. -; - Now allows 10 statement depth. -; - Condensed code. -; 2.0 - 10/03/2003 - Inital release 2, see notes. -; 2.1 - 10/05/2003 - Added continue and break labels to repeat type statements. -; 2.2 - 10/07/2003 - Updates by eccles -; - Simplified IfThen by utilising If and EndIf. -; - Simplified For by utilising ForEach. -; - Fixed ForEach missing the final iteration. -; - Fixed a couple of Break/Continue bugs. +; 1.0 - 09/19/2003 - Initial release. +; 1.1 - 09/20/2003 - Added simplified macros and removed NAME requirement. +; 1.2 - 09/21/2003 - Changed library name to LogicLib. +; - Allow for 5 statements deep without use of name variable. +; - Added If..ElseIf..Else..Endif statements. +; 1.3 - 09/22/2003 - Fixed maximum allow statements. +; - Now allows 10 statement depth. +; - Condensed code. +; 2.0 - 10/03/2003 - Inital release 2, see notes. +; 2.1 - 10/05/2003 - Added continue and break labels to repeat type statements. +; 2.2 - 10/07/2003 - Updates by eccles +; - Simplified IfThen by utilising If and EndIf. +; - Simplified For by utilising ForEach. +; - Fixed ForEach missing the final iteration. +; - Fixed a couple of Break/Continue bugs. +; 2.3 - 12/10/2003 - Much reworking and refactoring of things to help reduce +; duplication, etc. E.g. all loop varieties now go through +; a common set of macros. +; - Added built-in support for the rest of NSIS's built-in +; conditional tests (Abort, Errors, FileExists, RebootFlag, +; Silent). +; - Added ability to use any NSIS conditional command in a +; normal If type statement (no longer restricted to the +; specialised IfCmd statement). +; - Optimised the code produced by If (fewer Goto's). +; - Added statement similar to If that works in reverse: +; "Unless" executes the code in the contained block if the +; condition is false. If, Unless, ElseIf, ElseUnless, EndIf +; and ElseUnless can be used freely in any combination. +; - Fixed bug where using Continue in a Do..LoopUntil loop +; went to the top of the loop and not the loop condition. +; - Added DoWhile..Loop and Do..LoopWhile loop varieties (the +; existing While..EndWhile loop is still available and is +; identical to DoWhile..Loop). +; - Optimised the code prodiced by Select (fewer Goto's). +; - Renamed Case_Else to CaseElse (nothing else has an +; underscore so why should that one). The old name is still +; available too though (if you must). +; - CaseElse can also be called Default (for the C-minded). +!verbose push !verbose 3 +!ifndef LOGICLIB_VERBOSITY + !define LOGICLIB_VERBOSITY 3 +!endif +!define _LOGICLIB_VERBOSITY ${LOGICLIB_VERBOSITY} +!undef LOGICLIB_VERBOSITY +!verbose ${_LOGICLIB_VERBOSITY} !ifndef LOGICLIB !define LOGICLIB @@ -60,46 +98,30 @@ !define || "' '" !macro _PushLogic - !ifdef _Logic ; If we already have a statement - !define _CurLogic ${_Logic} - !undef _Logic - !define _Logic _${__LINE__} - !define ${_Logic}Prev ${_CurLogic} ; Save the current logic - !undef _CurLogic - !else - !define _Logic _${__LINE__} ; Initialise for first statement - !endif + !insertmacro _PushScope Logic _${__LINE__} !macroend !macro _PopLogic - !ifdef ${_Logic}Prev ; If a previous statment was active then restore it - !define _CurLogic ${_Logic} - !undef _Logic - !define _Logic ${${_CurLogic}Prev} - !undef ${_CurLogic}Prev - !undef _CurLogic - !else - !undef _Logic - !endif + !insertmacro _PopScope Logic !macroend - !macro _PushCustom Type label - !ifdef _${Type} ; If we already have a statement + !macro _PushScope Type label + !ifdef _${Type} ; If we already have a statement !define _Cur${Type} ${_${Type}} !undef _${Type} !define _${Type} ${label} - !define ${_${Type}}Prev${Type} ${_Cur${Type}} ; Save the current logic + !define ${_${Type}}Prev${Type} ${_Cur${Type}} ; Save the current logic !undef _Cur${Type} !else - !define _${Type} ${label} ; Initialise for first statement + !define _${Type} ${label} ; Initialise for first statement !endif !macroend - !macro _PopCustom Type + !macro _PopScope Type !ifndef _${Type} !error "Cannot use _Pop${Type} without a preceding _Push${Type}" !endif - !ifdef ${_${Type}}Prev${Type} ; If a previous statment was active then restore it + !ifdef ${_${Type}}Prev${Type} ; If a previous statment was active then restore it !define _Cur${Type} ${_${Type}} !undef _${Type} !define _${Type} ${${_Cur${Type}}Prev${Type}} @@ -112,366 +134,397 @@ ; String tests !macro _== _a _b _t _f - StrCmp "${_a}" "${_b}" "${_t}" "${_f}" + StrCmp `${_a}` `${_b}` `${_t}` `${_f}` !macroend !macro _!= _a _b _t _f - !insertmacro _== "${_a}" "${_b}" "${_f}" "${_t}" + !insertmacro _== `${_a}` `${_b}` `${_f}` `${_t}` !macroend ; Integer tests !macro _= _a _b _t _f - IntCmp "${_a}" "${_b}" "${_t}" "${_f}" "${_f}" + IntCmp `${_a}` `${_b}` `${_t}` `${_f}` `${_f}` !macroend !macro _<> _a _b _t _f - !insertmacro _= "${_a}" "${_b}" "${_f}" "${_t}" + !insertmacro _= `${_a}` `${_b}` `${_f}` `${_t}` !macroend !macro _< _a _b _t _f - IntCmp "${_a}" "${_b}" "${_f}" "${_t}" "${_f}" + IntCmp `${_a}` `${_b}` `${_f}` `${_t}` `${_f}` !macroend !macro _>= _a _b _t _f - !insertmacro _< "${_a}" "${_b}" "${_f}" "${_t}" + !insertmacro _< `${_a}` `${_b}` `${_f}` `${_t}` !macroend !macro _> _a _b _t _f - IntCmp "${_a}" "${_b}" "${_f}" "${_f}" "${_t}" + IntCmp `${_a}` `${_b}` `${_f}` `${_f}` `${_t}` !macroend !macro _<= _a _b _t _f - !insertmacro _> "${_a}" "${_b}" "${_f}" "${_t}" + !insertmacro _> `${_a}` `${_b}` `${_f}` `${_t}` !macroend - !macro IfCmd _a _t - !verbose 3 + ; Flag tests + !macro _Abort _a _b _t _f + IfAbort `${_t}` `${_f}` + !macroend + !define Abort `"" Abort ""` + + !macro _Errors _a _b _t _f + IfErrors `${_t}` `${_f}` + !macroend + !define Errors `"" Errors ""` + + !macro _FileExists _a _b _t _f + IfFileExists `${_b}` `${_t}` `${_f}` + !macroend + !define FileExists `"" FileExists` + + !macro _RebootFlag _a _b _t _f + IfRebootFlag `${_t}` `${_f}` + !macroend + !define RebootFlag `"" RebootFlag ""` + + !macro _Silent _a _b _t _f + IfSilent `${_t}` `${_f}` + !macroend + !define Silent `"" Silent ""` + + ; "Any instruction" test + !macro _Cmd _a _b _t _f + !define _t=${_t} + !ifdef _t= + !define __t +2 ; If no jump then make sure we skip the Goto below + !else + !define __t ${_t} + !endif + !undef _t=${_t} + ${_b} ${__t} + !undef __t + Goto ${_f} + !macroend + !define Cmd `"" Cmd` + + !define IfCmd `!insertmacro _IfThen "" Cmd ${|}` + + !macro _If _c _a _o _b + !verbose push + !verbose ${LOGICLIB_VERBOSITY} !insertmacro _PushLogic - !define ${_Logic}IfTrue _${__LINE__} - !define ${_Logic}IfCmd _${__LINE__} - ${_a} ${${_Logic}IfTrue} - Goto ${${_Logic}IfCmd} - ${${_Logic}IfTrue}: - ${_t} - Goto ${${_Logic}IfCmd} - ${${_Logic}IfCmd}: ; Place the EndIf - !undef ${_Logic}IfTrue - !undef ${_Logic}IfCmd - !insertmacro _PopLogic - !verbose 4 + !define ${_Logic}If + !define ${_Logic}Else _${__LINE__} ; Get a label for the Else + !define _c=${_c} + !ifdef _c=true ; If is true + !insertmacro _${_o} `${_a}` `${_b}` "" ${${_Logic}Else} + !else ; If condition is false + !insertmacro _${_o} `${_a}` `${_b}` ${${_Logic}Else} "" + !endif + !undef _c=${_c} + !verbose pop !macroend - !define IfCmd "!insertmacro IfCmd '" + !define If `!insertmacro _If true` + !define Unless `!insertmacro _If false` - !macro If _a _o _b - !verbose 3 - !insertmacro _PushLogic - !define ${_Logic}Elseif _${__LINE__} ; Get a label for the (provisional) EndIf (it might turn out to be Else) - !define ${_Logic}EndIf _${__LINE__} ; Get a label for the (provisional) EndIf (it might turn out to be Else) - !insertmacro _${_o} "${_a}" "${_b}" "" ${${_Logic}Elseif} - !verbose 4 + !macro _Else + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + !ifndef _Logic | ${_Logic}If + !error "Cannot use Else without a preceding If or Unless" + !endif + !ifndef ${_Logic}Else + !error "Cannot use Else following an Else" + !endif + !ifndef ${_Logic}EndIf ; First Else for this If? + !define ${_Logic}EndIf _${__LINE__} ; Get a label for the EndIf + !endif + Goto ${${_Logic}EndIf} ; Go to the EndIf + ${${_Logic}Else}: ; Place the Else label + !undef ${_Logic}Else ; and remove it + !verbose pop !macroend - !define If "!insertmacro If" + !define Else `!insertmacro _Else` - !macro Else - !verbose 3 - !ifndef _Logic | ${_Logic}Elseif - !error "Cannot use Else|Elseif without a preceding If" + !macro _ElseIf _c _a _o _b + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + ${Else} ; Perform the Else + !define ${_Logic}Else _${__LINE__} ; Get a label for the next Else and perform the new If + !define _c=${_c} + !ifdef _c=true ; If is true + !insertmacro _${_o} `${_a}` `${_b}` "" ${${_Logic}Else} + !else ; If condition is false + !insertmacro _${_o} `${_a}` `${_b}` ${${_Logic}Else} "" + !endif + !undef _c=${_c} + !verbose pop + !macroend + !define ElseIf `!insertmacro _ElseIf true` + !define ElseUnless `!insertmacro _ElseIf false` + + !macro _EndIf _n + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + !ifndef _Logic | ${_Logic}If + !error "Cannot use End${_n} without a preceding If or Unless" !endif !ifdef ${_Logic}Else - !error "Cannot use Else after Else" + ${${_Logic}Else}: ; Place the Else label + !undef ${_Logic}Else ; and remove it !endif - Goto ${${_Logic}EndIf} - !define ${_Logic}Else ${${_Logic}Elseif} ; Save current Else label - !undef ${_Logic}Elseif - !define ${_Logic}Elseif _${__LINE__} ; Get a label for the (new) EndIf and go there - ${${_Logic}Else}: ; Place the saved Else label - !verbose 4 - !macroend - !define Else "!insertmacro Else" - - !macro ElseIf _a _o _b - !verbose 3 - !insertmacro Else ; Place in Else code as normal - !undef ${_Logic}Else ; Forget the Else and perform the new If - !insertmacro _${_o} "${_a}" "${_b}" "" ${${_Logic}Elseif} - !verbose 4 - !macroend - !define ElseIf "!insertmacro ElseIf" - - !macro EndIf - !verbose 3 - !ifndef _Logic | ${_Logic}Elseif - !error "Cannot use EndIf without a preceding If" - !endif - Goto ${${_Logic}EndIf} - Goto ${${_Logic}ElseIf} - ${${_Logic}ElseIf}: - ${${_Logic}EndIf}: ; Place the EndIf - !undef ${_Logic}Elseif - !undef ${_Logic}EndIf - !ifdef ${_Logic}Else - !undef ${_Logic}Else ; Clear the Else flag + !ifdef ${_Logic}EndIf + ${${_Logic}EndIf}: ; Place the EndIf + !undef ${_Logic}EndIf ; and remove it !endif + !undef ${_Logic}If !insertmacro _PopLogic - !verbose 4 + !verbose pop !macroend - !define EndIf "!insertmacro EndIf" + !define EndIf `!insertmacro _EndIf If` + !define EndUnless `!insertmacro _EndIf Unless` - !macro IfThen _a _o _b _t - !verbose 3 - ${If} "${_a}" "${_o}" "${_b}" + !macro _IfThen _a _o _b _t + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + ${If} `${_a}` `${_o}` `${_b}` ${_t} ${EndIf} - !verbose 4 + !verbose pop !macroend - !define IfThen "!insertmacro IfThen" + !define IfThen `!insertmacro _IfThen` - !macro ForEach _v _f _t _o _s - !verbose 3 - StrCpy ${_v} ${_f} - !insertmacro _PushLogic - !define ${_Logic}For _${__LINE__} ; Get a label for the start of the loop - !define ${_Logic}For2 _${__LINE__} ; Get a label for the start of the loop - !define ${_Logic}Next _${__LINE__} ; Get a label for the end of the loop - !insertmacro _PushCustom "ExitFor" ${${_Logic}Next} - !insertmacro _PushCustom "Break" ${${_Logic}Next} - !insertmacro _PushCustom "Continue" ${${_Logic}For} - Goto ${${_Logic}For2} - ${${_Logic}For}: ; Insert the loop condition - IntOp ${_v} ${_v} ${_o} ${_s} - ${${_Logic}For2}: ; Insert the loop condition + !macro _ForEach _v _f _t _o _s + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + StrCpy "${_v}" "${_f}" ; Assign the initial value + Goto +2 ; Skip the loop expression for the first iteration + !define _DoLoopExpression `IntOp "${_v}" "${_v}" "${_o}" "${_s}"` ; Define the loop expression !define _o=${_o} - !ifdef _o=+ - !insertmacro _> ${_v} ${_t} ${${_Logic}Next} "" + !ifdef _o=+ ; Check the loop expression operator + !define __o > ; to determine the correct loop condition !else ifdef _o=- - !insertmacro _< ${_v} ${_t} ${${_Logic}Next} "" + !define __o < !else - !error "Unsupported ForEach step operator" + !error "Unsupported ForEach step operator (must be + or -)" !endif !undef _o=${_o} - !undef ${_Logic}For2 - !verbose 4 + !insertmacro _Do For false `${_v}` `${__o}` `${_t}` ; Let Do do the rest + !undef __o + !verbose pop !macroend - !define ForEach "!insertmacro ForEach" + !define ForEach `!insertmacro _ForEach` - !macro For _v _f _t - !verbose 3 - ${ForEach} "${_v}" "${_f}" "${_t}" + 1 - !verbose 4 + !macro _For _v _f _t + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + ${ForEach} `${_v}` `${_f}` `${_t}` + 1 ; Pass on to ForEach + !verbose pop !macroend - !define For "!insertmacro For" + !define For `!insertmacro _For` - !define ExitFor "Goto ${_ExitFor}" + !define ExitFor `!insertmacro _Goto ExitFor For` - !macro Next - !verbose 3 - !ifndef _Logic | ${_Logic}For - !error "Cannot use Next without a preceding For" - !endif - Goto ${${_Logic}For} ; Loop back to the For condition - ${${_Logic}Next}: ; Place the Next - !undef ${_Logic}For - !undef ${_Logic}Next - !insertmacro _PopLogic - !insertmacro _PopCustom "ExitFor" - !insertmacro _PopCustom "Break" - !insertmacro _PopCustom "Continue" - !verbose 4 - !macroend - !define Next "!insertmacro Next" + !define Next `!insertmacro _Loop For Next "" "" "" ""` - !macro While _a _o _b - !verbose 3 + !define While `!insertmacro _Do While true` + + !define ExitWhile `!insertmacro _Goto ExitWhile While` + + !define EndWhile `!insertmacro _Loop While EndWhile "" "" "" ""` + + !macro _Do _n _c _a _o _b + !verbose push + !verbose ${LOGICLIB_VERBOSITY} !insertmacro _PushLogic - !define ${_Logic}While _${__LINE__} ; Get a label for the start of the loop - !define ${_Logic}EndWhile _${__LINE__} ; Get a label for the end of the loop - !insertmacro _PushCustom "ExitWhile" ${${_Logic}EndWhile} - !insertmacro _PushCustom "Break" ${${_Logic}EndWhile} - !insertmacro _PushCustom "Continue" ${${_Logic}While} - ${${_Logic}While}: ; Insert the loop condition - !insertmacro _${_o} "${_a}" "${_b}" "" ${${_Logic}EndWhile} - !verbose 4 - !macroend - !define While "!insertmacro While" - - !define ExitWhile "Goto ${_ExitWhile}" - - !macro EndWhile - !verbose 3 - !ifndef _Logic | ${_Logic}While - !error "Cannot use EndWhile without a preceding While" + !define ${_Logic}${_n} _${__LINE__} ; Get a label for the start of the loop + ${${_Logic}${_n}}: + !insertmacro _PushScope Exit${_n} _${__LINE__} ; Get a label for the end of the loop + !insertmacro _PushScope Break ${_Exit${_n}} ; Break goes to the end of the loop + !ifdef _DoLoopExpression + ${_DoLoopExpression} ; Special extra parameter for inserting code + !undef _DoLoopExpression ; between the Continue label and the loop condition !endif - Goto ${${_Logic}While} ; Loop back to the While condition - ${${_Logic}EndWhile}: ; Place the EndWhile - !undef ${_Logic}While - !undef ${_Logic}EndWhile - !insertmacro _PopLogic - !insertmacro _PopCustom "ExitWhile" - !insertmacro _PopCustom "Break" - !insertmacro _PopCustom "Continue" - !verbose 4 + !define _c=${_c} + !ifdef _c= ; No starting condition + !insertmacro _PushScope Continue _${__LINE__} ; Get a label for Continue at the end of the loop + !else + !insertmacro _PushScope Continue ${${_Logic}${_n}} ; Continue goes to the start of the loop + !ifdef _c=true ; If is true + !insertmacro _${_o} `${_a}` `${_b}` "" ${_Exit${_n}} + !else ; If condition is false + !insertmacro _${_o} `${_a}` `${_b}` ${_Exit${_n}} "" + !endif + !endif + !undef _c=${_c} + !define ${_Logic}Condition ${_c} ; Remember the condition used + !verbose pop !macroend - !define EndWhile "!insertmacro EndWhile" + !define Do `!insertmacro _Do Do "" "" "" ""` + !define DoWhile `!insertmacro _Do Do true` + !define DoUntil `!insertmacro _Do Do false` - !macro Do - !verbose 3 + !macro _Goto _n _s + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + !ifndef _${_n} + !error "Cannot use ${_n} without a preceding ${_s}" + !endif + Goto ${_${_n}} + !verbose pop + !macroend + !define ExitDo `!insertmacro _Goto ExitDo Do` + + !macro _Loop _n _e _c _a _o _b + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + !ifndef _Logic | ${_Logic}${_n} + !error "Cannot use ${_e} without a preceding ${_n}" + !endif + !define _c=${${_Logic}Condition} + !ifdef _c= ; If Do had no condition place the Continue label + ${_Continue}: + !endif + !undef _c=${${_Logic}Condition} + !define _c=${_c} + !ifdef _c= ; No ending condition + Goto ${${_Logic}${_n}} + !else ifdef _c=true ; If condition is true + !insertmacro _${_o} `${_a}` `${_b}` ${${_Logic}${_n}} ${_Exit${_n}} + !else ; If condition is false + !insertmacro _${_o} `${_a}` `${_b}` ${_Exit${_n}} ${${_Logic}${_n}} + !endif + !undef _c=${_c} + Goto ${_Continue} ; Just to ensure it is referenced at least once + ${_Exit${_n}}: ; Place the loop exit point + !undef ${_Logic}Condition + !insertmacro _PopScope Continue + !insertmacro _PopScope Break + !insertmacro _PopScope Exit${_n} + !undef ${_Logic}${_n} + !insertmacro _PopLogic + !verbose pop + !macroend + !define Loop `!insertmacro _Loop Do Loop "" "" "" ""` + !define LoopWhile `!insertmacro _Loop Do LoopWhile true` + !define LoopUntil `!insertmacro _Loop Do LoopUntil false` + + !define Continue `!insertmacro _Goto Continue "For or Do or While"` + !define Break `!insertmacro _Goto Break "For or Do or While"` + + !macro _Select _a + !verbose push + !verbose ${LOGICLIB_VERBOSITY} !insertmacro _PushLogic - !define ${_Logic}Do _${__LINE__} ; Get a label for the start of the loop - !define ${_Logic}Loop _${__LINE__} ; Get a label for the end of the loop - !insertmacro _PushCustom "ExitDo" ${${_Logic}Loop} - !insertmacro _PushCustom "Break" ${${_Logic}Loop} - !insertmacro _PushCustom "Continue" ${${_Logic}Do} - ${${_Logic}Do}: ; Insert the loop condition - !verbose 4 + !define ${_Logic}Select `${_a}` ; Remember the left hand side of the comparison + !verbose pop !macroend - !define Do "!insertmacro Do" + !define Select `!insertmacro _Select` - !macro DoUntil _a _o _b - !verbose 3 - !insertmacro Do - !insertmacro _${_o} "${_a}" "${_b}" ${${_Logic}Loop} "" - !verbose 4 - !macroend - !define DoUntil "!insertmacro DoUntil" - - !define ExitDo "Goto ${_ExitDo}" - - !macro Loop - !verbose 3 - !ifndef _Logic | ${_Logic}Do - !error "Cannot use EndWhile without a preceding Do" + !macro _CaseElse + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + !ifndef _Logic | ${_Logic}Select + !error "Cannot use Case without a preceding Select" !endif - Goto ${${_Logic}Do} ; Loop back to the Do condition - ${${_Logic}Loop}: ; Place the Loop - !undef ${_Logic}Do - !undef ${_Logic}Loop - !insertmacro _PopLogic - !insertmacro _PopCustom "ExitDo" - !insertmacro _PopCustom "Break" - !insertmacro _PopCustom "Continue" - !verbose 4 - !macroend - !define Loop "!insertmacro Loop" - - !macro LoopUntil _a _o _b - !verbose 3 - !ifndef _Logic | ${_Logic}Do - !error "Cannot use EndWhile without a preceding Do" + !ifdef ${_Logic}EndSelect ; This is set only after the first case + !ifndef ${_Logic}Else + !error "Cannot use Case following a CaseElse" + !endif + Goto ${${_Logic}EndSelect} ; Go to the EndSelect + ${${_Logic}Else}: ; Place the Else label + !undef ${_Logic}Else ; and remove it + !else + !define ${_Logic}EndSelect _${__LINE__} ; Get a label for the EndSelect !endif - !insertmacro _${_o} "${_a}" "${_b}" ${${_Logic}Loop} ${${_Logic}Do} - ${${_Logic}Loop}: ; Place the Loop - !undef ${_Logic}Do - !undef ${_Logic}Loop - !insertmacro _PopLogic - !insertmacro _PopCustom "ExitDo" - !insertmacro _PopCustom "Break" - !insertmacro _PopCustom "Continue" - !verbose 4 + !verbose pop !macroend - !define LoopUntil "!insertmacro LoopUntil" + !define CaseElse `!insertmacro _CaseElse` + !define Case_Else `!insertmacro _CaseElse` ; Compatibility with 2.2 and earlier + !define Default `!insertmacro _CaseElse` ; For the C-minded - !macro Select _a - !verbose 3 - !insertmacro _PushLogic - !define ${_Logic}Case _${__LINE__} ; Get a label for the (provisional) EndSelect (it might turn out to be case_else) - !define ${_Logic}EndSelect _${__LINE__} ; Get a label for the (provisional) EndIf (it might turn out to be Else) - !define ${_Logic}Value "${_a}" - Goto ${${_Logic}Case} - !verbose 4 + !macro _Case _a + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + ${CaseElse} ; Perform the CaseElse + !define ${_Logic}Else _${__LINE__} ; Get a label for the next Else and perform the new Case + !insertmacro _== `${${_Logic}Select}` `${_a}` "" ${${_Logic}Else} + !verbose pop !macroend - !define Select "!insertmacro Select" + !define Case `!insertmacro _Case` - !macro Case_Else - !verbose 3 - !ifndef _Logic | ${_Logic}Case - !error "Cannot use Case|case_else without a preceding Select" - !endif - !ifdef ${_Logic}case_else - !error "Cannot use case_else after case_else" - !endif - Goto ${${_Logic}EndSelect} - !define ${_Logic}case_else ${${_Logic}Case} ; Save current case_else label - !undef ${_Logic}Case - !define ${_Logic}Case _${__LINE__} ; Get a label for the (new) EndSelect and go there - ${${_Logic}case_else}: ; Place the saved case_else label - !verbose 4 + !macro _Case2 _a _b + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + ${CaseElse} ; Perform the CaseElse + !define ${_Logic}Else _${__LINE__} ; Get a label for the next Else and perform the new Case + !insertmacro _== `${${_Logic}Select}` `${_a}` +2 "" + !insertmacro _== `${${_Logic}Select}` `${_b}` "" ${${_Logic}Else} + !verbose pop !macroend - !define case_else "!insertmacro case_else" + !define Case2 `!insertmacro _Case2` - !macro Case _a - !verbose 3 - !insertmacro Case_Else ; Place in case_else code as normal - !undef ${_Logic}case_else ; Forget the case_else and perform the new Case - !insertmacro _== "${_a}" "${${_Logic}Value}" "" ${${_Logic}Case} - !verbose 4 + !macro _Case3 _a _b _c + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + ${CaseElse} ; Perform the CaseElse + !define ${_Logic}Else _${__LINE__} ; Get a label for the next Else and perform the new Case + !insertmacro _== `${${_Logic}Select}` `${_a}` +3 "" + !insertmacro _== `${${_Logic}Select}` `${_b}` +2 "" + !insertmacro _== `${${_Logic}Select}` `${_c}` "" ${${_Logic}Else} + !verbose pop !macroend - !define Case "!insertmacro Case" + !define Case3 `!insertmacro _Case3` - !macro Case2 _a _b - !verbose 3 - !insertmacro case_else ; Place in case_else code as normal - !undef ${_Logic}case_else ; Forget the case_else and perform the new Case - !insertmacro _== "${_a}" "${${_Logic}Value}" +2 0 - !insertmacro _== "${_b}" "${${_Logic}Value}" 0 ${${_Logic}Case} - !verbose 4 + !macro _Case4 _a _b _c _d + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + ${CaseElse} ; Perform the CaseElse + !define ${_Logic}Else _${__LINE__} ; Get a label for the next Else and perform the new Case + !insertmacro _== `${${_Logic}Select}` `${_a}` +4 "" + !insertmacro _== `${${_Logic}Select}` `${_b}` +3 "" + !insertmacro _== `${${_Logic}Select}` `${_c}` +2 "" + !insertmacro _== `${${_Logic}Select}` `${_d}` "" ${${_Logic}Else} + !verbose pop !macroend - !define Case2 "!insertmacro Case2" + !define Case4 `!insertmacro _Case4` - !macro Case3 _a _b _c - !verbose 3 - !insertmacro case_else ; Place in case_else code as normal - !undef ${_Logic}case_else ; Forget the case_else and perform the new Case - !insertmacro _== "${_a}" "${${_Logic}Value}" +3 0 - !insertmacro _== "${_b}" "${${_Logic}Value}" +2 0 - !insertmacro _== "${_c}" "${${_Logic}Value}" 0 ${${_Logic}Case} - !verbose 4 + !macro _Case5 _a _b _c _d _e + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + ${CaseElse} ; Perform the CaseElse + !define ${_Logic}Else _${__LINE__} ; Get a label for the next Else and perform the new Case + !insertmacro _== `${${_Logic}Select}` `${_a}` +5 "" + !insertmacro _== `${${_Logic}Select}` `${_b}` +4 "" + !insertmacro _== `${${_Logic}Select}` `${_c}` +3 "" + !insertmacro _== `${${_Logic}Select}` `${_d}` +2 "" + !insertmacro _== `${${_Logic}Select}` `${_e}` "" ${${_Logic}Else} + !verbose pop !macroend - !define Case3 "!insertmacro Case3" + !define Case5 `!insertmacro _Case5` - !macro Case4 _a _b _c _d - !verbose 3 - !insertmacro case_else ; Place in case_else code as normal - !undef ${_Logic}case_else ; Forget the case_else and perform the new Case - !insertmacro _== "${_a}" "${${_Logic}Value}" +4 0 - !insertmacro _== "${_b}" "${${_Logic}Value}" +3 0 - !insertmacro _== "${_c}" "${${_Logic}Value}" +2 0 - !insertmacro _== "${_d}" "${${_Logic}Value}" 0 ${${_Logic}Case} - !verbose 4 - !macroend - !define Case4 "!insertmacro Case4" - - !macro Case5 _a _b _c _d _e - !verbose 3 - !insertmacro case_else ; Place in case_else code as normal - !undef ${_Logic}case_else ; Forget the case_else and perform the new Case - !insertmacro _== "${_a}" "${${_Logic}Value}" +5 0 - !insertmacro _== "${_b}" "${${_Logic}Value}" +4 0 - !insertmacro _== "${_c}" "${${_Logic}Value}" +3 0 - !insertmacro _== "${_d}" "${${_Logic}Value}" +2 0 - !insertmacro _== "${_e}" "${${_Logic}Value}" 0 ${${_Logic}Case} - !verbose 4 - !macroend - !define Case5 "!insertmacro Case5" - - !macro EndSelect - !verbose 3 - !ifndef _Logic | ${_Logic}Case + !macro _EndSelect + !verbose push + !verbose ${LOGICLIB_VERBOSITY} + !ifndef _Logic | ${_Logic}Select !error "Cannot use EndSelect without a preceding Select" !endif - Goto ${${_Logic}Case} - Goto ${${_Logic}EndSelect} - ${${_Logic}Case}: - ${${_Logic}EndSelect}: ; Place the EndSelect - !undef ${_Logic}Case - !undef ${_Logic}EndSelect - !undef ${_Logic}Value - !ifdef ${_Logic}case_else - !undef ${_Logic}case_else ; Clear the case_else flag + !ifdef ${_Logic}Else + ${${_Logic}Else}: ; Place the Else label + !undef ${_Logic}Else ; and remove it !endif + !ifdef ${_Logic}EndSelect ; This won't be set if there weren't any cases + ${${_Logic}EndSelect}: ; Place the EndSelect + !undef ${_Logic}EndSelect ; and remove it + !endif + !undef ${_Logic}Select !insertmacro _PopLogic - !verbose 4 + !verbose pop !macroend - !define EndSelect "!insertmacro EndSelect" + !define EndSelect `!insertmacro _EndSelect` !endif ; LOGICLIB -!verbose 4 +!verbose 3 +!define LOGICLIB_VERBOSITY ${_LOGICLIB_VERBOSITY} +!undef _LOGICLIB_VERBOSITY +!verbose pop