1package My::Utility; 2use strict; 3use warnings; 4use base qw(Exporter); 5 6our @EXPORT_OK = qw(check_config_script check_prebuilt_binaries check_prereqs_libs check_prereqs_tools find_SDL_dir find_file check_header 7 sed_inplace get_dlext $inc_lib_candidates $source_packs check_perl_buildlibs); 8use Config; 9use ExtUtils::CBuilder; 10use File::Spec::Functions qw(splitdir catdir splitpath catpath rel2abs); 11use File::Find qw(find); 12use File::Which; 13use File::Copy qw(cp); 14use Cwd qw(realpath); 15 16our $cc = $Config{cc}; 17our $inc_lib_candidates = { 18 '/usr/local/include' => '/usr/local/lib', 19 '/usr/include' => '/usr/lib', 20 '/usr/X11R6/include' => '/usr/X11R6/lib', 21 '/usr/local/include/smpeg' => '/usr/local/lib', 22}; 23$inc_lib_candidates->{'/usr/pkg/include/smpeg'} = '/usr/local/lib' if -f '/usr/pkg/include/smpeg/smpeg.h'; 24$inc_lib_candidates->{'/usr/include/smpeg'} = '/usr/lib' if -f '/usr/include/smpeg/smpeg.h'; 25$inc_lib_candidates->{'/usr/X11R6/include'} = '/usr/X11R6/lib' if -f '/usr/X11R6/include/GL/gl.h'; 26$inc_lib_candidates->{'/usr/X11R7/include'} = '/usr/X11R7/lib' if -f '/usr/X11R7/include/GL/gl.h'; 27$inc_lib_candidates->{'/usr/X11R7/include'} = '/usr/X11R7/lib' if -f '/usr/X11R7/include/freetype2/freetype/freetype.h'; 28$inc_lib_candidates->{'/usr/X11R7/include'} = '/usr/X11R7/lib' if -f '/usr/X11R7/include/fontconfig/fontconfig.h'; 29$inc_lib_candidates->{'/usr/include/ogg'} = '/usr/lib/x86_64-linux-gnu' if -f '/usr/lib/x86_64-linux-gnu/libogg.so'; 30$inc_lib_candidates->{'/usr/include/vorbis'} = '/usr/lib/x86_64-linux-gnu' if -f '/usr/lib/x86_64-linux-gnu/libvorbis.so'; 31$inc_lib_candidates->{'/usr/include'} = '/usr/lib64' if -e '/usr/lib64' && $Config{'myarchname'} =~ /64/; 32$inc_lib_candidates->{$ENV{SDL_INC}} = $ENV{SDL_LIB} if exists $ENV{SDL_LIB} && exists $ENV{SDL_INC}; 33 34#### packs with prebuilt binaries 35# - all regexps has to match: arch_re ~ $Config{archname}, cc_re ~ $Config{cc}, os_re ~ $^O 36# - the order matters, we offer binaries to user in the same order (1st = preffered) 37my $prebuilt_binaries = [ 38 { 39 title => "Binaries Win/32bit SDL-1.2.14 (extended, 20100704) RECOMMENDED\n" . 40 "\t(gfx, image, mixer, net, smpeg, ttf, sound, svg, rtf, Pango)", 41 url => [ 42 'http://strawberryperl.com/package/kmx/sdl/Win32_SDL-1.2.14-extended-bin_20100704.zip', 43 'http://froggs.de/libsdl/Win32_SDL-1.2.14-extended-bin_20100704.zip', 44 ], 45 sha1sum => '98409ddeb649024a9cc1ab8ccb2ca7e8fe804fd8', 46 arch_re => qr/^MSWin32-x86-multi-thread(-64int)?$/, 47 os_re => qr/^MSWin32$/, 48 cc_re => qr/gcc/, 49 }, 50 { 51 title => "Binaries Win/32bit SDL-1.2.14 (extended, 20111205)\n" . 52 "\t(gfx, image, mixer, net, smpeg, ttf, sound, svg, rtf, Pango)", 53 url => [ 54 'http://strawberryperl.com/package/kmx/sdl/Win32_SDL-1.2.14-extended-bin_20111205.zip', 55 'http://froggs.de/libsdl/Win32_SDL-1.2.14-extended-bin_20111205.zip', 56 ], 57 sha1sum => '553b7e21bb650d047ec9f2a5f650c67d76430e61', 58 arch_re => qr/^MSWin32-x86-multi-thread(-64int)?$/, 59 os_re => qr/^MSWin32$/, 60 cc_re => qr/gcc/, 61 }, 62 { 63 title => "Binaries Win/64bit SDL-1.2.14 (extended, 20100824)\n" . 64 "\t(gfx, image, mixer, net, smpeg, ttf, sound, svg, rtf, Pango)\n" . 65 "\tBEWARE: binaries are using old ABI - will fail with the latest gcc\n" . 66 "\tBEWARE: this is intended just for old strawberryperl 5.12.x/64bit", 67 url => [ 68 'http://strawberryperl.com/package/kmx/sdl/Win64_SDL-1.2.14-extended-bin_20100824.zip', 69 'http://froggs.de/libsdl/Win64_SDL-1.2.14-extended-bin_20100824.zip', 70 ], 71 sha1sum => 'ccffb7218bcb17544ab00c8a1ae383422fe9586d', 72 arch_re => qr/^MSWin32-x64-multi-thread$/, 73 os_re => qr/^MSWin32$/, 74 cc_re => qr/gcc/, 75 gccversion_re => qr/^4\.4\.3$/, #specific to the old gcc compiler used in 64bit strawberryperl 5.12.x 76 }, 77 { 78 title => "Binaries Win/64bit SDL-1.2.14 (extended, 20111205) RECOMMENDED\n" . 79 "\t(gfx, image, mixer, net, smpeg, ttf, sound, svg, rtf, Pango)", 80 url => [ 81 'http://strawberryperl.com/package/kmx/sdl/Win64_SDL-1.2.14-extended-bin_20111205.zip', 82 'http://froggs.de/libsdl/Win64_SDL-1.2.14-extended-bin_20111205.zip', 83 ], 84 sha1sum => '35f3b496ca443a9d14eff77e9e26acfa813afafd', 85 arch_re => qr/^MSWin32-x64-multi-thread$/, 86 os_re => qr/^MSWin32$/, 87 cc_re => qr/gcc/, 88 gccversion_re => qr/^4\.(4\.[5-9]|[5-9]\.[0-9])$/, 89 }, 90 { 91 title => "Binaries Win/32bit SDL-1.2.15 (20120612)\n" . 92 "\t(gfx, image, mixer, smpeg, ttf)", 93 url => [ 94 'http://froggs.de/libsdl/Win32_SDL-1.2.15-20120612.zip', 95 ], 96 sha1sum => '22c531c1d0cc5a363c05045760870b2f45e9d0da', 97 arch_re => qr/^MSWin32/, 98 os_re => qr/^MSWin32$/, 99 cc_re => qr/cl/, 100 }, 101 ]; 102 103#### tarballs with source codes 104our $source_packs = [ 105 { 106 title => "Source code build\n ", 107 members => [ 108 { 109 pack => 'z', 110 version => '1.2.5', 111 dirname => 'zlib-1.2.5', 112 url => [ 113 'http://froggs.de/libz/zlib-1.2.5.tar.gz', 114 ], 115 sha1sum => '8e8b93fa5eb80df1afe5422309dca42964562d7e', 116 patches => [ 117 'zlib-1.2.5-bsd-ldconfig.patch', 118 ], 119 prereqs => { 120 libs => [ ] 121 } 122 }, 123 { 124 pack => 'jpeg', 125 version => '8b', 126 dirname => 'jpeg-8b', 127 url => [ 128 'http://www.ijg.org/files/jpegsrc.v8b.tar.gz', 129 'http://froggs.de/libjpeg/jpegsrc.v8b.tar.gz', 130 ], 131 sha1sum => '15dc1939ea1a5b9d09baea11cceb13ca59e4f9df', 132 patches => [ 133 'jpeg-8a_cygwin.patch', 134 ], 135 prereqs => { 136 libs => [ ] 137 } 138 }, 139 { 140 pack => 'tiff', 141 version => '3.9.1', 142 dirname => 'tiff-3.9.1', 143 url => [ 144 'http://froggs.de/libtiff/tiff-3.9.1.tar.gz', 145 'ftp://ftp.remotesensing.org/pub/libtiff/tiff-3.9.1.tar.gz', 146 ], 147 sha1sum => '675ad1977023a89201b80cd5cd4abadea7ba0897', 148 patches => [ ], 149 prereqs => { 150 libs => [ ] 151 } 152 }, 153 { 154 pack => 'png', 155 version => '1.4.1', 156 dirname => 'libpng-1.4.1', 157 url => [ 158 'http://froggs.de/libpng/libpng-1.4.1.tar.gz', 159 ], 160 sha1sum => '7a3488f5844068d67074f2507dd8a7ed9c69ff04', 161 prereqs => { 162 libs => [ 163 'z', 164 ] 165 } 166 }, 167 { 168 pack => 'freetype', 169 version => '2.3.12', 170 dirname => 'freetype-2.3.12', 171 url => [ 172 'http://mirror.lihnidos.org/GNU/savannah/freetype/freetype-2.3.12.tar.gz', 173 'http://froggs.de/libfreetype/freetype-2.3.12.tar.gz', 174 ], 175 sha1sum => '0082ec5e99fec5a1c6d89b321a7e2f201542e4b3', 176 prereqs => { 177 libs => [ ] 178 } 179 }, 180 { 181 pack => 'SDL', 182 version => '1.2.15', 183 dirname => 'SDL-1.2', 184 url => [ 185 'http://froggs.de/libsdl/SDL-1.2-2b923729fd01.tar.gz', 186 ], 187 sha1sum => 'ec9841377403e8d1bcfd76626434be64d11f59f0', 188 patches => [ 189 'test1.patch', 190 'SDL-1.2-openbsd-rldflags.patch', 191 'libsdl-1.2.15-const-xdata32.1.patch', 192 'libsdl-1.2.15-const-xdata32.2.patch', 193 'libsdl-1.2.15-const-xdata32.3.patch', 194 'libsdl-1.2.15-const-xdata32.4.patch', 195 'SDL-1.2.15-PIC-in-CFLAGS.patch', 196 'SDL-1.2.15-Makefile.in-OBJECTS.patch', 197 'SDL-1.2.15-mavericks-cgdirectpallete.patch', 198 ], 199 prereqs => { 200 libs => [ 201 'pthread', 202 ] 203 }, 204 }, 205 { 206 pack => 'SDL_image', 207 version => '1.2.11', 208 dirname => 'SDL_image-1.2.11', 209 url => [ 210 'http://www.libsdl.org/projects/SDL_image/release/SDL_image-1.2.11.tar.gz', 211 'http://froggs.de/libsdl/SDL_image-1.2.11.tar.gz', 212 ], 213 sha1sum => 'dd384ff87848595fcc0691833431ec5029f973c7', 214 patches => [ 215 'SDL_image-1.2.11-CGFloat.patch', 216 'SDL_image-1.2.11-libpng-flags.patch', 217 ], 218 prereqs => { 219 libs => [ 220 'jpeg', 'tiff', 'png', 221 ] 222 } 223 }, 224 { 225 pack => 'ogg', 226 version => '1.3.0', 227 dirname => 'libogg-1.3.0', 228 url => [ 229 'http://downloads.xiph.org/releases/ogg/libogg-1.3.0.tar.gz', 230 'http://froggs.de/libsdl/libogg-1.3.0.tar.gz', 231 ], 232 sha1sum => 'a900af21b6d7db1c7aa74eb0c39589ed9db991b8', 233 patches => [ ], 234 }, 235 { 236 pack => 'vorbis', 237 version => '1.3.3', 238 dirname => 'libvorbis-1.3.3', 239 url => [ 240 'http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.3.tar.gz', 241 'http://froggs.de/libsdl/libvorbis-1.3.3.tar.gz', 242 ], 243 sha1sum => '8dae60349292ed76db0e490dc5ee51088a84518b', 244 patches => [ 245 'libvorbis-1.3.3-configure.patch', 246 ], 247 prereqs => { 248 libs => [ ] 249 } 250 }, 251 { 252 pack => 'SDL_mixer', 253 version => '1.2.12', 254 dirname => 'SDL_mixer-1.2.12', 255 url => [ 256 'http://www.libsdl.org/projects/SDL_mixer/release/SDL_mixer-1.2.12.tar.gz', 257 'http://froggs.de/libsdl/SDL_mixer-1.2.12.tar.gz', 258 ], 259 sha1sum => 'a20fa96470ad9e1052f1957b77ffa68fb090b384', 260 patches => [ 261 'SDL_mixer-1.2.12-native-midi-win32.patch', 262 ], 263 prereqs => { 264 libs => [ 265 'ogg', 'vorbis', 266 ] 267 }, 268 }, 269 { 270 pack => 'SDL_ttf', 271 version => '2.0.11', 272 dirname => 'SDL_ttf-2.0.11', 273 url => [ 274 'http://www.libsdl.org/projects/SDL_ttf/release/SDL_ttf-2.0.11.tar.gz', 275 'http://froggs.de/libsdl/SDL_ttf-2.0.11.tar.gz', 276 ], 277 sha1sum => '0ccf7c70e26b7801d83f4847766e09f09db15cc6', 278 patches => [ ], 279 prereqs => { 280 libs => [ 281 'freetype', # SDL_ttf 282 ] 283 }, 284 }, 285 { 286 pack => 'SDL_gfx', 287 version => '2.0.25', 288 dirname => 'SDL_gfx-2.0.25', 289 url => [ 290 'http://froggs.de/libsdl/SDL_gfx-2.0.25.tar.gz', 291 'http://www.ferzkopp.net/Software/SDL_gfx-2.0/SDL_gfx-2.0.25.tar.gz', 292 ], 293 sha1sum => '20a89d0b71b7b790b830c70f17ed2c44100bc0f4', 294 patches => [ ], 295 prereqs => { 296 libs => [ ] 297 } 298 }, 299 { 300 pack => 'SDL_Pango', 301 version => '1.2', 302 dirname => 'SDL_Pango-0.1.2', 303 url => [ 304 'http://downloads.sourceforge.net/sdlpango/SDL_Pango-0.1.2.tar.gz', 305 'http://froggs.de/libsdl/SDL_Pango-0.1.2.tar.gz', 306 ], 307 sha1sum => 'c30f2941d476d9362850a150d29cb4a93730af68', 308 patches => [ 309 'SDL_Pango-0.1.2-API-adds.1.patch', 310 'SDL_Pango-0.1.2-API-adds.2.patch', 311 'SDL_Pango-0.1.2-config-tools.1.patch', 312 'SDL_Pango-0.1.2-config-tools.2.patch', 313 'SDL_Pango-0.1.2-config-tools.3.patch', 314 'SDL_Pango-0.1.2-include-ft2build.h.patch', 315 ], 316 prereqs => { 317 libs => [ 318 'pangoft2', 'pango', 'gobject', 'gmodule', 'glib', 'fontconfig', 'freetype', 'expat', # SDL_Pango 319 ] 320 } 321 }, 322 ], 323 }, 324]; 325 326sub check_config_script { 327 my $script = shift || 'sdl-config'; 328 print "checking for config script... "; 329 my $devnull = File::Spec->devnull(); 330 my $version = `$script --version 2>$devnull`; 331 if($? >> 8) { 332 print "no\n"; 333 return; 334 } 335 my $prefix = `$script --prefix 2>$devnull`; 336 if($? >> 8) { 337 print "no\n"; 338 return; 339 } 340 $version =~ s/[\r\n]+$//; 341 $prefix =~ s/[\r\n]+$//; 342 print "yes, $script\n"; 343 #returning HASHREF 344 return { 345 title => "Already installed SDL ver=$version path=$prefix", 346 buildtype => 'use_config_script', 347 script => $script, 348 prefix => $prefix, 349 }; 350} 351 352sub check_prebuilt_binaries 353{ 354 print "checking for prebuilt binaries... "; 355# print "(os=$^O cc=$cc archname=$Config{archname})\n"; 356 my @good = (); 357 foreach my $b (@{$prebuilt_binaries}) { 358 if ( ($^O =~ $b->{os_re}) && 359 ($Config{archname} =~ $b->{arch_re}) && 360 ($cc =~ $b->{cc_re}) && 361 (!defined $b->{gccversion_re} || $Config{gccversion} =~ $b->{gccversion_re}) 362 ) { 363 $b->{buildtype} = 'use_prebuilt_binaries'; 364 push @good, $b; 365 } 366 } 367 scalar(@good) 368 ? print "yes, " . scalar(@good) . " option(s)\n" 369 : print "no\n"; 370 #returning ARRAY of HASHREFs (sometimes more than one value) 371 return \@good; 372} 373 374sub check_prereqs_libs { 375 my @libs = @_; 376 my $ret = 1; 377 378 foreach my $lib (@libs) { 379 print "checking for $lib... "; 380 my $found_dll = ''; 381 my $found_lib = ''; 382 my $found_inc = ''; 383 my $header_map = { 384 'z' => 'zlib', 385 'jpeg' => 'jpeglib', 386 'vorbis' => 'vorbisenc', 387 'SDL_gfx' => 'SDL_gfxPrimitives', 388 'SDL' => 'SDL_version', 389 }; 390 my $header = (defined $header_map->{$lib}) ? $header_map->{$lib} : $lib; 391 392 my $dlext = get_dlext(); 393 foreach (keys %$inc_lib_candidates) { 394 my $ld = $inc_lib_candidates->{$_}; 395 next unless -d $_ && -d $ld; 396 ($found_dll) = find_file($ld, qr/[\/\\]lib\Q$lib\E[\-\d\.]*\.($dlext[\d\.]*|so|dll)$/); 397 $found_dll = $1 if $found_dll && $found_dll =~/^(.+($dlext|so|dll))/ && -e $1; 398 ($found_lib) = find_file($ld, qr/[\/\\]lib\Q$lib\E[\-\d\.]*\.($dlext[\d\.]*|a|dll.a)$/); 399 ($found_inc) = find_file($_, qr/[\/\\]\Q$header\E[\-\d\.]*\.h$/); 400 last if $found_lib && $found_inc; 401 } 402 403 if($found_lib && $found_inc) { 404 print "yes\n"; 405 $ret &= 1; 406 } 407 else { 408 print "no\n"; 409 $ret = 0; 410 } 411 412 if( scalar(@libs) == 1 ) { 413 return $ret 414 ? [(get_header_version($found_inc) || 'found'), $found_dll] 415 : [0, undef]; 416 } 417 } 418 419 return $ret; 420} 421 422sub check_perl_buildlibs { 423 my @libs = @_; 424 my $ret = 1; 425 my $dlext = get_dlext(); 426 my $devnull = File::Spec->devnull(); 427 for my $lib (@libs) { 428 print "checking if perl is linked against $lib... "; 429 if($Config{libs} =~ /\Q-l$lib\E\b/ 430 || $Config{perllibs} =~ /\Q-l$lib\E\b/ 431 || `ldd $^X 2>$devnull` =~ /[\/\\]lib\Q$lib\E[\-\d\.]*\.($dlext[\d\.]*|so|dll)$/) { 432 print "yes\n"; 433 $ret &= 1; 434 } 435 else { 436 print "no\n"; 437 $ret = 0; 438 } 439 } 440 return $ret; 441} 442 443sub check_prereqs { 444 my $bp = shift; 445 my $ret = 1; 446 $ret &= check_prereqs_libs(@{$bp->{prereqs}->{libs}}) if defined $bp->{prereqs}->{libs}; 447 448 return $ret; 449} 450 451sub check_prereqs_tools { 452 my @tools = @_; 453 my $ret = 1; 454 455 foreach my $tool (@tools) { 456 457 if((File::Which::which($tool) && -x File::Which::which($tool)) 458 || ('pkg-config' eq $tool && defined $ENV{PKG_CONFIG} && $ENV{PKG_CONFIG} 459 && File::Which::which($ENV{PKG_CONFIG}) 460 && -x File::Which::which($ENV{PKG_CONFIG}))) { 461 $ret &= 1; 462 } 463 else { 464 $ret = 0; 465 } 466 } 467 468 return $ret; 469} 470 471sub find_file { 472 my ($dir, $re) = @_; 473 my @files; 474 $re ||= qr/.*/; 475 { 476 #hide warning "Can't opendir(...): Permission denied - fix for http://rt.cpan.org/Public/Bug/Display.html?id=57232 477 no warnings; 478 find({ wanted => sub { push @files, rel2abs($_) if /$re/ }, follow => 1, no_chdir => 1 , follow_skip => 2}, $dir); 479 }; 480 return @files; 481} 482 483sub find_SDL_dir { 484 my $root = shift; 485 my ($version, $prefix, $incdir, $libdir); 486 return unless $root; 487 488 # try to find SDL_version.h 489 my ($found) = find_file($root, qr/SDL_version\.h$/i ); # take just the first one 490 return unless $found; 491 492 # get version info 493 open(DAT, $found) || return; 494 my @raw=<DAT>; 495 close(DAT); 496 my ($v_maj) = grep(/^#define[ \t]+SDL_MAJOR_VERSION[ \t]+[0-9]+/, @raw); 497 $v_maj =~ s/^#define[ \t]+SDL_MAJOR_VERSION[ \t]+([0-9]+)[.\r\n]*$/$1/; 498 my ($v_min) = grep(/^#define[ \t]+SDL_MINOR_VERSION[ \t]+[0-9]+/, @raw); 499 $v_min =~ s/^#define[ \t]+SDL_MINOR_VERSION[ \t]+([0-9]+)[.\r\n]*$/$1/; 500 my ($v_pat) = grep(/^#define[ \t]+SDL_PATCHLEVEL[ \t]+[0-9]+/, @raw); 501 $v_pat =~ s/^#define[ \t]+SDL_PATCHLEVEL[ \t]+([0-9]+)[.\r\n]*$/$1/; 502 return if (($v_maj eq '')||($v_min eq '')||($v_pat eq '')); 503 $version = "$v_maj.$v_min.$v_pat"; 504 505 # get prefix dir 506 my ($v, $d, $f) = splitpath($found); 507 my @pp = reverse splitdir($d); 508 shift(@pp) if(defined($pp[0]) && $pp[0] eq ''); 509 shift(@pp) if(defined($pp[0]) && $pp[0] eq 'SDL'); 510 if(defined($pp[0]) && $pp[0] eq 'include') { 511 shift(@pp); 512 @pp = reverse @pp; 513 return ( 514 $version, 515 catpath($v, catdir(@pp), ''), 516 catpath($v, catdir(@pp, 'include'), ''), 517 catpath($v, catdir(@pp, 'lib'), ''), 518 ); 519 } 520} 521 522sub check_header { 523 my ($cflags, @header) = @_; 524 print STDERR "Testing header(s): " . join(', ', @header) . "\n"; 525 my $cb = ExtUtils::CBuilder->new(quiet => 1); 526 my ($fs, $src) = File::Temp::tempfile('aaXXXX', SUFFIX => '.c', UNLINK => 1); 527 my $inc = ''; 528 $inc .= "#include <$_>\n" for @header; 529 syswrite($fs, <<MARKER); # write test source code 530#if defined(_WIN32) && !defined(__CYGWIN__) 531#include <stdio.h> 532/* GL/gl.h on Win32 requires windows.h being included before */ 533#include <windows.h> 534#endif 535$inc 536int demofunc(void) { return 0; } 537 538MARKER 539 close($fs); 540 my $obj = eval { $cb->compile( source => $src, extra_compiler_flags => $cflags); }; 541 if($obj) { 542 unlink $obj; 543 return 1; 544 } 545 else { 546 print STDERR "###TEST FAILED### for: " . join(', ', @header) . "\n"; 547 return 0; 548 } 549} 550 551sub sed_inplace { 552 # we expect to be called like this: 553 # sed_inplace("filename.txt", 's/0x([0-9]*)/n=$1/g'); 554 my ($file, $re) = @_; 555 if (-e $file) { 556 cp($file, "$file.bak") or die "###ERROR### cp: $!"; 557 open INPF, "<", "$file.bak" or die "###ERROR### open<: $!"; 558 open OUTF, ">", $file or die "###ERROR### open>: $!"; 559 binmode OUTF; # we do not want Windows newlines 560 while (<INPF>) { 561 eval( "$re" ); 562 print OUTF $_; 563 } 564 close INPF; 565 close OUTF; 566 } 567} 568 569sub get_dlext { 570 if($^O =~ /darwin/) { # there can be .dylib's on a mac even if $Config{dlext} is 'bundle' 571 return 'so|dylib|bundle'; 572 } 573 elsif( $^O =~ /cygwin/) { 574 return 'la'; 575 } 576 else { 577 return $Config{so}; 578 } 579} 580 581sub get_header_version { 582 my $file = shift; 583 # get version info 584 open(DAT, $file) || return; 585 my @raw = <DAT>; 586 close(DAT); 587 588 # generic magic how to get version major/minor/patchlevel 589 my ($v_maj) = grep(/^#define[ \t]+[A-Z_]+?MAJOR[A-Z_]*[ \t]+[0-9]+/, @raw); 590 $v_maj = '' unless defined $v_maj; 591 $v_maj =~ s/^#define[ \t]+[A-Z_]+[ \t]+([0-9]+)[.\r\n]*$/$1/; 592 my ($v_min) = grep(/^#define[ \t]+[A-Z_]+MINOR[A-Z_]*[ \t]+[0-9]+/, @raw); 593 $v_min = '' unless defined $v_min; 594 $v_min =~ s/^#define[ \t]+[A-Z_]+[ \t]+([0-9]+)[.\r\n]*$/$1/; 595 my ($v_pat) = grep(/^#define[ \t]+[A-Z_]+(PATCHLEVEL|MICRO|RELEASE)[A-Z_]*[ \t]+[0-9]+/, @raw); 596 $v_pat = '' unless defined $v_pat; 597 $v_pat =~ s/^#define[ \t]+[A-Z_]+[ \t]+([0-9]+)[.\r\n]*$/$1/; 598 if(($v_maj eq '')||($v_min eq '')||($v_pat eq '')) { 599 my ($rev) = grep(/\$Revision:\s*[0-9\.]+\s*\$/, @raw); 600 return unless defined $rev; 601 $rev =~ s/.*\$Revision:\s*([0-9\.]+)\s*\$[.\r\n]*/$1/; 602 return $rev; 603 } 604 return "$v_maj.$v_min.$v_pat"; 605} 606 6071; 608