NSIS: problème avec $ 0- $ 9, $ R0- $ R9

Salutations à tous ceux qui lisent :) Le

hub cible ne correspond pas au contenu de l'article, mais que faire ... - il n'y a pas de thèmes à cet effet, mais le plus approprié est "C", car les lecteurs pourront plus facilement percevoir ce qui est écrit.

Objet de l'article


Une option pour résoudre le problème du contrôle des variables globales lors de l'écriture du programme d'installation / désinstallation à l'aide de NSIS .

Petite introduction


Lors de l'écriture de code nsis, le programmeur a la possibilité d'utiliser des variables globales dont la portée est l'ensemble du projet. Il n'y en a que 20: 0 $ - 9 $ et R0 $ - R9 $.
Il est très pratique de les utiliser, car cela élimine le besoin d'introduire des variables supplémentaires formellement destinées à résoudre les problèmes cibles. Je dis, officiellement, parce que toutes les variables nsis ont une portée globale et si elles diffèrent en quoi que ce soit, alors uniquement avec le qualificatif const (en termes C / C ++):

!define variable1 ''value 1''

Fonctionnalités:

  • variable statique de portée globale;
  • Initialisé lors de la déclaration;
  • Méthode de contact: $ {variable1}

Var variable2

Fonctionnalités:

  • Variable dynamique de portée mondiale;
  • Il est déclaré n'importe où par code, mais au-dessus du premier appel;
  • Il est initialisé autant de fois que nécessaire, mais uniquement à l'intérieur des blocs fonctionnels et des macros;
  • Méthode d'accès: $ variable2

Ainsi, compte tenu des caractéristiques ci-dessus, il devient clair que la création ciblée de variables autres que statiques est difficile à justifier, car les variables globales existent déjà par défaut, il y en a suffisamment pour satisfaire tous les besoins (et sinon, vous devez poser les questions "appropriées" au programmeur) et toutes les autres ne feront probablement qu'encombrer le code.

description du problème


Mais le problème est que ce code génère toujours des erreurs:


Function F1
    StrCpy $0 "vladimir"
FunctionEnd

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

Et vous pouvez en trouver de nombreux exemples, et les artisans de la programmation sur nsis pourraient résoudre ce problème du mieux qu'ils le pourraient:

  • Quelqu'un a regardé attentivement toutes les variables (ces personnes doivent ériger un monument);
  • Quelqu'un, principalement les créateurs de divers plug-ins, voulant à chaque fois utiliser l'une des variables présentées, l'a fait pousser sur la pile, et après la fin de l'utilisation, ils ont renvoyé la valeur principale en appelant Pop;
  • Et quelqu'un a produit des variables via Var, comme décrit ci-dessus.

En tout cas, ils ont tous été confrontés au problème de l'absence d'un mécanisme universel qui résout le problème du suivi de l'état des variables globales.

Ici, je me permets de lui offrir (problèmes) une solution universelle.

Solution au problème


Pour commencer, le lien vers NSISList est un plugin qui introduit la possibilité d'utiliser une structure de données de type liste, qui doit être prise de la même manière que std :: list en C ++ est perçu.

La deuxième étape est le code source du mécanisme de résolution de problèmes :


!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."

Et la troisième étape est une petite description de son fonctionnement:

chaque fonction créée et conçue selon la règle décrite par le commentaire de code principal précédent sera absolument protégée du point de vue du danger de réécrire les variables globales $ 0- $ 9, $ R0- $ R9 à l'intérieur, et donc - de violation de la logique de la fonction appelante.

Cela fonctionne comme ceci:

  1. La fonction F1 elle-même n'est pas appelée directement,
    Call F1
    et à travers le macro wrapper
    ${F1} [paramIn1 [paramIn2]...[paramInN]] [paramOut1 [paramOut2]...[paramOutM]]
  2. Même avant d'appeler directement la fonction, elle sera appelée
    ${Dump}
    en conséquence, les valeurs actuelles des variables $ 0- $ 9, $ R0- $ R9 sont enregistrées dans Dump. Sous le capot, il a beaucoup de listes, chacune liée à sa variable cible;
  3. Chargement sur la pile de toutes les variables cibles de la fonction
    Push ${paramIn1} Push ${paramIn2} ... Push ${paramInN}
    (si nécessaire);
  4. La fonction sera appelée;
  5. La fonction exécutera sa logique et quittera;
  6. L'appel aura lieu
    ${Undump}
    en conséquence, les valeurs des variables globales stockées lors du dernier appel de $ {Dump} seront restaurées;
  7. Déchargement des résultats de la fonction de la pile
    Pop ${paramOut1} Pop ${paramOut2} ... Pop ${paramOutM}
    (si nécessaire);
  8. Le wrapper de macro sur la fonction F1 achèvera son travail.

Conclusion


En conséquence, nous avons obtenu une conception universelle pour une écriture sûre du code nsis.

Vous pouvez même dire qu'il n'apporte aucun inconvénient, sauf que le code compilé fonctionnera pendant environ 30 ms. Ralentissez.

J'espère que cela rend la vie plus facile à quelqu'un :)

Merci!

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


All Articles