NSIS: problema con $ 0- $ 9, $ R0- $ R9

Saludos a todos los que leen :) El

centro de destino no corresponde al contenido del artículo, sino a qué hacer ... - no hay temas temáticos para el propósito, pero el más adecuado es "C", porque los lectores podrán percibir más fácilmente lo que está escrito.

Propósito del artículo.


Una opción para resolver el problema de controlar las variables globales al escribir el instalador / desinstalador usando NSIS .

Pequeña introducción


Al escribir código nsis, el programador tiene la oportunidad de usar variables globales cuyo alcance es el proyecto completo. Solo hay 20 de ellos: $ 0- $ 9 y $ R0- $ R9.
Es muy conveniente usarlos, porque Esto elimina la necesidad de introducir variables adicionales destinadas formalmente a resolver problemas objetivo. Digo formalmente porque cualquier variable nsis tiene un alcance global y si difieren en algo, solo con el calificador const (hablando en términos C / C ++):

!define variable1 ''value 1''

caracteristicas:

  • variable estática de alcance global;
  • Inicializado tras la declaración;
  • Método de contacto: $ {variable1}

Var variable2

caracteristicas:

  • Variable dinámica de alcance global;
  • Se declara en cualquier lugar por código, pero por encima de la primera llamada;
  • Se inicializa tantas veces como sea necesario, pero solo dentro de bloques de funciones y macros;
  • Método de acceso: $ variable2

Por lo tanto, teniendo en cuenta las características anteriores, queda claro que la creación específica de cualquier variable que no sea estática es difícil de justificar, porque las variables globales ya existen de forma predeterminada, hay suficientes para satisfacer cualquier necesidad (y si no, debe hacer las preguntas "apropiadas" al programador) y las otras probablemente solo obstruirán el código.

Descripción del problema


Pero el problema es que este código siempre genera errores:


Function F1
    StrCpy $0 "vladimir"
FunctionEnd

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

Y puede encontrar muchos ejemplos de esto, y los expertos en programación de nsis resolvieron este problema lo mejor que pudieron:

  • Alguien solo observó cuidadosamente todas las variables (esas personas necesitan erigir un monumento);
  • Alguien, principalmente los creadores de varios complementos, cada vez que quería usar cualquiera de las variables presentadas, lo empujó a la pila, y después del final del uso devolvieron el valor primario llamando a Pop;
  • Y alguien produjo variables a través de Var, como se describió anteriormente.

En cualquier caso, todos enfrentaron el problema de la falta de un mecanismo universal que resuelva el problema de monitorear el estado de las variables globales.

Aquí me permito ofrecerle (problemas) una solución universal.

Solución al problema


Para empezar, el enlace a NSISList es un complemento que introduce la capacidad de usar una estructura de datos de tipo lista, que debe tomarse de manera similar a std :: list en C ++.

El segundo paso es el código fuente del mecanismo de resolución de problemas :


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

Y el tercer paso es una pequeña descripción de cómo funciona:

cada función creada y diseñada de acuerdo con la regla descrita por el comentario del código principal anterior estará absolutamente protegida desde el punto de vista del peligro de reescribir las variables globales $ 0- $ 9, $ R0- $ R9 dentro de ella, y por lo tanto - por violación de la lógica de la función de llamada.

Funciona así:

  1. La función F1 en sí no se llama directamente,
    Call F1
    y a través de la macro envoltura
    ${F1} [paramIn1 [paramIn2]...[paramInN]] [paramOut1 [paramOut2]...[paramOutM]]
  2. Incluso antes de que la función se llame directamente, se llamará
    ${Dump}
    Como resultado, los valores actuales de las variables $ 0- $ 9, $ R0- $ R9 se guardan en Dump. Debajo del capó tiene muchas listas, cada una atada a su variable objetivo;
  3. Cargando en la pila todas las variables de destino para la función
    Push ${paramIn1} Push ${paramIn2} ... Push ${paramInN}
    (Si es necesario);
  4. Se llamará a la función;
  5. La función ejecutará su lógica y saldrá;
  6. Llamada sucederá
    ${Undump}
    como resultado, se restaurarán los valores de las variables globales almacenadas en la última llamada de $ {Dump};
  7. Descargar los resultados de la función de la pila
    Pop ${paramOut1} Pop ${paramOut2} ... Pop ${paramOutM}
    (Si es necesario);
  8. El contenedor macro en la función F1 completará su trabajo.

Conclusión


Como resultado, obtuvimos un diseño universal para la escritura segura de código nsis.

Incluso puede decir que no trae ningún inconveniente, excepto que el código compilado funcionará durante unos 30 ms. más lento.

Espero que esto haga la vida más fácil para alguien :) ¡

Gracias!

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


All Articles