modules.pm 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. #
  2. # Copyright 1999, 2000, 2001 Patrik Stridvall
  3. #
  4. # This library is free software; you can redistribute it and/or
  5. # modify it under the terms of the GNU Lesser General Public
  6. # License as published by the Free Software Foundation; either
  7. # version 2.1 of the License, or (at your option) any later version.
  8. #
  9. # This library is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. # Lesser General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU Lesser General Public
  15. # License along with this library; if not, write to the Free Software
  16. # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  17. #
  18. package modules;
  19. use strict;
  20. use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
  21. require Exporter;
  22. @ISA = qw(Exporter);
  23. @EXPORT = qw();
  24. @EXPORT_OK = qw($modules);
  25. use vars qw($modules);
  26. use config qw(
  27. file_type files_skip
  28. file_directory
  29. get_c_files get_spec_files
  30. $current_dir $wine_dir
  31. );
  32. use options qw($options);
  33. use output qw($output);
  34. sub import(@) {
  35. $Exporter::ExportLevel++;
  36. Exporter::import(@_);
  37. $Exporter::ExportLevel--;
  38. if (defined($modules)) {
  39. return;
  40. }
  41. $modules = 'modules'->new;
  42. }
  43. sub get_spec_file_type($) {
  44. my $file = shift;
  45. my $module;
  46. my $type;
  47. $module = $file;
  48. $module =~ s%^.*?([^/]+)\.spec$%$1%;
  49. open(IN, "< $file") || die "$file: $!\n";
  50. local $/ = "\n";
  51. my $header = 1;
  52. my $lookahead = 0;
  53. while($lookahead || defined($_ = <IN>)) {
  54. $lookahead = 0;
  55. s/^\s*(.*?)\s*$/$1/;
  56. s/^(.*?)\s*#.*$/$1/;
  57. /^$/ && next;
  58. if($header) {
  59. if(/^(?:\d+|@)/) { $header = 0; $lookahead = 1; }
  60. next;
  61. }
  62. if(/^(\d+|@)\s+pascal(?:16)?/) {
  63. $type = "win16";
  64. last;
  65. }
  66. }
  67. close(IN);
  68. if(!defined($type)) {
  69. $type = "win32";
  70. }
  71. return ($type, $module);
  72. }
  73. sub find_spec_files($) {
  74. my $self = shift;
  75. my $dir2spec_file = \%{$self->{DIR2SPEC_FILE}};
  76. my $spec_file2dir = \%{$self->{SPEC_FILE2DIR}};
  77. $output->progress("modules");
  78. my $spec_file_found = {};
  79. my $allowed_dir;
  80. my $spec_file;
  81. my @spec_files = <{dlls/*/*.spec}>;
  82. foreach $spec_file (@spec_files) {
  83. $spec_file =~ /(.*)\/.*\.spec/;
  84. $allowed_dir = $1;
  85. $$spec_file_found{$spec_file}++;
  86. $$spec_file2dir{$spec_file}{$allowed_dir}++;
  87. $$dir2spec_file{$allowed_dir}{$spec_file}++;
  88. # gdi32.dll and gdi.exe have some extra sources in subdirectories
  89. if ($spec_file =~ m!/gdi32\.spec$!)
  90. {
  91. $$spec_file2dir{$spec_file}{"$allowed_dir/enhmfdrv"}++;
  92. $$dir2spec_file{"$allowed_dir/enhmfdrv"}{$spec_file}++;
  93. }
  94. if ($spec_file =~ m!/gdi(?:32|\.exe)\.spec$!)
  95. {
  96. $$spec_file2dir{$spec_file}{"$allowed_dir/mfdrv"}++;
  97. $$dir2spec_file{"$allowed_dir/mfdrv"}{$spec_file}++;
  98. }
  99. }
  100. return $spec_file_found;
  101. }
  102. sub read_spec_files($$) {
  103. my $self = shift;
  104. my $spec_file_found = shift;
  105. my $dir2spec_file = \%{$self->{DIR2SPEC_FILE}};
  106. my $spec_files16 = \@{$self->{SPEC_FILES16}};
  107. my $spec_files32 = \@{$self->{SPEC_FILES32}};
  108. my $spec_file2module = \%{$self->{SPEC_FILE2MODULE}};
  109. my $module2spec_file = \%{$self->{MODULE2SPEC_FILE}};
  110. my @spec_files;
  111. if($wine_dir eq ".") {
  112. @spec_files = get_spec_files("winelib");
  113. } else {
  114. my %spec_files = ();
  115. foreach my $dir ($options->directories) {
  116. $dir = "$current_dir/$dir";
  117. $dir =~ s%/\.$%%;
  118. foreach my $spec_file (sort(keys(%{$$dir2spec_file{$dir}}))) {
  119. $spec_files{$spec_file}++;
  120. }
  121. }
  122. @spec_files = sort(keys(%spec_files));
  123. }
  124. @$spec_files16 = ();
  125. @$spec_files32 = ();
  126. foreach my $spec_file (@spec_files) {
  127. (my $type, my $module) = get_spec_file_type("$wine_dir/$spec_file");
  128. $$spec_file2module{$spec_file} = $module;
  129. $$module2spec_file{$module} = $spec_file;
  130. if($type eq "win16") {
  131. push @$spec_files16, $spec_file;
  132. } elsif($type eq "win32") {
  133. push @$spec_files32, $spec_file;
  134. } else {
  135. $output->write("$spec_file: unknown type '$type'\n");
  136. }
  137. }
  138. foreach my $spec_file (@spec_files) {
  139. if(!$$spec_file_found{$spec_file} && $spec_file !~ m%tests/[^/]+$%) {
  140. $output->write("modules: $spec_file: exists but is not specified\n");
  141. }
  142. }
  143. }
  144. sub new($) {
  145. my $proto = shift;
  146. my $class = ref($proto) || $proto;
  147. my $self = {};
  148. bless ($self, $class);
  149. my $spec_file_found = $self->find_spec_files();
  150. $self->read_spec_files($spec_file_found);
  151. return $self;
  152. }
  153. sub all_modules($) {
  154. my $self = shift;
  155. my $module2spec_file = \%{$self->{MODULE2SPEC_FILE}};
  156. return sort(keys(%$module2spec_file));
  157. }
  158. sub is_allowed_module($$) {
  159. my $self = shift;
  160. my $module2spec_file = \%{$self->{MODULE2SPEC_FILE}};
  161. my $module = shift;
  162. return defined($$module2spec_file{$module});
  163. }
  164. sub is_allowed_module_in_file($$$) {
  165. my $self = shift;
  166. my $dir2spec_file = \%{$self->{DIR2SPEC_FILE}};
  167. my $spec_file2module = \%{$self->{SPEC_FILE2MODULE}};
  168. my $module = shift;
  169. my $file = shift;
  170. $file =~ s/^\.\///;
  171. my $dir = $file;
  172. $dir =~ s/\/[^\/]*$//;
  173. if($dir =~ m%^include%) {
  174. return 1;
  175. }
  176. foreach my $spec_file (sort(keys(%{$$dir2spec_file{$dir}}))) {
  177. if($$spec_file2module{$spec_file} eq $module) {
  178. return 1;
  179. }
  180. }
  181. return 0;
  182. }
  183. sub allowed_modules_in_file($$) {
  184. my $self = shift;
  185. my $dir2spec_file = \%{$self->{DIR2SPEC_FILE}};
  186. my $spec_file2module = \%{$self->{SPEC_FILE2MODULE}};
  187. my $file = shift;
  188. $file =~ s/^\.\///;
  189. my $dir = $file;
  190. $dir =~ s/\/[^\/]*$//;
  191. my %allowed_modules = ();
  192. foreach my $spec_file (sort(keys(%{$$dir2spec_file{$dir}}))) {
  193. my $module = $$spec_file2module{$spec_file};
  194. $allowed_modules{$module}++;
  195. }
  196. my $module = join(" & ", sort(keys(%allowed_modules)));
  197. return $module;
  198. }
  199. sub allowed_dirs_for_module($$) {
  200. my $self = shift;
  201. my $module2spec_file = \%{$self->{MODULE2SPEC_FILE}};
  202. my $spec_file2dir = \%{$self->{SPEC_FILE2DIR}};
  203. my $module = shift;
  204. my $spec_file = $$module2spec_file{$module};
  205. return sort(keys(%{$$spec_file2dir{$spec_file}}));
  206. }
  207. sub allowed_spec_files16($) {
  208. my $self = shift;
  209. my $spec_files16 = \@{$self->{SPEC_FILES16}};
  210. return @$spec_files16;
  211. }
  212. sub allowed_spec_files32($) {
  213. my $self = shift;
  214. my $spec_files32 = \@{$self->{SPEC_FILES32}};
  215. return @$spec_files32;
  216. }
  217. sub found_module_in_dir($$$) {
  218. my $self = shift;
  219. my $module = shift;
  220. my $dir = shift;
  221. my $used_module_dirs = \%{$self->{USED_MODULE_DIRS}};
  222. $dir = "$current_dir/$dir";
  223. $dir =~ s%/\.$%%;
  224. $$used_module_dirs{$module}{$dir}++;
  225. }
  226. sub complete_modules($$) {
  227. my $self = shift;
  228. my $c_files = shift;
  229. my %dirs;
  230. foreach my $file (@$c_files) {
  231. my $dir = file_directory("$current_dir/$file");
  232. $dirs{$dir}++;
  233. }
  234. my @c_files = get_c_files("winelib");
  235. @c_files = files_skip(@c_files);
  236. foreach my $file (@c_files) {
  237. my $dir = file_directory($file);
  238. if(exists($dirs{$dir})) {
  239. $dirs{$dir}--;
  240. }
  241. }
  242. my @complete_modules = ();
  243. foreach my $module ($self->all_modules) {
  244. my $index = -1;
  245. my @dirs = $self->allowed_dirs_for_module($module);
  246. foreach my $dir (@dirs) {
  247. if(exists($dirs{$dir}) && $dirs{$dir} == 0) {
  248. $index++;
  249. }
  250. }
  251. if($index == $#dirs) {
  252. push @complete_modules, $module;
  253. }
  254. }
  255. return @complete_modules;
  256. }
  257. sub global_report($) {
  258. my $self = shift;
  259. my $module2spec_file = \%{$self->{MODULE2SPEC_FILE}};
  260. my $used_module_dirs = \%{$self->{USED_MODULE_DIRS}};
  261. my @messages;
  262. foreach my $dir ($options->directories) {
  263. $dir = "$current_dir/$dir";
  264. $dir =~ s%/\.$%%;
  265. foreach my $module ($self->all_modules) {
  266. if(!$$used_module_dirs{$module}{$dir}) {
  267. my $spec_file = $$module2spec_file{$module};
  268. push @messages, "modules: $spec_file: directory ($dir) is not used\n";
  269. }
  270. }
  271. }
  272. foreach my $message (sort(@messages)) {
  273. $output->write($message);
  274. }
  275. }
  276. 1;