NSIS: Problem mit $ 0- $ 9, $ R0- $ R9

Grüße an alle, die lesen :) Der

Ziel-Hub entspricht nicht dem Inhalt des Artikels, aber was zu tun ist ... - Es gibt keine thematischen für diesen Zweck, aber der am besten geeignete ist "C", weil Leser werden am leichtesten erkennen können, was geschrieben steht.

Zweck des Artikels


Eine Option zur Lösung des Problems der Steuerung globaler Variablen beim Schreiben des Installations- / Deinstallationsprogramms mit NSIS .

Kleine Einführung


Beim Schreiben von nsis-Code hat der Programmierer die Möglichkeit, globale Variablen zu verwenden, deren Umfang das gesamte Projekt umfasst. Es gibt nur 20 davon: $ 0- $ 9 und $ R0- $ R9.
Es ist sehr bequem, sie zu verwenden, weil Dadurch entfällt die Notwendigkeit, zusätzliche Variablen einzuführen, die formal zur Lösung von Zielproblemen vorgesehen sind. Ich sage formell, weil Alle nsis-Variablen haben einen globalen Gültigkeitsbereich und wenn sie sich in irgendetwas unterscheiden, nur mit dem Qualifikationsmerkmal const (in C / C ++ - Begriffen):

!define variable1 ''value 1''

Eigenschaften:

  • statische Variable des globalen Bereichs;
  • Initialisiert bei Erklärung;
  • Kontaktmethode: $ {variable1}

Var variable2

Eigenschaften:

  • Dynamische Variable mit globalem Geltungsbereich;
  • Es wird überall durch Code deklariert, jedoch über dem ersten Aufruf.
  • Es wird so oft wie nötig initialisiert, jedoch nur innerhalb von Funktionsblöcken und Makros.
  • Zugriffsmethode: $ variable2

Angesichts der obigen Merkmale wird daher klar, dass die gezielte Erstellung anderer als statischer Variablen schwer zu rechtfertigen ist, weil Standardmäßig sind bereits globale Variablen vorhanden. Es gibt genügend Variablen, um alle Anforderungen zu erfüllen (und wenn nicht, müssen Sie dem Programmierer die "entsprechenden" Fragen stellen), und andere verstopfen höchstwahrscheinlich nur den Code.

Beschreibung des Problems


Das Problem ist jedoch, dass dieser Code immer Fehler generiert:


Function F1
    StrCpy $0 "vladimir"
FunctionEnd

Function F2
    StrCpy $0 "alexei"
    Call F1
    ${If} $0 == "alexei" ; //  $0  "vladimir"
        ; // -  ...
    ${EndIf}
FunctionEnd

Und Sie können sich viele Beispiele dafür einfallen lassen, und die Programmierer von nsis haben dieses Problem so gut wie möglich gelöst:

  • Jemand hat nur alle Variablen genau beobachtet (solche Leute müssen ein Denkmal errichten);
  • Jemand, hauptsächlich die Ersteller verschiedener Plug-Ins, die jedes Mal eine der dargestellten Variablen verwenden wollten, ließen es auf den Stapel schieben, und nach dem Ende der Verwendung gaben sie den primären Wert zurück, indem sie Pop aufriefen.
  • Und jemand hat Variablen durch Var erzeugt, wie oben beschrieben.

Auf jeden Fall standen sie alle vor dem Problem, dass es keinen universellen Mechanismus gibt, der das Problem der Überwachung des Zustands globaler Variablen löst.

Hier erlaube ich mir, ihr (Probleme) eine universelle Lösung anzubieten.

Lösung


Zunächst ist der Link zu NSISList ein Plugin, das die Möglichkeit einführt, eine Datenstruktur vom Listentyp zu verwenden, die ähnlich wie std :: list in C ++ verwendet werden sollte.

Der zweite Schritt ist der Quellcode des Problemlösungsmechanismus :


!verbose 3
!include NSISList.nsh	;      *

/*
  Dump, :

!define F1 "!insertmacro _F1"
!macro _F1 [paramIn1 paramIn2 ... paramInN] [paramOut1 paramOut1 ... paramOutM]
    ${Dump}
    [Push ${paramIn1}
	Push ${paramIn2}
	...
	Push ${paramInN}]
    !ifdef __UNINSTALL__
        Call un.F1
    !else
        Call F1
    !endif
    ${Undump}
    [Pop ${paramOut1}
	Pop ${paramOut2}
	...
	Pop ${paramOutM}]
!macroend

!macro Func_F1 un
    Function ${un}F1
        ;  ...
        ;         $0-$9, $R0-$R9.
        ;        .
    FunctionEnd
!macroend
!insertmacro Func_F1 ""
!insertmacro Func_F1 "un."

*/

/**   Dump */
!define InitDump "!insertmacro _InitDump"
!macro _InitDump
    !ifdef __UNINSTALL__
        Call un.InitDump
    !else
        Call InitDump
    !endif
!macroend

!macro Func_InitDump un
    Function ${un}InitDump
        #  $0-$9
        ${List.Create} d0
        ${List.Create} d1
        ${List.Create} d2
        ${List.Create} d3
        ${List.Create} d4
        ${List.Create} d5
        ${List.Create} d6
        ${List.Create} d7
        ${List.Create} d8
        ${List.Create} d9
        #  $R0-$R10
        ${List.Create} dR0
        ${List.Create} dR1
        ${List.Create} dR2
        ${List.Create} dR3
        ${List.Create} dR4
        ${List.Create} dR5
        ${List.Create} dR6
        ${List.Create} dR7
        ${List.Create} dR8
        ${List.Create} dR9
    FunctionEnd
!macroend
!insertmacro Func_InitDump ""
!insertmacro Func_InitDump "un."


/**     nsis-  Dump */
!define Dump "!insertmacro _Dump"
!macro _Dump
    !ifdef __UNINSTALL__
        Call un.Dump
    !else
        Call Dump
    !endif
!macroend

!macro Func_Dump un
    Function ${un}Dump
        # $0-$9
        ${List.Add} d0 $0
        ${List.Add} d1 $1
        ${List.Add} d2 $2
        ${List.Add} d3 $3
        ${List.Add} d4 $4
        ${List.Add} d5 $5
        ${List.Add} d6 $6
        ${List.Add} d7 $7
        ${List.Add} d8 $8
        ${List.Add} d9 $9
        # R0-R9
        ${List.Add} dR0 $R0
        ${List.Add} dR1 $R1
        ${List.Add} dR2 $R2
        ${List.Add} dR3 $R3
        ${List.Add} dR4 $R4
        ${List.Add} dR5 $R5
        ${List.Add} dR6 $R6
        ${List.Add} dR7 $R7
        ${List.Add} dR8 $R8
        ${List.Add} dR9 $R9
    FunctionEnd
!macroend
!insertmacro Func_Dump ""
!insertmacro Func_Dump "un."


/**     nsis-  Dump */
!define Undump "!insertmacro _Undump"
!macro _Undump
    !ifdef __UNINSTALL__
        Call un.Undump
    !else
        Call Undump
    !endif
!macroend

!macro Func_Undump un
    Function ${un}Undump
        # $0-$9
        ${List.Pop} $0 d0
        ${List.Pop} $1 d1
        ${List.Pop} $2 d2
        ${List.Pop} $3 d3
        ${List.Pop} $4 d4
        ${List.Pop} $5 d5
        ${List.Pop} $6 d6
        ${List.Pop} $7 d7
        ${List.Pop} $8 d8
        ${List.Pop} $9 d9
        # R0-R9
        ${List.Pop} $R0 dR0
        ${List.Pop} $R1 dR1
        ${List.Pop} $R2 dR2
        ${List.Pop} $R3 dR3
        ${List.Pop} $R4 dR4
        ${List.Pop} $R5 dR5
        ${List.Pop} $R6 dR6
        ${List.Pop} $R7 dR7
        ${List.Pop} $R8 dR8
        ${List.Pop} $R9 dR9
    FunctionEnd
!macroend
!insertmacro Func_Undump ""
!insertmacro Func_Undump "un."

Und der dritte Schritt ist eine kleine Beschreibung der Funktionsweise:

Jede Funktion, die gemäß der im vorherigen Hauptcodekommentar beschriebenen Regel erstellt und entworfen wurde, ist unter dem Gesichtspunkt der Gefahr des Überschreibens der globalen Variablen $ 0- $ 9, $ R0- $ R9 in sich selbst absolut geschützt - wegen Verletzung der Logik der aufrufenden Funktion.

Es funktioniert so:

  1. Die F1-Funktion selbst wird nicht direkt aufgerufen,
    Call F1
    und durch den Makro-Wrapper
    ${F1} [paramIn1 [paramIn2]...[paramInN]] [paramOut1 [paramOut2]...[paramOutM]]
  2. Noch bevor die Funktion direkt aufgerufen wird, wird sie aufgerufen
    ${Dump}
    Infolgedessen werden die aktuellen Werte der Variablen $ 0- $ 9, $ R0- $ R9 in Dump gespeichert. Unter der Haube hat er viele Listen, die jeweils an die Zielvariable gebunden sind.
  3. Laden aller Zielvariablen für die Funktion auf den Stapel
    Push ${paramIn1} Push ${paramIn2} ... Push ${paramInN}
    (wenn es benötigt wird);
  4. Die Funktion wird aufgerufen;
  5. Die Funktion führt ihre Logik aus und beendet sie.
  6. Anruf wird passieren
    ${Undump}
    Infolgedessen werden die Werte der globalen Variablen, die beim letzten Aufruf von $ {Dump} gespeichert wurden, wiederhergestellt.
  7. Das Entladen der Funktion ergibt sich aus dem Stapel
    Pop ${paramOut1} Pop ${paramOut2} ... Pop ${paramOutM}
    (wenn es benötigt wird);
  8. Der Makro-Wrapper der F1-Funktion beendet seine Arbeit.

Fazit


Als Ergebnis haben wir ein universelles Design für das sichere Schreiben von nsis-Code erhalten.

Sie können sogar sagen, dass es keine Minuspunkte bringt, außer dass der kompilierte Code etwa 30 ms lang funktioniert. Langsamer.

Hoffe das macht jemandem das Leben leichter :)

Danke!

Source: https://habr.com/ru/post/undefined/


All Articles