Guest User

Linvstblast 0.1

a guest
Nov 14th, 2017
77
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/env tclsh
  2.  
  3. # execute in wish from path \
  4. #exec wish "$0" ${1+"$@"}
  5.  
  6. # ======================== LINVST BLASTER =========================
  7. # ==================== LINVST DLL BATCH LINKER ====================
  8. # by a linvst user
  9. #
  10. # READ THIS INTRODUCTION BEFORE ATTEMPTING TO USE IT
  11. #
  12. # IF YOU DON'T RUN LINUX, THIS IS NONE OF YOUR BUSINESS
  13. #
  14. # ==================== HOW TO USE IT ===============================
  15. # This is a Tcl script. You must have Tcl 8.4.6 or later to use it.
  16. # Older versions of Tcl may work, but I am not sure they will.
  17. #
  18. # First, 'cd' to the directory that contains the DLL files of the
  19. # Windows plugins and run the command. All the *.dll files in the  
  20. # working directory will be found and linked RECURSIVELY. Yes,
  21. # recursively, so make sure you're happy with the directory location
  22. # and structure before you run this script.
  23. #
  24. # Example:
  25. # $ cd /some/directory/with/a/truckload/of/plugins
  26. # $ linvstblast
  27. #
  28. # Tip: some file managers such as pcmanfm or spacefm let you press F4
  29. # to launch a terminal session in whatever directory it is displaying,
  30. # so you don't even have to 'cd' manually.
  31. #
  32. # After you run the command, a temporary file may be opened in a text
  33. # editor. I use Vim, but it is easy to edit the USER OPTIONS section
  34. # of this script and change it to another editor of your preference.
  35. # That will be your chance to edit the list of plugins that will be
  36. # linked to linvst. You can change that list or not. Your call.
  37. #
  38. # Unlike airwave (another Windows plugin DLL bridge for Linux), linvst
  39. # doesn't let you link to the plugins with some kind of alias or
  40. # alternative name. The name of the bridge .so file must be EXACTLY the
  41. # same as the name of the original .dll file. If you really must change
  42. # names, you will have to rename the .dll files first. Up to you. Most
  43. # plugins will work fine after being renamed. It's possible that one
  44. # or another will refuse to work, but that should be extremely rare.
  45. # Renaming is an awful lot of work though, hardly worth the trouble.
  46. #
  47. # Anyway,
  48. #
  49. # Your first providence before using this script is making sure you
  50. # have a copy of the linvst.so file stored in a predictable path. For
  51. # the sake of instruction, this documentation assumes you keep that
  52. # file as /usr/local/bin/linvst.so
  53. # Then you navigate to a target directory that contains many Windows
  54. # plugin .dll files and run the script.
  55. # linvstblast (this script) will then recursively traverse that target
  56. # directory and find all .dll files in it. Note that not all .dll files
  57. # are plugins, and the script will handle that problem to some extent.
  58. # More on that later.
  59. # For every .dll file that is found, the script will copy your linvst.so
  60. # file from /usr/local/bin/ over to the same directory as the .dll file
  61. # and rename that brand new copy of the linvst.so file so that it has
  62. # the exact same name as the .dll file except the extension will be .so
  63. # rather than .dll. That is just how linvst works.
  64. #
  65. # POSSIBLE CONFLICTS
  66. # When copying the linvst.so file over to each directory where a .dll
  67. # file is found, linvstblast performs two checks:
  68. #
  69. # 1) There is a USER OPTIONS section in the beginning of this script,
  70. # right after these instructions. You are the one supposed to maintain
  71. # it. Yes, you. Don't look around, I am talking to you. That section
  72. # contains a blacklist. It is a list of .dll files that might exist
  73. # inside any given directory inside the target directory and are
  74. # required by their parent plugins, but are not plugins themselves
  75. # therefore they must never be linked to linvst in any way.
  76. # Those little buggers are easy to spot once you try to add them to a
  77. # DAW thinking that you're adding plugins and they fail, and their names
  78. # also should give them away if you know anything about software.
  79. # It's too bad neither clue can be identified automatically by this
  80. # script. They're unpredictable. So our only recourse is to maintain a
  81. # blacklist. Once you find one of those pesky .dll files, add it to
  82. # the blacklist HERE, IN THIS SCRIPT, in the USER OPTIONS section of
  83. # this script so you never have to worry about that particular file
  84. # again, even if the same target directory is selected over and over
  85. # (because you have added new directories and plugins to it).
  86. # When copying the linvst.so file over to each directory where a .dll
  87. # file is found, linvstblast checks if the .dll file is included in the
  88. # blacklist, in which case the .dll file is excluded from the entire
  89. # operation.
  90. # Note: the blacklist check procedure is case insensitive, and the .dll
  91. # extensions are optional. You can write the extensions, but they are
  92. # always assumed anyway.
  93. #
  94. # 2) If linvstblast finds that a PLUGIN-NAME.so file already exists
  95. # whose name matches that of PLUGIN-NAME.dll, linvstblast checks
  96. # whether PLUGIN-NAME.so is a copy of the /usr/local/bin/linvst.so file.
  97. # If it is indeed a copy, then that plugin is already taken care of and
  98. # will be ignored. Such occurrence is never mentioned in any reports
  99. # or requests for confirmation. That would be very annoying.
  100. # If PLUGIN-NAME.so is not a copy of the /usr/local/bin/linvst.so file,
  101. # that occurrence will be added to a conflict report presented to you
  102. # before the end of the procedure and you will be offered the chance to
  103. # decide what to do about it.
  104. # The report will tell you exactly what to do. Just follow the
  105. # instructions on it, and everything will be fine.
  106. # The only caveat is that I only test these things on Vim. If you use
  107. # another text editor and it fails, you might want to try to inform me
  108. # of the problem. Who knows, I might even fix it. Or not.
  109. # Or you can just stick to Vim and stay out of trouble. It's what
  110. # grownups do.
  111. # If you use pico, Ok, I'll be merciful to you.
  112. # If you use emacs, bleh, you can fix the situation on your own. You
  113. # brought this fate upon yourself.
  114. #
  115. # OUTCOME
  116. # After running this highfallutin script, open your DAW and have it
  117. # refresh the list of plugins -- assuming it's already configured to
  118. # find plugins in the same target directory that you selected in the
  119. # beginning of the procedure. That's it. The DAW will detect the new
  120. # plugins in that directory and add them to its internal catalogue.
  121. #
  122. # OTHER FEATURES
  123. # This script can operate in three modes: normal, express and remove.
  124. # Modes are triggered by the presence or absence of arguments.
  125. # If neither the "express" or "remove" argument is used, "normal" mode
  126. # is assumed automatically. Only one mode can be used at a time.
  127. # If you try to use more than one argument, the script aborts all
  128. # operation and outputs a warning.
  129. #
  130. # NORMAL MODE
  131. # Already described in the previous sections of this documentation.
  132. #
  133. # EXPRESS MODE
  134. # In express mode, the script skips the confirmation stage entirely.
  135. # You will never be given the chance to edit anything in a text
  136. # editor. Items that match your blacklist and potential conflicts will
  137. # be properly skipped, and you will be given a brief report on standard
  138. # output.
  139. #
  140. # How to use:
  141. # $ cd /some/directory/with/a/truckload/of/plugins
  142. # $ linvstblast express
  143. #
  144. # REMOVE MODE
  145. # The remove mode will remove all copies of the linvst.so file in the
  146. # working directory, recursively. Don't worry, you will be presented
  147. # with a list in your file editor that you can edit before the
  148. # procedure is run, so you can be sure that you're only removing the
  149. # ones you want. There is no express mode for this operation.
  150. # Also note that .so files are only removed if they are an exact copy
  151. # of your matrix linvst.so file, so if you have any old copies of
  152. # linvst.so lingering around, they will be preserved and will probably
  153. # be detected as potential conflicts in subsequent runs.
  154. #
  155. # How to use:
  156. # $ cd /some/directory/with/a/truckload/of/plugins
  157. # $ linvstblast remove
  158. #
  159. # This script is placed in the public domain.
  160. # No guarantees are included whatsoever. If it blows up in your face,
  161. # eats your files or teaches profanity to your parrot, no one will be
  162. # responsible.
  163. # If you find a bug in my precious script, fix it for your own good.
  164. # That's open source for ya! Har. If you don't find any bugs, rejoice.
  165. # Ignorance is bliss.
  166. #
  167. # ==================================================================
  168.  
  169. # USER OPTIONS SECTION. YOU MUST CHECK AND POSSIBLY EDIT THESE.
  170.  
  171. # This is the location of the linvst.so file that will be copied to all
  172. # the directories where a plugin DLL is found. Make sure it is correct.
  173. set _linvst "/usr/local/bin/linvst.so"
  174.  
  175. # Specify the full path of the editor you want to use. I've only tested
  176. # it with vim. Other editors may fail. Sorry!
  177. set _editor "/usr/bin/vim"
  178.  
  179. # Sometimes a plugin's directory contains other DLL files that are not
  180. # plugins and should be ignored, but this script is not smart enough
  181. # to figure them out on its own. You may add such undesirable DLL files
  182. # to this list, so they will always be ignored.
  183. # NOTE: this check is case insensitive and the '.dll' extension part is
  184. # optional. If '.dll' is omitted, it's still assumed, though.
  185.  
  186. set _blackList  {
  187. d2d1.dll
  188. msvcr120.dll
  189. msvcr140
  190. msvcp120
  191. msvcp140.dll
  192. }
  193.  
  194. # ==================================================================
  195. # END OF THE USER OPTIONS SECTION.
  196. # ==================================================================
  197.  
  198. # ==================================================================
  199. # SCRIPT BEGINS HERE. DON'T CHANGE ANYTHING BELOW THIS POINT
  200. # UNLESS YOU KNOW WHAT YOU'RE DOING.
  201. # ==================================================================
  202.  
  203. # ==================================================================
  204. # CHECKS AND PREPARATIONS
  205. # ==================================================================
  206. if  {$argc > 1} {
  207.     puts "ERROR! Only one argument, please."
  208.     puts ""
  209.     exit
  210. }
  211. # --------------------------------
  212. if  {$argc == 1}    {
  213.     if  {[lindex $argv 0] == "remove"}  {
  214.         set _mode "remove"
  215.     } elseif    {[lindex $argv 0] == "express"} {
  216.         set _mode "express"
  217.     } {
  218.         puts "ERROR! Incorrect argument \"[lindex $argv 0]\""
  219.         puts ""
  220.         exit
  221.     }
  222. } else {set _mode "normal"}
  223.  
  224. # --------------------------------
  225. if  {![file isfile $_linvst]}   {
  226.     puts "ERROR! Choice of linvst.so does not exist."
  227.     puts "Please fix first line in the USER OPTIONS section of the script."
  228.     puts ""
  229.     exit
  230. }
  231.  
  232. # --------------------------------
  233. set _found_dlls_tmpfile [file normalize "/tmp/found_dlls.txt"]
  234. file delete $_found_dlls_tmpfile
  235.  
  236. # --------------------------------
  237. set ::hashMethod tcllib
  238. foreach i {sha512sum sha384sum sha256sum sha224sum sha1sum md5sum} {
  239.     if  {[catch {set ::hashMethod [exec which $i]} _catchError]}    {
  240.         continue
  241.     } else  {break}
  242. }
  243.  
  244. if  {$::hashMethod == "tcllib"} {
  245.     if  {[catch {package require sha256} _catchError]}      {
  246.         puts "ERROR! Impossible to proceed. Please install at least one of these packages: "
  247.         puts "sha512sum, sha384sum, sha256sum, sha224sum, sha1sum, md5sum, or tcllib."
  248.         puts "Note: tcllib is considerably slower than all the others."
  249.         puts ""
  250.         exit
  251.     }
  252. }
  253. proc p.compare {arg1 arg2}  {
  254.     if  {$::hashMethod == "tcllib"} {
  255.         package require sha256
  256.         set arg1 [::sha2::sha256 -hex -file $arg1]
  257.         set arg2 [::sha2::sha256 -hex -file $arg2]
  258.         if  {$arg1 == $arg2} {return 1} else {return 0}
  259.     } else {
  260.         set arg1 [lindex [exec $::hashMethod $arg1] 0]
  261.         set arg2 [lindex [exec $::hashMethod $arg2] 0]
  262.         if  {$arg1 == $arg2} {return 1} else {return 0}
  263.     }  
  264. }
  265.  
  266. # ==================================================================
  267. # END OF CHECKS AND PREPARATIONS
  268. # ==================================================================
  269.  
  270. # ==================================================================
  271. # REMOVE MODE
  272. # ==================================================================
  273. if  {$_mode == "remove"}    {
  274.     set _found_sos [exec find [pwd] -iname "*.so"]
  275.  
  276.     if  {[llength $_found_sos] == 0}    {
  277.         puts "-> Done! No .so files found whatsoever."
  278.         puts "Are you sure you're running this in the right directory?"
  279.         puts ""
  280.         exit
  281.     }
  282.     foreach i [split $_found_sos "\n"]  {
  283.         if  {[p.compare "$i" "$_linvst"] == 1}  {lappend _found_sos_confirmed $i}
  284.     }
  285.     if  {![info exists _found_sos_confirmed]}   {
  286.         puts "-> Done! Some .so files were found, but none of them is a copy of "
  287.         puts "$_linvst, so nothing has been done this time. Here they are:"
  288.         foreach i [split $_found_sos "\n"]  {puts $i}
  289.         puts ""
  290.         exit
  291.     }
  292.        
  293.     set _fp [open $_found_dlls_tmpfile w]
  294.         puts $_fp "# All these .so files are confirmed to be copies of $_linvst "
  295.         puts $_fp "# and will be removed. If you don't want any of them to be removed, delete "
  296.         puts $_fp "# its corresponding line in this document before saving and closing the document."
  297.         puts $_fp "# You can obviously delete all lines then save and close, which has the same effect "
  298.         puts $_fp "# as cancelling the whole operation altogether."
  299.         puts $_fp ""
  300.         foreach i [split $_found_sos "\n"]  {
  301.             if  {[p.compare $i $_linvst]}   {
  302.                 puts $_fp $i
  303.             }
  304.         }
  305.     close $_fp
  306.  
  307.     eval "exec $::_editor $::_found_dlls_tmpfile <@stdin >@stdout"
  308.  
  309.     set _count 0
  310.     set _fp [open $_found_dlls_tmpfile r]
  311.         while   {-1 != [gets $_fp _line]}  {
  312.             if  {[file isfile $_line]}  {
  313.                 file delete $_line
  314.                 incr _count
  315.             }
  316.         }
  317.     close $_fp
  318.     puts "-> Done! $_count files removed."
  319.     exit
  320. }
  321. # ==================================================================
  322. # END OF REMOVE MODE
  323. # ==================================================================
  324.  
  325. # ==================================================================
  326. # NORMAL AND EXPRESS MODE
  327. # ==================================================================
  328. set _found_dlls [exec find [pwd] -iname "*.dll"]
  329.  
  330. foreach i $_blackList   {
  331.     lappend _blackList_cleaned [file rootname $i]
  332. }
  333.  
  334. foreach i [split $_found_dlls "\n"] {
  335.     if  {[lsearch -nocase $_blackList_cleaned [file rootname [file tail $i]]] >= 0} {
  336.         lappend _blacklisted $i
  337.         continue
  338.     }
  339.  
  340.     set _dir [file dirname $i]
  341.     if  {[file isfile $_dir/[file rootname [file tail $i]].so]} {
  342.         if  {![p.compare $_dir/[file rootname [file tail $i]].so $_linvst]} {
  343.             lappend _conflicts $i
  344.         }
  345.         continue
  346.     }
  347.    
  348.     lappend _dll_final_list $i
  349. }
  350.  
  351. if  {![info exists _blacklisted] && ![info exists _conflicts] && ![info exists _dll_final_list]}    {
  352.     puts ""
  353.     puts "No .dll files without a proper .so counterpart found."
  354.     puts "No conflicts or blacklist matches either."
  355.     puts "Nothing to do now. Maybe next time."
  356.     puts ""
  357.     exit
  358. }
  359.  
  360. set _fp [open $_found_dlls_tmpfile w]
  361.     puts $_fp "# Once you save and close this document, the operation will be executed "
  362.     puts $_fp "# automatically."
  363.     puts $_fp "# If you want to cancel/abort the entire operation, just delete all lines "
  364.     puts $_fp "# in this document, save and close."
  365.     puts $_fp ""
  366.  
  367.     if  {[info exists _blacklisted]}    {
  368.         puts $_fp "# Here is the list of files that will NOT be linked to linvst "
  369.         puts $_fp "# because they match at least one of the items in your blacklist: "
  370.         puts $_fp ""
  371.         foreach i $_blacklisted {puts $_fp "#$i"}
  372.         puts $_fp ""
  373.         puts $_fp "# If you think that any of the files above has been blacklisted in error "
  374.         puts $_fp "# and should be linked to linvst, just delete the # symbol at the beginning of its line "
  375.         puts $_fp "# before you save the document and close the text editor."
  376.         puts $_fp ""
  377.         puts $_fp "# --------------------------------"
  378.         puts $_fp ""
  379.     }
  380.  
  381.     if  {[info exists _conflicts]}  {
  382.         puts $_fp "# This is the list of '.dll' files that already have their own '.so' counterpart, "
  383.         puts $_fp "# but the .so file is not a copy of your linvst file. If you think they should be overwritten "
  384.         puts $_fp "# with your linvst.so file, just remove the # symbol at the beginning of their respective lines. "
  385.         puts $_fp "# BE CAREFUL with that decision. You may overwrite a file that is provided by the plugin "
  386.         puts $_fp "# vendor/developer and is required for proper operation of the plugin."
  387.         puts $_fp ""
  388.         foreach i $_conflicts   {puts $_fp "#$i"}
  389.         puts $_fp ""
  390.         puts $_fp "# --------------------------------"
  391.     }
  392.  
  393.     if  {[info exists _dll_final_list]} {
  394.         puts $_fp "# This is the list of files that WILL be linked to linvst."
  395.         puts $_fp "# After inspecting the list, save the document and close the text editor."
  396.         puts $_fp "# If you want to exclude any of the files below, delete it from the list here "
  397.         puts $_fp "# before saving the document and closing the text editor."
  398.         puts $_fp "# If you don't want to have to exclude it manually again in the future, "
  399.         puts $_fp "# add it to the blacklist in the USER OPTIONS section of the script."
  400.         puts $_fp ""
  401.  
  402.         foreach i $_dll_final_list  {puts $_fp "$i"}
  403.     }
  404.  
  405. close $_fp
  406.  
  407. if  {$_mode != "express"}   {eval "exec $::_editor $::_found_dlls_tmpfile <@stdin >@stdout"}
  408.  
  409. set _count 0
  410. set _fp [open $_found_dlls_tmpfile r]
  411.     while   {-1 != [gets $_fp _line]}  {
  412.         if  {[regexp "^\s*#" $_line]}   {continue}
  413.         if  {[file isfile $_line]}  {
  414.             file copy -force $_linvst [file dirname $_line]/[file rootname [file tail $_line]].so
  415.             incr _count
  416.         }
  417.         if  {[info exists _blacklisted]}    {
  418.             set _lsearch    [lsearch -nocase $_blacklisted $_line]
  419.             if  {$_lsearch >= 0}    {
  420.                 lappend _overridden $_line
  421.                 set _blacklisted [lreplace $_blacklisted $_lsearch $_lsearch]
  422.             }
  423.             if  {[llength $_blacklisted] == 0}  {unset _blacklisted}
  424.         }
  425.         if  {[info exists _conflicts]}  {
  426.             set _lsearch    [lsearch -nocase $_conflicts $_line]
  427.             if  {$_lsearch >= 0}    {
  428.                 lappend _overridden $_line
  429.                 set _conflicts [lreplace $_conflicts $_lsearch $_lsearch]
  430.             }
  431.             if  {[llength $_conflicts] == 0}    {unset _conflicts}
  432.         }
  433.     }
  434. close $_fp
  435.  
  436. # ==================================================================
  437. # FINAL OUTPUT
  438. # ==================================================================
  439. puts ""
  440. if  {[info exists _dll_final_list]} {
  441.     puts "-> Done. $_count new .dll to .so copies were performed."
  442. }
  443. if  {[info exists _blacklisted]}    {
  444.     puts "-> Excluded by blacklisting:"
  445.     foreach i $_blacklisted {puts $i}
  446. }
  447. if  {[info exists _overridden]} {
  448.     puts "-> These files were blacklisted, but were copied because you chose to override the blacklist:"
  449.     foreach i $_overridden  {puts $i}
  450. }
  451. if  {[info exists _conflicts]}  {
  452.     puts "-> Excluded due to name conflicts:"
  453.     foreach i $_conflicts   {puts $i}
  454. }
  455. puts ""
  456. exit
RAW Paste Data