1; NSIS LOGIC LIBRARY - LogicLib.nsh
2; see mingw-file-association.nshmingw-file-association.nsh for license info
3; Version 2.6 - 08/12/2007
4; By dselkirk@hotmail.com
5; and eccles@users.sf.net
6; with IfNot support added by Message
7;
8; Questions/Comments -
9; See http://forums.winamp.com/showthread.php?s=&postid=1116241
10;
11; Description:
12;   Provides the use of various logic statements within NSIS.
13;
14; Usage:
15;   The following "statements" are available:
16;       If|IfNot|Unless..{ElseIf|ElseIfNot|ElseUnless}..[Else]..EndIf|EndUnless
17;         - Conditionally executes a block of statements, depending on the value
18;           of an expression. IfNot and Unless are equivalent and
19;           interchangeable, as are ElseIfNot and ElseUnless.
20;       AndIf|AndIfNot|AndUnless|OrIf|OrIfNot|OrUnless
21;         - Adds any number of extra conditions to If, IfNot, Unless, ElseIf,
22;           ElseIfNot and ElseUnless statements.
23;       IfThen|IfNotThen..|..|
24;         - Conditionally executes an inline statement, depending on the value
25;           of an expression.
26;       IfCmd..||..|
27;         - Conditionally executes an inline statement, depending on a true
28;           value of the provided NSIS function.
29;       Select..{Case[2|3|4|5]}..[CaseElse|Default]..EndSelect
30;         - Executes one of several blocks of statements, depending on the value
31;           of an expression.
32;       Switch..{Case|CaseElse|Default}..EndSwitch
33;         - Jumps to one of several labels, depending on the value of an
34;           expression.
35;       Do[While|Until]..{ExitDo|Continue|Break}..Loop[While|Until]
36;         - Repeats a block of statements until stopped, or depending on the
37;           value of an expression.
38;       While..{ExitWhile|Continue|Break}..EndWhile
39;         - An alias for DoWhile..Loop (for backwards-compatibility)
40;       For[Each]..{ExitFor|Continue|Break}..Next
41;         - Repeats a block of statements varying the value of a variable.
42;
43;   The following "expressions" are available:
44;       Standard (built-in) string tests (which are case-insensitive):
45;         a == b; a != b
46;       Additional case-insensitive string tests (using System.dll):
47;         a S< b; a S>= b; a S> b; a S<= b
48;       Case-sensitive string tests:
49;         a S== b; a S!= b
50;       Standard (built-in) signed integer tests:
51;         a = b; a <> b; a < b; a >= b; a > b; a <= b
52;       Standard (built-in) unsigned integer tests:
53;         a U< b; a U>= b; a U> b; a U<= b
54;       64-bit integer tests (using System.dll):
55;         a L= b; a L<> b; a L< b; a L>= b; a L> b; a L<= b
56;       Built-in NSIS flag tests:
57;         ${Abort}; ${Errors}; ${RebootFlag}; ${Silent}
58;       Built-in NSIS other tests:
59;         ${FileExists} a
60;       Any conditional NSIS instruction test:
61;         ${Cmd} a
62;       Section flag tests:
63;         ${SectionIsSelected} a; ${SectionIsSectionGroup} a;
64;         ${SectionIsSectionGroupEnd} a; ${SectionIsBold} a;
65;         ${SectionIsReadOnly} a; ${SectionIsExpanded} a;
66;         ${SectionIsPartiallySelected} a
67;
68; Examples:
69;   See LogicLib.nsi in the Examples folder for lots of example usage.
70
71!verbose push
72!verbose 3
73!ifndef LOGICLIB_VERBOSITY
74  !define LOGICLIB_VERBOSITY 3
75!endif
76!define _LOGICLIB_VERBOSITY ${LOGICLIB_VERBOSITY}
77!undef LOGICLIB_VERBOSITY
78!verbose ${_LOGICLIB_VERBOSITY}
79
80!ifndef LOGICLIB
81  !define LOGICLIB
82  !define | "'"
83  !define || "' '"
84  !define LOGICLIB_COUNTER 0
85
86  !include Sections.nsh
87
88  !macro _LOGICLIB_TEMP
89    !ifndef _LOGICLIB_TEMP
90      !define _LOGICLIB_TEMP
91      Var /GLOBAL _LOGICLIB_TEMP  ; Temporary variable to aid the more elaborate logic tests
92    !endif
93  !macroend
94
95  !macro _IncreaseCounter
96    !define _LOGICLIB_COUNTER ${LOGICLIB_COUNTER}
97    !undef LOGICLIB_COUNTER
98    !define /math LOGICLIB_COUNTER ${_LOGICLIB_COUNTER} + 1
99    !undef _LOGICLIB_COUNTER
100  !macroend
101
102  !macro _PushLogic
103    !insertmacro _PushScope Logic _LogicLib_Label_${LOGICLIB_COUNTER}
104    !insertmacro _IncreaseCounter
105  !macroend
106
107  !macro _PopLogic
108    !insertmacro _PopScope Logic
109  !macroend
110
111  !macro _PushScope Type label
112    !ifdef _${Type}                                       ; If we already have a statement
113      !define _Cur${Type} ${_${Type}}
114      !undef _${Type}
115      !define _${Type} ${label}
116      !define ${_${Type}}Prev${Type} ${_Cur${Type}}       ; Save the current logic
117      !undef _Cur${Type}
118    !else
119      !define _${Type} ${label}                           ; Initialise for first statement
120    !endif
121  !macroend
122
123  !macro _PopScope Type
124    !ifndef _${Type}
125      !error "Cannot use _Pop${Type} without a preceding _Push${Type}"
126    !endif
127    !ifdef ${_${Type}}Prev${Type}                         ; If a previous statement was active then restore it
128      !define _Cur${Type} ${_${Type}}
129      !undef _${Type}
130      !define _${Type} ${${_Cur${Type}}Prev${Type}}
131      !undef ${_Cur${Type}}Prev${Type}
132      !undef _Cur${Type}
133    !else
134      !undef _${Type}
135    !endif
136  !macroend
137
138  ; String tests
139  !macro _== _a _b _t _f
140    StrCmp `${_a}` `${_b}` `${_t}` `${_f}`
141  !macroend
142
143  !macro _!= _a _b _t _f
144    !insertmacro _== `${_a}` `${_b}` `${_f}` `${_t}`
145  !macroend
146
147  ; Case-sensitive string tests
148  !macro _S== _a _b _t _f
149    StrCmpS `${_a}` `${_b}` `${_t}` `${_f}`
150  !macroend
151
152  !macro _S!= _a _b _t _f
153    !insertmacro _S== `${_a}` `${_b}` `${_f}` `${_t}`
154  !macroend
155
156  ; Extra string tests (cannot do these case-sensitively - I tried and lstrcmp still ignored the case)
157  !macro _StrCmpI _a _b _e _l _m
158    !insertmacro _LOGICLIB_TEMP
159    System::Call `kernel32::lstrcmpiA(ts, ts) i.s` `${_a}` `${_b}`
160    Pop $_LOGICLIB_TEMP
161    IntCmp $_LOGICLIB_TEMP 0 `${_e}` `${_l}` `${_m}`
162  !macroend
163
164  !macro _S< _a _b _t _f
165    !insertmacro _StrCmpI `${_a}` `${_b}` `${_f}` `${_t}` `${_f}`
166  !macroend
167
168  !macro _S>= _a _b _t _f
169    !insertmacro _S< `${_a}` `${_b}` `${_f}` `${_t}`
170  !macroend
171
172  !macro _S> _a _b _t _f
173    !insertmacro _StrCmpI `${_a}` `${_b}` `${_f}` `${_f}` `${_t}`
174  !macroend
175
176  !macro _S<= _a _b _t _f
177    !insertmacro _S> `${_a}` `${_b}` `${_f}` `${_t}`
178  !macroend
179
180  ; Integer tests
181  !macro _= _a _b _t _f
182    IntCmp `${_a}` `${_b}` `${_t}` `${_f}` `${_f}`
183  !macroend
184
185  !macro _<> _a _b _t _f
186    !insertmacro _= `${_a}` `${_b}` `${_f}` `${_t}`
187  !macroend
188
189  !macro _< _a _b _t _f
190    IntCmp `${_a}` `${_b}` `${_f}` `${_t}` `${_f}`
191  !macroend
192
193  !macro _>= _a _b _t _f
194    !insertmacro _< `${_a}` `${_b}` `${_f}` `${_t}`
195  !macroend
196
197  !macro _> _a _b _t _f
198    IntCmp `${_a}` `${_b}` `${_f}` `${_f}` `${_t}`
199  !macroend
200
201  !macro _<= _a _b _t _f
202    !insertmacro _> `${_a}` `${_b}` `${_f}` `${_t}`
203  !macroend
204
205  ; Unsigned integer tests (NB: no need for extra equality tests)
206  !macro _U< _a _b _t _f
207    IntCmpU `${_a}` `${_b}` `${_f}` `${_t}` `${_f}`
208  !macroend
209
210  !macro _U>= _a _b _t _f
211    !insertmacro _U< `${_a}` `${_b}` `${_f}` `${_t}`
212  !macroend
213
214  !macro _U> _a _b _t _f
215    IntCmpU `${_a}` `${_b}` `${_f}` `${_f}` `${_t}`
216  !macroend
217
218  !macro _U<= _a _b _t _f
219    !insertmacro _U> `${_a}` `${_b}` `${_f}` `${_t}`
220  !macroend
221
222  ; Int64 tests
223  !macro _Int64Cmp _a _o _b _t _f
224    !insertmacro _LOGICLIB_TEMP
225    System::Int64Op `${_a}` `${_o}` `${_b}`
226    Pop $_LOGICLIB_TEMP
227    !insertmacro _= $_LOGICLIB_TEMP 0 `${_f}` `${_t}`
228  !macroend
229
230  !macro _L= _a _b _t _f
231    !insertmacro _Int64Cmp `${_a}` = `${_b}` `${_t}` `${_f}`
232  !macroend
233
234  !macro _L<> _a _b _t _f
235    !insertmacro _L= `${_a}` `${_b}` `${_f}` `${_t}`
236  !macroend
237
238  !macro _L< _a _b _t _f
239    !insertmacro _Int64Cmp `${_a}` < `${_b}` `${_t}` `${_f}`
240  !macroend
241
242  !macro _L>= _a _b _t _f
243    !insertmacro _L< `${_a}` `${_b}` `${_f}` `${_t}`
244  !macroend
245
246  !macro _L> _a _b _t _f
247    !insertmacro _Int64Cmp `${_a}` > `${_b}` `${_t}` `${_f}`
248  !macroend
249
250  !macro _L<= _a _b _t _f
251    !insertmacro _L> `${_a}` `${_b}` `${_f}` `${_t}`
252  !macroend
253
254  ; Flag tests
255  !macro _Abort _a _b _t _f
256    IfAbort `${_t}` `${_f}`
257  !macroend
258  !define Abort `"" Abort ""`
259
260  !macro _Errors _a _b _t _f
261    IfErrors `${_t}` `${_f}`
262  !macroend
263  !define Errors `"" Errors ""`
264
265  !macro _FileExists _a _b _t _f
266    IfFileExists `${_b}` `${_t}` `${_f}`
267  !macroend
268  !define FileExists `"" FileExists`
269
270  !macro _RebootFlag _a _b _t _f
271    IfRebootFlag `${_t}` `${_f}`
272  !macroend
273  !define RebootFlag `"" RebootFlag ""`
274
275  !macro _Silent _a _b _t _f
276    IfSilent `${_t}` `${_f}`
277  !macroend
278  !define Silent `"" Silent ""`
279
280  ; "Any instruction" test
281  !macro _Cmd _a _b _t _f
282    !define _t=${_t}
283    !ifdef _t=                                            ; If no true label then make one
284      !define __t _LogicLib_Label_${LOGICLIB_COUNTER}
285      !insertmacro _IncreaseCounter
286    !else
287      !define __t ${_t}
288    !endif
289    ${_b} ${__t}
290    !define _f=${_f}
291    !ifndef _f=                                           ; If a false label then go there
292      Goto ${_f}
293    !endif
294    !undef _f=${_f}
295    !ifdef _t=                                            ; If we made our own true label then place it
296      ${__t}:
297    !endif
298    !undef __t
299    !undef _t=${_t}
300  !macroend
301  !define Cmd `"" Cmd`
302
303  ; Section flag test
304  !macro _SectionFlagIsSet _a _b _t _f
305    !insertmacro _LOGICLIB_TEMP
306    SectionGetFlags `${_b}` $_LOGICLIB_TEMP
307    IntOp $_LOGICLIB_TEMP $_LOGICLIB_TEMP & `${_a}`
308    !insertmacro _= $_LOGICLIB_TEMP `${_a}` `${_t}` `${_f}`
309  !macroend
310  !define SectionIsSelected `${SF_SELECTED} SectionFlagIsSet`
311  !define SectionIsSubSection `${SF_SUBSEC} SectionFlagIsSet`
312  !define SectionIsSubSectionEnd `${SF_SUBSECEND} SectionFlagIsSet`
313  !define SectionIsSectionGroup `${SF_SECGRP} SectionFlagIsSet`
314  !define SectionIsSectionGroupEnd `${SF_SECGRPEND} SectionFlagIsSet`
315  !define SectionIsBold `${SF_BOLD} SectionFlagIsSet`
316  !define SectionIsReadOnly `${SF_RO} SectionFlagIsSet`
317  !define SectionIsExpanded `${SF_EXPAND} SectionFlagIsSet`
318  !define SectionIsPartiallySelected `${SF_PSELECTED} SectionFlagIsSet`
319
320  !define IfCmd `!insertmacro _IfThen "" Cmd ${|}`
321
322  !macro _If _c _a _o _b
323    !verbose push
324    !verbose ${LOGICLIB_VERBOSITY}
325    !insertmacro _PushLogic
326    !define ${_Logic}If
327    !define ${_Logic}Else _LogicLib_Label_${LOGICLIB_COUNTER}                    ; Get a label for the Else
328    !insertmacro _IncreaseCounter
329    !define _c=${_c}
330    !ifdef _c=true                                        ; If is true
331      !insertmacro _${_o} `${_a}` `${_b}` "" ${${_Logic}Else}
332    !else                                                 ; If condition is false
333      !insertmacro _${_o} `${_a}` `${_b}` ${${_Logic}Else} ""
334    !endif
335    !undef _c=${_c}
336    !verbose pop
337  !macroend
338  !define If     `!insertmacro _If true`
339  !define Unless `!insertmacro _If false`
340  !define IfNot  `!insertmacro _If false`
341
342  !macro _And _c _a _o _b
343    !verbose push
344    !verbose ${LOGICLIB_VERBOSITY}
345    !ifndef _Logic | ${_Logic}If
346      !error "Cannot use And without a preceding If or IfNot/Unless"
347    !endif
348    !ifndef ${_Logic}Else
349      !error "Cannot use And following an Else"
350    !endif
351    !define _c=${_c}
352    !ifdef _c=true                                        ; If is true
353      !insertmacro _${_o} `${_a}` `${_b}` "" ${${_Logic}Else}
354    !else                                                 ; If condition is false
355      !insertmacro _${_o} `${_a}` `${_b}` ${${_Logic}Else} ""
356    !endif
357    !undef _c=${_c}
358    !verbose pop
359  !macroend
360  !define AndIf     `!insertmacro _And true`
361  !define AndUnless `!insertmacro _And false`
362  !define AndIfNot  `!insertmacro _And false`
363
364  !macro _Or _c _a _o _b
365    !verbose push
366    !verbose ${LOGICLIB_VERBOSITY}
367    !ifndef _Logic | ${_Logic}If
368      !error "Cannot use Or without a preceding If or IfNot/Unless"
369    !endif
370    !ifndef ${_Logic}Else
371      !error "Cannot use Or following an Else"
372    !endif
373    !define _label _LogicLib_Label_${LOGICLIB_COUNTER}                           ; Skip this test as we already
374    !insertmacro _IncreaseCounter
375    Goto ${_label}                                        ; have a successful result
376    ${${_Logic}Else}:                                     ; Place the Else label
377    !undef ${_Logic}Else                                  ; and remove it
378    !define ${_Logic}Else _LogicLib_Label_${LOGICLIB_COUNTER}                    ; Get a label for the next Else and perform the new If
379    !insertmacro _IncreaseCounter
380    !define _c=${_c}
381    !ifdef _c=true                                        ; If is true
382      !insertmacro _${_o} `${_a}` `${_b}` "" ${${_Logic}Else}
383    !else                                                 ; If condition is false
384      !insertmacro _${_o} `${_a}` `${_b}` ${${_Logic}Else} ""
385    !endif
386    !undef _c=${_c}
387    ${_label}:
388    !undef _label
389    !verbose pop
390  !macroend
391  !define OrIf     `!insertmacro _Or true`
392  !define OrUnless `!insertmacro _Or false`
393  !define OrIfNot  `!insertmacro _Or false`
394
395  !macro _Else
396    !verbose push
397    !verbose ${LOGICLIB_VERBOSITY}
398    !ifndef _Logic | ${_Logic}If
399      !error "Cannot use Else without a preceding If or IfNot/Unless"
400    !endif
401    !ifndef ${_Logic}Else
402      !error "Cannot use Else following an Else"
403    !endif
404    !ifndef ${_Logic}EndIf                                ; First Else for this If?
405      !define ${_Logic}EndIf _LogicLib_Label_${LOGICLIB_COUNTER}                 ; Get a label for the EndIf
406      !insertmacro _IncreaseCounter
407    !endif
408    Goto ${${_Logic}EndIf}                                ; Go to the EndIf
409    ${${_Logic}Else}:                                     ; Place the Else label
410    !undef ${_Logic}Else                                  ; and remove it
411    !verbose pop
412  !macroend
413  !define Else `!insertmacro _Else`
414
415  !macro _ElseIf _c _a _o _b
416    !verbose push
417    !verbose ${LOGICLIB_VERBOSITY}
418    ${Else}                                               ; Perform the Else
419    !define ${_Logic}Else _LogicLib_Label_${LOGICLIB_COUNTER}                    ; Get a label for the next Else and perform the new If
420    !insertmacro _IncreaseCounter
421    !define _c=${_c}
422    !ifdef _c=true                                        ; If is true
423      !insertmacro _${_o} `${_a}` `${_b}` "" ${${_Logic}Else}
424    !else                                                 ; If condition is false
425      !insertmacro _${_o} `${_a}` `${_b}` ${${_Logic}Else} ""
426    !endif
427    !undef _c=${_c}
428    !verbose pop
429  !macroend
430  !define ElseIf     `!insertmacro _ElseIf true`
431  !define ElseUnless `!insertmacro _ElseIf false`
432  !define ElseIfNot  `!insertmacro _ElseIf false`
433
434  !macro _EndIf _n
435    !verbose push
436    !verbose ${LOGICLIB_VERBOSITY}
437    !ifndef _Logic | ${_Logic}If
438      !error "Cannot use End${_n} without a preceding If or IfNot/Unless"
439    !endif
440    !ifdef ${_Logic}Else
441      ${${_Logic}Else}:                                   ; Place the Else label
442      !undef ${_Logic}Else                                ; and remove it
443    !endif
444    !ifdef ${_Logic}EndIf
445      ${${_Logic}EndIf}:                                  ; Place the EndIf
446      !undef ${_Logic}EndIf                               ; and remove it
447    !endif
448    !undef ${_Logic}If
449    !insertmacro _PopLogic
450    !verbose pop
451  !macroend
452  !define EndIf     `!insertmacro _EndIf If`
453  !define EndUnless `!insertmacro _EndIf Unless`
454
455  !macro _IfThen _a _o _b _t
456    !verbose push
457    !verbose ${LOGICLIB_VERBOSITY}
458    ${If} `${_a}` `${_o}` `${_b}`
459      ${_t}
460    ${EndIf}
461    !verbose pop
462  !macroend
463  !define IfThen `!insertmacro _IfThen`
464
465  !macro _IfNotThen _a _o _b _t
466    !verbose push
467    !verbose ${LOGICLIB_VERBOSITY}
468    ${IfNot} `${_a}` `${_o}` `${_b}`
469      ${_t}
470    ${EndIf}
471    !verbose pop
472  !macroend
473  !define IfNotThen `!insertmacro _IfNotThen`
474
475  !macro _ForEach _v _f _t _o _s
476    !verbose push
477    !verbose ${LOGICLIB_VERBOSITY}
478    StrCpy "${_v}" "${_f}"                                ; Assign the initial value
479    Goto +2                                               ; Skip the loop expression for the first iteration
480    !define _DoLoopExpression `IntOp "${_v}" "${_v}" "${_o}" "${_s}"` ; Define the loop expression
481    !define _o=${_o}
482    !ifdef _o=+                                           ; Check the loop expression operator
483      !define __o >                                       ; to determine the correct loop condition
484    !else ifdef _o=-
485      !define __o <
486    !else
487      !error "Unsupported ForEach step operator (must be + or -)"
488    !endif
489    !undef _o=${_o}
490    !insertmacro _Do For false `${_v}` `${__o}` `${_t}`   ; Let Do do the rest
491    !undef __o
492    !verbose pop
493  !macroend
494  !define ForEach `!insertmacro _ForEach`
495
496  !macro _For _v _f _t
497    !verbose push
498    !verbose ${LOGICLIB_VERBOSITY}
499    ${ForEach} `${_v}` `${_f}` `${_t}` + 1                ; Pass on to ForEach
500    !verbose pop
501  !macroend
502  !define For `!insertmacro _For`
503
504  !define ExitFor `!insertmacro _Goto ExitFor For`
505
506  !define Next      `!insertmacro _Loop For Next "" "" "" ""`
507
508  !define While     `!insertmacro _Do While true`
509
510  !define ExitWhile `!insertmacro _Goto ExitWhile While`
511
512  !define EndWhile  `!insertmacro _Loop While EndWhile "" "" "" ""`
513
514  !macro _Do _n _c _a _o _b
515    !verbose push
516    !verbose ${LOGICLIB_VERBOSITY}
517    !insertmacro _PushLogic
518    !define ${_Logic}${_n} _LogicLib_Label_${LOGICLIB_COUNTER}                   ; Get a label for the start of the loop
519    !insertmacro _IncreaseCounter
520    ${${_Logic}${_n}}:
521    !insertmacro _PushScope Exit${_n} _LogicLib_Label_${LOGICLIB_COUNTER}        ; Get a label for the end of the loop
522    !insertmacro _IncreaseCounter
523    !insertmacro _PushScope Break ${_Exit${_n}}           ; Break goes to the end of the loop
524    !ifdef _DoLoopExpression
525      ${_DoLoopExpression}                                ; Special extra parameter for inserting code
526      !undef _DoLoopExpression                            ; between the Continue label and the loop condition
527    !endif
528    !define _c=${_c}
529    !ifdef _c=                                            ; No starting condition
530      !insertmacro _PushScope Continue _LogicLib_Label_${LOGICLIB_COUNTER}       ; Get a label for Continue at the end of the loop
531      !insertmacro _IncreaseCounter
532    !else
533      !insertmacro _PushScope Continue ${${_Logic}${_n}}  ; Continue goes to the start of the loop
534      !ifdef _c=true                                      ; If is true
535        !insertmacro _${_o} `${_a}` `${_b}` "" ${_Exit${_n}}
536      !else                                               ; If condition is false
537        !insertmacro _${_o} `${_a}` `${_b}` ${_Exit${_n}} ""
538      !endif
539    !endif
540    !undef _c=${_c}
541    !define ${_Logic}Condition ${_c}                      ; Remember the condition used
542    !verbose pop
543  !macroend
544  !define Do      `!insertmacro _Do Do "" "" "" ""`
545  !define DoWhile `!insertmacro _Do Do true`
546  !define DoUntil `!insertmacro _Do Do false`
547
548  !macro _Goto _n _s
549    !verbose push
550    !verbose ${LOGICLIB_VERBOSITY}
551    !ifndef _${_n}
552      !error "Cannot use ${_n} without a preceding ${_s}"
553    !endif
554    Goto ${_${_n}}
555    !verbose pop
556  !macroend
557  !define ExitDo   `!insertmacro _Goto ExitDo Do`
558
559  !macro _Loop _n _e _c _a _o _b
560    !verbose push
561    !verbose ${LOGICLIB_VERBOSITY}
562    !ifndef _Logic | ${_Logic}${_n}
563      !error "Cannot use ${_e} without a preceding ${_n}"
564    !endif
565    !define _c=${${_Logic}Condition}
566    !ifdef _c=                                            ; If Do had no condition place the Continue label
567      ${_Continue}:
568    !endif
569    !undef _c=${${_Logic}Condition}
570    !define _c=${_c}
571    !ifdef _c=                                            ; No ending condition
572      Goto ${${_Logic}${_n}}
573    !else ifdef _c=true                                   ; If condition is true
574      !insertmacro _${_o} `${_a}` `${_b}` ${${_Logic}${_n}} ${_Exit${_n}}
575    !else                                                 ; If condition is false
576      !insertmacro _${_o} `${_a}` `${_b}` ${_Exit${_n}} ${${_Logic}${_n}}
577    !endif
578    !undef _c=${_c}
579    Goto ${_Continue}                                     ; Just to ensure it is referenced at least once
580	Goto ${_Exit${_n}}                                    ; Just to ensure it is referenced at least once
581    ${_Exit${_n}}:                                        ; Place the loop exit point
582    !undef ${_Logic}Condition
583    !insertmacro _PopScope Continue
584    !insertmacro _PopScope Break
585    !insertmacro _PopScope Exit${_n}
586    !undef ${_Logic}${_n}
587    !insertmacro _PopLogic
588    !verbose pop
589  !macroend
590  !define Loop      `!insertmacro _Loop Do Loop "" "" "" ""`
591  !define LoopWhile `!insertmacro _Loop Do LoopWhile true`
592  !define LoopUntil `!insertmacro _Loop Do LoopUntil false`
593
594  !define Continue `!insertmacro _Goto Continue "For or Do or While"`
595  !define Break    `!insertmacro _Goto Break "For or Do or While"`
596
597  !macro _Select _a
598    !verbose push
599    !verbose ${LOGICLIB_VERBOSITY}
600    !insertmacro _PushLogic
601    !define ${_Logic}Select `${_a}`                       ; Remember the left hand side of the comparison
602    !verbose pop
603  !macroend
604  !define Select `!insertmacro _Select`
605
606  !macro _Select_CaseElse
607    !verbose push
608    !verbose ${LOGICLIB_VERBOSITY}
609    !ifndef _Logic | ${_Logic}Select
610      !error "Cannot use Case without a preceding Select"
611    !endif
612    !ifdef ${_Logic}EndSelect                             ; This is set only after the first case
613      !ifndef ${_Logic}Else
614        !error "Cannot use Case following a CaseElse"
615      !endif
616      Goto ${${_Logic}EndSelect}                          ; Go to the EndSelect
617      ${${_Logic}Else}:                                   ; Place the Else label
618      !undef ${_Logic}Else                                ; and remove it
619    !else
620      !define ${_Logic}EndSelect _LogicLib_Label_${LOGICLIB_COUNTER}             ; Get a label for the EndSelect
621      !insertmacro _IncreaseCounter
622    !endif
623    !verbose pop
624  !macroend
625  !define CaseElse `!insertmacro _CaseElse`
626  !define Case_Else `!insertmacro _CaseElse`              ; Compatibility with 2.2 and earlier
627  !define Default `!insertmacro _CaseElse`                ; For the C-minded
628
629  !macro _Select_Case _a
630    !verbose push
631    !verbose ${LOGICLIB_VERBOSITY}
632    ${CaseElse}                                           ; Perform the CaseElse
633    !define ${_Logic}Else _LogicLib_Label_${LOGICLIB_COUNTER}                    ; Get a label for the next Else and perform the new Case
634    !insertmacro _IncreaseCounter
635    !insertmacro _== `${${_Logic}Select}` `${_a}` "" ${${_Logic}Else}
636    !verbose pop
637  !macroend
638  !define Case `!insertmacro _Case`
639
640  !macro _Case2 _a _b
641    !verbose push
642    !verbose ${LOGICLIB_VERBOSITY}
643    ${CaseElse}                                           ; Perform the CaseElse
644    !define ${_Logic}Else _LogicLib_Label_${LOGICLIB_COUNTER}                    ; Get a label for the next Else and perform the new Case
645    !insertmacro _IncreaseCounter
646    !insertmacro _== `${${_Logic}Select}` `${_a}` +2 ""
647    !insertmacro _== `${${_Logic}Select}` `${_b}` "" ${${_Logic}Else}
648    !verbose pop
649  !macroend
650  !define Case2 `!insertmacro _Case2`
651
652  !macro _Case3 _a _b _c
653    !verbose push
654    !verbose ${LOGICLIB_VERBOSITY}
655    ${CaseElse}                                           ; Perform the CaseElse
656    !define ${_Logic}Else _LogicLib_Label_${LOGICLIB_COUNTER}                    ; Get a label for the next Else and perform the new Case
657    !insertmacro _IncreaseCounter
658    !insertmacro _== `${${_Logic}Select}` `${_a}` +3 ""
659    !insertmacro _== `${${_Logic}Select}` `${_b}` +2 ""
660    !insertmacro _== `${${_Logic}Select}` `${_c}` "" ${${_Logic}Else}
661    !verbose pop
662  !macroend
663  !define Case3 `!insertmacro _Case3`
664
665  !macro _Case4 _a _b _c _d
666    !verbose push
667    !verbose ${LOGICLIB_VERBOSITY}
668    ${CaseElse}                                           ; Perform the CaseElse
669    !define ${_Logic}Else _LogicLib_Label_${LOGICLIB_COUNTER}                    ; Get a label for the next Else and perform the new Case
670    !insertmacro _IncreaseCounter
671    !insertmacro _== `${${_Logic}Select}` `${_a}` +4 ""
672    !insertmacro _== `${${_Logic}Select}` `${_b}` +3 ""
673    !insertmacro _== `${${_Logic}Select}` `${_c}` +2 ""
674    !insertmacro _== `${${_Logic}Select}` `${_d}` "" ${${_Logic}Else}
675    !verbose pop
676  !macroend
677  !define Case4 `!insertmacro _Case4`
678
679  !macro _Case5 _a _b _c _d _e
680    !verbose push
681    !verbose ${LOGICLIB_VERBOSITY}
682    ${CaseElse}                                           ; Perform the CaseElse
683    !define ${_Logic}Else _LogicLib_Label_${LOGICLIB_COUNTER}                    ; Get a label for the next Else and perform the new Case
684    !insertmacro _IncreaseCounter
685    !insertmacro _== `${${_Logic}Select}` `${_a}` +5 ""
686    !insertmacro _== `${${_Logic}Select}` `${_b}` +4 ""
687    !insertmacro _== `${${_Logic}Select}` `${_c}` +3 ""
688    !insertmacro _== `${${_Logic}Select}` `${_d}` +2 ""
689    !insertmacro _== `${${_Logic}Select}` `${_e}` "" ${${_Logic}Else}
690    !verbose pop
691  !macroend
692  !define Case5 `!insertmacro _Case5`
693
694  !macro _EndSelect
695    !verbose push
696    !verbose ${LOGICLIB_VERBOSITY}
697    !ifndef _Logic | ${_Logic}Select
698      !error "Cannot use EndSelect without a preceding Select"
699    !endif
700    !ifdef ${_Logic}Else
701      ${${_Logic}Else}:                                   ; Place the Else label
702      !undef ${_Logic}Else                                ; and remove it
703    !endif
704    !ifdef ${_Logic}EndSelect                             ; This won't be set if there weren't any cases
705      ${${_Logic}EndSelect}:                              ; Place the EndSelect
706      !undef ${_Logic}EndSelect                           ; and remove it
707    !endif
708    !undef ${_Logic}Select
709    !insertmacro _PopLogic
710    !verbose pop
711  !macroend
712  !define EndSelect `!insertmacro _EndSelect`
713
714  !macro _Switch _a
715    !verbose push
716    !verbose ${LOGICLIB_VERBOSITY}
717    !insertmacro _PushLogic
718    !insertmacro _PushScope Switch ${_Logic}              ; Keep a separate stack for switch data
719    !insertmacro _PushScope Break _LogicLib_Label_${LOGICLIB_COUNTER}            ; Get a lable for beyond the end of the switch
720    !insertmacro _IncreaseCounter
721    !define ${_Switch}Var `${_a}`                         ; Remember the left hand side of the comparison
722    !tempfile ${_Switch}Tmp                               ; Create a temporary file
723    !define ${_Logic}Switch _LogicLib_Label_${LOGICLIB_COUNTER}                  ; Get a label for the end of the switch
724    !insertmacro _IncreaseCounter
725    Goto ${${_Logic}Switch}                               ; and go there
726    !verbose pop
727  !macroend
728  !define Switch `!insertmacro _Switch`
729
730  !macro _Case _a
731    !verbose push
732    !verbose ${LOGICLIB_VERBOSITY}
733    !ifdef _Logic & ${_Logic}Select                       ; Check for an active Select
734      !insertmacro _Select_Case `${_a}`
735    !else ifndef _Switch                                  ; If not then check for an active Switch
736      !error "Cannot use Case without a preceding Select or Switch"
737    !else
738      !define _label _LogicLib_Label_${LOGICLIB_COUNTER}                         ; Get a label for this case,
739      !insertmacro _IncreaseCounter
740      ${_label}:                                          ; place it and add it's check to the temp file
741      !appendfile "${${_Switch}Tmp}" `!insertmacro _== $\`${${_Switch}Var}$\` $\`${_a}$\` ${_label} ""$\n`
742      !undef _label
743    !endif
744    !verbose pop
745  !macroend
746
747  !macro _CaseElse
748    !verbose push
749    !verbose ${LOGICLIB_VERBOSITY}
750    !ifdef _Logic & ${_Logic}Select                       ; Check for an active Select
751      !insertmacro _Select_CaseElse
752    !else ifndef _Switch                                  ; If not then check for an active Switch
753      !error "Cannot use Case without a preceding Select or Switch"
754    !else ifdef ${_Switch}Else                            ; Already had a default case?
755      !error "Cannot use CaseElse following a CaseElse"
756    !else
757      !define ${_Switch}Else _LogicLib_Label_${LOGICLIB_COUNTER}                 ; Get a label for the default case,
758      !insertmacro _IncreaseCounter
759      ${${_Switch}Else}:                                  ; and place it
760    !endif
761    !verbose pop
762  !macroend
763
764  !macro _EndSwitch
765    !verbose push
766    !verbose ${LOGICLIB_VERBOSITY}
767    !ifndef _Logic | ${_Logic}Switch
768      !error "Cannot use EndSwitch without a preceding Switch"
769    !endif
770    Goto ${_Break}                                        ; Skip the jump table
771    ${${_Logic}Switch}:                                   ; Place the end of the switch
772    !undef ${_Logic}Switch
773    !include "${${_Switch}Tmp}"                           ; Include the jump table
774    !delfile "${${_Switch}Tmp}"                           ; and clear it up
775    !ifdef ${_Switch}Else                                 ; Was there a default case?
776      Goto ${${_Switch}Else}                              ; then go there if all else fails
777      !undef ${_Switch}Else
778    !endif
779    !undef ${_Switch}Tmp
780    !undef ${_Switch}Var
781    ${_Break}:                                            ; Place the break label
782    !insertmacro _PopScope Break
783    !insertmacro _PopScope Switch
784    !insertmacro _PopLogic
785    !verbose pop
786  !macroend
787  !define EndSwitch `!insertmacro _EndSwitch`
788
789!endif ; LOGICLIB
790!verbose 3
791!define LOGICLIB_VERBOSITY ${_LOGICLIB_VERBOSITY}
792!undef _LOGICLIB_VERBOSITY
793!verbose pop
794