NSIS: masalah dengan $ 0- $ 9, $ R0- $ R9

Salam kepada semua yang membaca :)

Hub target tidak sesuai dengan konten artikel, tetapi apa yang harus dilakukan ... - tidak ada yang tematik untuk tujuan tersebut, tetapi yang paling cocok adalah "C", karena pembaca itu akan dengan mudah dapat memahami apa yang ditulis.

Tujuan artikel


Opsi untuk memecahkan masalah mengendalikan variabel global saat menulis installer / uninstaller menggunakan NSIS .

Pengantar kecil


Saat menulis kode nsis, programmer memiliki kesempatan untuk menggunakan variabel global yang ruang lingkupnya adalah keseluruhan proyek. Hanya ada 20 di antaranya: $ 0- $ 9 dan $ R0- $ R9.
Sangat nyaman untuk menggunakannya, karena ini menghilangkan kebutuhan untuk memperkenalkan variabel tambahan yang secara formal dimaksudkan untuk memecahkan masalah target. Saya katakan, secara formal, karena setiap variabel nsis memiliki cakupan global dan jika mereka berbeda dalam hal apa pun, maka hanya dengan const kualifikasi (berbicara dalam istilah C / C ++):

!define variable1 ''value 1''

Fitur:

  • variabel statis lingkup global;
  • Diinisialisasi setelah deklarasi;
  • Metode Kontak: $ {variable1}

Var variable2

Fitur:

  • Variabel dinamis lingkup global;
  • Itu dinyatakan di mana saja dengan kode, tetapi di atas panggilan pertama;
  • Ini diinisialisasi sebanyak yang diperlukan, tetapi hanya di dalam blok fungsi dan makro;
  • Metode Akses: $ variabel2

Dengan demikian, dengan mempertimbangkan fitur-fitur di atas, menjadi jelas bahwa pembuatan target variabel apa pun selain statis sulit untuk dibenarkan, karena variabel global sudah ada secara default, ada cukup banyak untuk memenuhi kebutuhan apa pun (dan jika tidak, Anda perlu mengajukan pertanyaan yang "sesuai" kepada programmer) dan yang lainnya kemungkinan besar hanya akan menyumbat kode.

Deskripsi masalah


Tetapi masalahnya adalah, kode ini selalu menghasilkan kesalahan:


Function F1
    StrCpy $0 "vladimir"
FunctionEnd

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

Dan Anda dapat menemukan banyak contoh tentang hal ini, dan pengrajin pemrograman pada nsis dapat memecahkan masalah ini sebaik mungkin:

  • Seseorang hanya dengan cermat mengamati semua variabel (orang-orang seperti itu perlu mendirikan sebuah monumen));
  • Seseorang, terutama pencipta berbagai plug-in, setiap kali ingin menggunakan variabel apa pun yang disajikan, membuatnya Push ke stack, dan setelah akhir penggunaan mereka mengembalikan nilai primer dengan menelepon Pop;
  • Dan seseorang menghasilkan variabel melalui Var, seperti dijelaskan di atas.

Bagaimanapun, mereka semua menghadapi masalah kurangnya mekanisme universal yang memecahkan masalah pemantauan keadaan variabel global.

Di sini saya membiarkan diri saya menawarkan (masalah) solusi universal.

Solusi untuk masalah tersebut


Sebagai permulaan, tautan ke NSISList adalah plugin yang memperkenalkan kemampuan untuk menggunakan struktur data tipe-daftar, yang harus diambil dengan cara yang sama seperti yang dirasakan oleh std :: list di C ++.

Langkah kedua adalah kode sumber dari mekanisme pemecahan masalah :


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

Dan langkah ketiga adalah deskripsi kecil tentang cara kerjanya:

Setiap fungsi dibuat dan dirancang sesuai dengan aturan yang dijelaskan oleh komentar kode utama sebelumnya akan benar-benar dilindungi dari sudut pandang bahaya menimpa variabel global $ 0 - $ 9, $ R0 - $ R9 di dalam dirinya sendiri, dan oleh karena itu - dari pelanggaran logika fungsi pemanggilan.

Ini berfungsi seperti ini:

  1. Fungsi F1 itu sendiri tidak disebut secara langsung,
    Call F1
    dan melalui pembungkus makro
    ${F1} [paramIn1 [paramIn2]...[paramInN]] [paramOut1 [paramOut2]...[paramOutM]]
  2. Bahkan sebelum fungsi dipanggil langsung, itu akan dipanggil
    ${Dump}
    sebagai hasilnya, nilai saat ini dari variabel $ 0- $ 9, $ R0- $ R9 disimpan dalam Dump. Di bawah tenda ia memiliki banyak daftar, masing-masing terikat pada variabel targetnya;
  3. Memuat pada stack semua variabel target untuk fungsi
    Push ${paramIn1} Push ${paramIn2} ... Push ${paramInN}
    (jika diperlukan);
  4. Fungsi akan dipanggil;
  5. Fungsi akan menjalankan logikanya dan keluar;
  6. Panggilan akan terjadi
    ${Undump}
    sebagai hasilnya, nilai-nilai variabel global yang disimpan pada panggilan terakhir $ {Dump} akan dikembalikan;
  7. Membongkar hasil fungsi dari tumpukan
    Pop ${paramOut1} Pop ${paramOut2} ... Pop ${paramOutM}
    (jika diperlukan);
  8. Pembungkus makro pada fungsi F1 akan menyelesaikan pekerjaannya.

Kesimpulan


Sebagai hasilnya, kami mendapatkan desain universal untuk penulisan kode nsis yang aman.

Anda bahkan dapat mengatakan bahwa itu tidak membawa minus, kecuali bahwa kode yang dikompilasi akan bekerja sekitar 30 ms. lebih lambat.

Semoga ini membuat hidup lebih mudah bagi seseorang :)

Terima kasih!

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


All Articles