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