Modules.pm
上传用户:market2
上传日期:2018-11-18
资源大小:18786k
文件大小:6k
源码类别:

外挂编程

开发平台:

Windows_Unix

  1. #########################################################################
  2. #  OpenKore - Module Support Code
  3. #
  4. #  This software is open source, licensed under the GNU General Public
  5. #  License, version 2.  Basically, this means that you're allowed to
  6. #  modify and distribute this software. However, if you distribute
  7. #  modified versions, you MUST also distribute the source code.  See
  8. #  http://www.gnu.org/licenses/gpl.html for the full license.
  9. #########################################################################
  10. ##
  11. # MODULE DESCRIPTION: Module support system
  12. #
  13. # The OpenKore source code is split into various files: openkore.pl,
  14. # functions.pl, and some .pm files. These .pm files are modules: source
  15. # code that's part of OpenKore.  Modules implement various subsystems.
  16. #
  17. # One of the features of OpenKore is "dynamic code reloading". This
  18. # means that if you've modified source code, you can reload it at
  19. # runtime, without restarting Kore.
  20. #
  21. # This module, Modules.pm, is what makes it possible. It "glues" all the
  22. # other modules together. openkore.pl registers all the other modules,
  23. # and this modules will save that list in memory.
  24. #
  25. # Modules must put initialization code in a function called MODINIT().
  26. # This function is called at startup. Initialization code must not be
  27. # put elsewhere, because that code will be called again every time the
  28. # module is reloaded, and will overwrite existing values of variables.
  29. # MODINIT() is only called once at startup (during registration), and is
  30. # never called again.
  31. package Modules;
  32. use strict;
  33. use warnings;
  34. use Config;
  35. use FindBin;
  36. use File::Spec;
  37. our %modules;
  38. our @queue;
  39. sub import {
  40. my ($class, $arg) = @_;
  41. if ($arg && $arg eq 'register') {
  42. my ($package) = caller();
  43. register($package);
  44. }
  45. }
  46. sub getModuleFilename {
  47. my ($moduleName) = @_;
  48. my @nameParts = split /::/, $moduleName;
  49. my $baseName = File::Spec->join(@nameParts) . ".pm";
  50. foreach my $dir (@INC) {
  51. my $file = File::Spec->join($dir, $baseName);
  52. if (-f $file) {
  53. return $file;
  54. }
  55. }
  56. return undef;
  57. }
  58. sub T {
  59. if (defined &Translation::T && defined &Translation::_translate) {
  60. return &Translation::T;
  61. } else {
  62. return $_[0];
  63. }
  64. }
  65. sub TF {
  66. if (defined &Translation::TF && defined &Translation::T && defined &Translation::_translate) {
  67. return &Translation::TF;
  68. } else {
  69. my $format = shift;
  70. return sprintf($format, @_);
  71. }
  72. }
  73. sub error {
  74. if (defined &Log::error) {
  75. &Log::error;
  76. } else {
  77. print STDERR $_[0];
  78. }
  79. }
  80. sub message {
  81. if (defined &Log::message) {
  82. &Log::message;
  83. } else {
  84. print STDERR $_[0];
  85. }
  86. }
  87. ##
  88. # void Modules::register(names...)
  89. # names: the names of the modules to register.
  90. #
  91. # Register modules. Registered modules can be dynamically reloaded.
  92. # Upon registration, the module's MODINIT() function is called.
  93. #
  94. # Nothing will happen on attempts to re-register an already
  95. # registered module.
  96. #
  97. # Example:
  98. # Modules::register("Log", "Interface");  # Registers Log.pm and Interface.pm
  99. sub register {
  100. no strict 'refs';
  101. foreach my $module (@_) {
  102. if (!$modules{$module}) {
  103. my $func = UNIVERSAL::can($module, 'MODINIT');
  104. $func->() if ($func);
  105. $modules{$module} = 1;
  106. }
  107. }
  108. }
  109. ##
  110. # void Modules::addToReloadQueue(String namepart)
  111. # namepart: A part of the name of a registered Perl module.
  112. #
  113. # All registered Perl module whose name contain $namepart will be put into the reload queue.
  114. # Those modules are actually reloaded when Modules::reloadAllInQueue() is called.
  115. sub addToReloadQueue {
  116. my ($namepart) = @_;
  117. my $re = quotemeta $namepart;
  118. foreach my $module (keys %modules) {
  119. if ($module =~ /$re/i) {
  120. my $file = getModuleFilename($module);
  121. if ($file) {
  122. push @queue, $file;
  123. } else {
  124. error(TF("Unable to reload code: %s not foundn", $file));
  125. }
  126. }
  127. }
  128. }
  129. ##
  130. # boolean Modules::checkSyntax(String file)
  131. #
  132. # Check whether the file's syntax is correct.
  133. sub checkSyntax {
  134. my ($file) = @_;
  135. my (undef, undef, $baseName) = File::Spec->splitpath($file);
  136. system($Config{perlpath},
  137. '-I', "$FindBin::RealBin/src",
  138. '-I', "$FindBin::RealBin/src/deps",
  139. '-c', $file);
  140. if ($? == -1) {
  141. error(TF("Failed to execute %sn", $Config{perlpath}));
  142. return 0;
  143. } elsif ($? & 127) {
  144. error(TF("%s exited abnormallyn", $Config{perlpath}));
  145. return 0;
  146. } elsif (($? >> 8) == 0) {
  147. message(TF("%s passed syntax check.n", $baseName), "success");
  148. return 1;
  149. } else {
  150. error(TF("%s contains syntax errors.n", $baseName));
  151. return 0;
  152. }
  153. }
  154. ##
  155. # Modules::reloadFile(String filename)
  156. #
  157. # Executes "do $filename" if $filename exists and does not contain syntax
  158. # errors. This function is used internally by Modules::reloadAllInQueue(), do not
  159. # use this directly.
  160. sub reloadFile {
  161. my ($filename) = @_;
  162. my (undef, undef, $baseName) = File::Spec->splitpath($filename);
  163. if (!-f $Config{perlpath}) {
  164. error(TF("Cannot find Perl interpreter %sn", $Config{perlpath}));
  165. return;
  166. }
  167. message(TF("Checking %s for errors...n", $filename), "info");
  168. if (checkSyntax($filename)) {
  169. # Translation Comment: Reloading a Kore's module
  170. message(TF("Reloading %s...n", $baseName), "info");
  171. {
  172. package main;
  173. if (!do $filename || $@) {
  174. # Translation Comment: Unable to Reload a Kore's module
  175. error(TF("Unable to reload %sn", $baseName));
  176. error("$@n", "syntax", 1) if ($@);
  177. }
  178. }
  179. # Translation Comment: Kore's module reloaded successfully
  180. message(T("Reloaded.n"), "success");
  181. }
  182. }
  183. ##
  184. # void Modules::reloadAllInQueue()
  185. #
  186. # Reload all modules in the reload queue. This function is meant to be run in
  187. # Kore's main loop. Do not call this function directly in any other places.
  188. sub reloadAllInQueue {
  189. while (@queue > 0) {
  190. my $file = shift @queue;
  191. reloadFile($file);
  192. }
  193. }
  194. 1;