File Coverage

lib/App/Info/Lib/Expat.pm
Criterion Covered Total %
statement 76 90 84.4
branch 23 42 54.7
condition 0 6 0.0
subroutine 25 28 89.2
pod 20 20 100.0
total 144 186 77.4


line stmt bran cond sub pod time code
1             package App::Info::Lib::Expat;
2              
3             =head1 NAME
4              
5             App::Info::Lib::Expat - Information about the Expat XML parser
6              
7             =head1 SYNOPSIS
8              
9             use App::Info::Lib::Expat;
10              
11             my $expat = App::Info::Lib::Expat->new;
12              
13             if ($expat->installed) {
14             print "App name: ", $expat->name, "\n";
15             print "Version: ", $expat->version, "\n";
16             print "Bin dir: ", $expat->bin_dir, "\n";
17             } else {
18             print "Expat is not installed. :-(\n";
19             }
20              
21             =head1 DESCRIPTION
22              
23             App::Info::Lib::Expat supplies information about the Expat XML parser
24             installed on the local system. It implements all of the methods defined by
25             App::Info::Lib. Methods that trigger events will trigger them only the first
26             time they're called (See L for documentation on handling
27             events). To start over (after, say, someone has installed Expat) construct a
28             new App::Info::Lib::Expat object to aggregate new meta data.
29              
30             Some of the methods trigger the same events. This is due to cross-calling of
31             shared subroutines. However, any one event should be triggered no more than
32             once. For example, although the info event "Searching for 'expat.h'" is
33             documented for the methods C, C,
34             C, and C, rest assured that it will only be
35             triggered once, by whichever of those four methods is called first.
36              
37             =cut
38              
39 3     3   31121 use strict;
  3         6  
  3         102  
40 3     3   1259 use App::Info::Util;
  3         9  
  3         92  
41 3     3   1425 use App::Info::Lib;
  3         8  
  3         80  
42 3     3   15 use vars qw(@ISA $VERSION);
  3         6  
  3         5213  
43             @ISA = qw(App::Info::Lib);
44             $VERSION = '0.57';
45              
46             my $u = App::Info::Util->new;
47              
48             ##############################################################################
49              
50             =head1 INTERFACE
51              
52             =head2 Constructor
53              
54             =head3 new
55              
56             my $expat = App::Info::Lib::Expat->new(@params);
57              
58             Returns an App::Info::Lib::Expat object. See L for a
59             complete description of argument parameters.
60              
61             When called, C searches all of the paths returned by the
62             C method for one of the files returned by the
63             C method. If any of is found, then Expat is assumed to be
64             installed. Otherwise, most of the object methods will return C.
65              
66             B
67              
68             =over 4
69              
70             =item info
71              
72             Searching for Expat libraries
73              
74             =item confirm
75              
76             Path to Expat library directory?
77              
78             =item unknown
79              
80             Path to Expat library directory?
81              
82             =back
83              
84             =cut
85              
86             sub new {
87             # Construct the object.
88 3     3 1 3431 my $self = shift->SUPER::new(@_);
89             # Find libexpat.
90 3         33 $self->info("Searching for Expat libraries");
91              
92 3         37 my @libs = $self->search_lib_names;
93 3     1   17 my $cb = sub { $u->first_cat_dir(\@libs, $_) };
  1         6  
94 3 100       16 if (my $lexpat = $u->first_cat_dir(\@libs, $self->search_lib_dirs)) {
95             # We found libexpat. Confirm.
96 1         12 $self->{libexpat} =
97             $self->confirm( key => 'expat lib dir',
98             prompt => 'Path to Expat library directory?',
99             value => $lexpat,
100             callback => $cb,
101             error => 'No Expat libraries found in directory');
102             } else {
103             # Handle an unknown value.
104 2         33 $self->{libexpat} =
105             $self->unknown( key => 'expat lib dir',
106             prompt => 'Path to Expat library directory?',
107             callback => $cb,
108             error => 'No Expat libraries found in directory');
109             }
110              
111 3         47 return $self;
112             }
113              
114             ##############################################################################
115              
116             =head2 Class Method
117              
118             =head3 key_name
119              
120             my $key_name = App::Info::Lib::Expat->key_name;
121              
122             Returns the unique key name that describes this class. The value returned is
123             the string "Expat".
124              
125             =cut
126              
127 1     1 1 15 sub key_name { 'Expat' }
128              
129             ##############################################################################
130              
131             =head2 Object Methods
132              
133             =head3 installed
134              
135             print "Expat is ", ($expat->installed ? '' : 'not '),
136             "installed.\n";
137              
138             Returns true if Expat is installed, and false if it is not.
139             App::Info::Lib::Expat determines whether Expat is installed based on the
140             presence or absence on the file system of one of the files searched for when
141             C constructed the object. If Expat does not appear to be installed,
142             then most of the other object methods will return empty values.
143              
144             =cut
145              
146 2 100   2 1 14 sub installed { $_[0]->{libexpat} ? 1 : undef }
147              
148             ##############################################################################
149              
150             =head3 name
151              
152             my $name = $expat->name;
153              
154             Returns the name of the application. In this case, C simply returns
155             the string "Expat".
156              
157             =cut
158              
159 2     2 1 9 sub name { 'Expat' }
160              
161             ##############################################################################
162              
163             =head3 version
164              
165             Returns the full version number for Expat. App::Info::Lib::Expat attempts
166             parse the version number from the F file, if it exists.
167              
168             B
169              
170             =over 4
171              
172             =item info
173              
174             Searching for 'expat.h'
175              
176             Searching for include directory
177              
178             =item error
179              
180             Cannot find include directory
181              
182             Cannot find 'expat.h'
183              
184             Failed to parse version from 'expat.h'
185              
186             =item unknown
187              
188             Enter a valid Expat include directory
189              
190             Enter a valid Expat version number
191              
192             =back
193              
194             =cut
195              
196             my $get_version = sub {
197             my $self = shift;
198             $self->{version} = undef;
199             $self->info("Searching for 'expat.h'");
200             my $inc = $self->inc_dir
201             or ($self->error("Cannot find 'expat.h'")) && return;
202             my $header = $u->catfile($inc, 'expat.h');
203             my @regexen = ( qr/XML_MAJOR_VERSION\s+(\d+)$/,
204             qr/XML_MINOR_VERSION\s+(\d+)$/,
205             qr/XML_MICRO_VERSION\s+(\d+)$/ );
206              
207             my ($x, $y, $z) = $u->multi_search_file($header, @regexen);
208             if (defined $x and defined $y and defined $z) {
209             # Assemble the version number and store it.
210             my $v = "$x.$y.$z";
211             @{$self}{qw(version major minor patch)} = ($v, $x, $y, $z);
212             } else {
213             # Warn them if we couldn't get them all.
214             $self->error("Failed to parse version from '$header'");
215             }
216             };
217              
218             sub version {
219 1     1 1 3 my $self = shift;
220 1 50       4 return unless $self->{libexpat};
221              
222             # Get data.
223 1 50       6 $get_version->($self) unless exists $self->{version};
224              
225             # Handle an unknown value.
226 1 50       5 unless ($self->{version}) {
227             # Create a validation code reference.
228             my $chk_version = sub {
229             # Try to get the version number parts.
230 0     0   0 my ($x, $y, $z) = /^(\d+)\.(\d+).(\d+)$/;
231             # Return false if we didn't get all three.
232 0 0 0     0 return unless $x and defined $y and defined $z;
      0        
233             # Save all three parts.
234 0         0 @{$self}{qw(major minor patch)} = ($x, $y, $z);
  0         0  
235             # Return true.
236 0         0 return 1;
237 0         0 };
238 0         0 $self->{version} = $self->unknown( key => 'expat version number',
239             callback => $chk_version);
240             }
241 1         5 return $self->{version};
242             }
243              
244             ##############################################################################
245              
246             =head3 major_version
247              
248             my $major_version = $expat->major_version;
249              
250             Returns the Expat major version number. App::Info::Lib::Expat attempts to
251             parse the version number from the F file, if it exists. For example,
252             if C returns "1.95.2", then this method returns "1".
253              
254             B
255              
256             =over 4
257              
258             =item info
259              
260             Searching for 'expat.h'
261              
262             Searching for include directory
263              
264             =item error
265              
266             Cannot find include directory
267              
268             Cannot find 'expat.h'
269              
270             Failed to parse version from 'expat.h'
271              
272             =item unknown
273              
274             Enter a valid Expat include directory
275              
276             Enter a valid Expat major version number
277              
278             =back
279              
280             =cut
281              
282             # This code reference is used by major_version(), minor_version(), and
283             # patch_version() to validate a version number entered by a user.
284             my $is_int = sub { /^\d+$/ };
285              
286             sub major_version {
287 1     1 1 2 my $self = shift;
288 1 50       5 return unless $self->{libexpat};
289              
290             # Get data.
291 1 50       4 $get_version->($self) unless exists $self->{version};
292              
293             # Handle an unknown value.
294 1 50       4 $self->{major} = $self->unknown( key => 'expat major version number',
295             callback => $is_int)
296             unless $self->{major};
297              
298 1         4 return $self->{major};
299             }
300              
301             ##############################################################################
302              
303             =head3 minor_version
304              
305             my $minor_version = $expat->minor_version;
306              
307             Returns the Expat minor version number. App::Info::Lib::Expat attempts to
308             parse the version number from the F file, if it exists. For example,
309             if C returns "1.95.2", then this method returns "95".
310              
311             B
312              
313             =over 4
314              
315             =item info
316              
317             Searching for 'expat.h'
318              
319             Searching for include directory
320              
321             =item error
322              
323             Cannot find include directory
324              
325             Cannot find 'expat.h'
326              
327             Failed to parse version from 'expat.h'
328              
329             =item unknown
330              
331             Enter a valid Expat include directory
332              
333             Enter a valid Expat minor version number
334              
335             =back
336              
337             =cut
338              
339             sub minor_version {
340 1     1 1 2 my $self = shift;
341 1 50       6 return unless $self->{libexpat};
342              
343             # Get data.
344 1 50       3 $get_version->($self) unless exists $self->{version};
345              
346             # Handle an unknown value.
347 1 50       4 $self->{minor} = $self->unknown( key =>'expat minor version number',
348             callback => $is_int)
349             unless $self->{minor};
350              
351 1         7 return $self->{minor};
352             }
353              
354             ##############################################################################
355              
356             =head3 patch_version
357              
358             my $patch_version = $expat->patch_version;
359              
360             Returns the Expat patch version number. App::Info::Lib::Expat attempts to
361             parse the version number from the F file, if it exists. For example,
362             C returns "1.95.2", then this method returns "2".
363              
364             B
365              
366             =over 4
367              
368             =item info
369              
370             Searching for 'expat.h'
371              
372             Searching for include directory
373              
374             =item error
375              
376             Cannot find include directory
377              
378             Cannot find 'expat.h'
379              
380             Failed to parse version from 'expat.h'
381              
382             =item unknown
383              
384             Enter a valid Expat include directory
385              
386             Enter a valid Expat patch version number
387              
388             =back
389              
390             =cut
391              
392             sub patch_version {
393 1     1 1 2 my $self = shift;
394 1 50       4 return unless $self->{libexpat};
395              
396             # Get data.
397 1 50       4 $get_version->($self) unless exists $self->{version};
398              
399             # Handle an unknown value.
400 1 50       4 $self->{patch} = $self->unknown( key => 'expat patch version number',
401             callback => $is_int)
402             unless $self->{patch};
403              
404 1         6 return $self->{patch};
405             }
406              
407             ##############################################################################
408              
409             =head3 bin_dir
410              
411             my $bin_dir = $expat->bin_dir;
412              
413             Since Expat includes no binaries, this method always returns false.
414              
415             =cut
416              
417 1     1 1 5 sub bin_dir { return }
418              
419             ##############################################################################
420              
421             =head3 executable
422              
423             my $executable = $expat->executable;
424              
425             Since Expat includes no executable program, this method always returns false.
426              
427             =cut
428              
429 1     1 1 3 sub executable { return }
430              
431             ##############################################################################
432              
433             =head3 inc_dir
434              
435             my $inc_dir = $expat->inc_dir;
436              
437             Returns the directory path in which the file F was found.
438             App::Info::Lib::Expat searches for F in the following directories:
439              
440             =over 4
441              
442             =item /usr/local/include
443              
444             =item /usr/include
445              
446             =item /sw/include
447              
448             =back
449              
450             B
451              
452             =over 4
453              
454             =item info
455              
456             Searching for include directory
457              
458             =item error
459              
460             Cannot find include directory
461              
462             =item unknown
463              
464             Enter a valid Expat include directory
465              
466             =back
467              
468             =cut
469              
470             # This code reference is used by inc_dir() and so_lib_dir() to validate a
471             # directory entered by the user.
472             my $is_dir = sub { -d };
473              
474             sub inc_dir {
475 2     2 1 4 my $self = shift;
476 2 50       7 return unless $self->{libexpat};
477 2 100       5 unless (exists $self->{inc_dir}) {
478 1         4 $self->info("Searching for include directory");
479 1         7 my @incs = $self->search_inc_names;
480              
481 1 50       4 if (my $dir = $u->first_cat_dir(\@incs, $self->search_inc_dirs)) {
482 1         3 $self->{inc_dir} = $dir;
483             } else {
484 0         0 $self->error("Cannot find include directory");
485 0     0   0 my $cb = sub { $u->first_cat_dir(\@incs, $_) };
  0         0  
486 0         0 $self->{inc_dir} =
487             $self->unknown( key => 'explat inc dir',
488             callback => $cb,
489             error => "No expat include file found in " .
490             "directory");
491             }
492             }
493 2         9 return $self->{inc_dir};
494             }
495              
496             ##############################################################################
497              
498             =head3 lib_dir
499              
500             my $lib_dir = $expat->lib_dir;
501              
502             Returns the directory path in which a Expat library was found. The files and
503             paths searched are as described for the L<"new"|new> constructor, as are
504             the events.
505              
506             =cut
507              
508 1     1 1 7 sub lib_dir { $_[0]->{libexpat} }
509              
510             ##############################################################################
511              
512             =head3 so_lib_dir
513              
514             my $so_lib_dir = $expat->so_lib_dir;
515              
516             Returns the directory path in which a Expat shared object library was found.
517             It searches all of the paths in the C and C attributes
518             defined by the Perl L module -- plus F (for all you
519             Fink fans) -- for one of the following files:
520              
521             =over
522              
523             =item libexpat.so
524              
525             =item libexpat.so.0
526              
527             =item libexpat.so.0.0.1
528              
529             =item libexpat.dylib
530              
531             =item libexpat.0.dylib
532              
533             =item libexpat.0.0.1.dylib
534              
535             =back
536              
537             B
538              
539             =over 4
540              
541             =item info
542              
543             Searching for shared object library directory
544              
545             =item error
546              
547             Cannot find shared object library directory
548              
549             =item unknown
550              
551             Enter a valid Expat shared object library directory
552              
553             =back
554              
555             =cut
556              
557             sub so_lib_dir {
558 1     1 1 2 my $self = shift;
559 1 50       4 return unless $self->{libexpat};
560 1 50       4 unless (exists $self->{so_lib_dir}) {
561 1         4 $self->info("Searching for shared object library directory");
562              
563 1         8 my @libs = $self->search_so_lib_names;
564 1     0   4 my $cb = sub { $u->first_cat_dir(\@libs, $_) };
  0         0  
565 1 50       4 if (my $dir = $u->first_cat_dir(\@libs, $self->search_lib_dirs)) {
566 1         5 $self->{so_lib_dir} = $dir;
567             } else {
568 0         0 $self->error("Cannot find shared object library directory");
569 0         0 $self->{so_lib_dir} =
570             $self->unknown( key => 'expat so dir',
571             callback => $cb,
572             error => "Shared object libraries not " .
573             "found in directory");
574             }
575             }
576 1         9 return $self->{so_lib_dir};
577             }
578              
579             =head3 home_url
580              
581             my $home_url = $expat->home_url;
582              
583             Returns the libexpat home page URL.
584              
585             =cut
586              
587 1     1 1 4 sub home_url { 'http://expat.sourceforge.net/' }
588              
589             =head3 download_url
590              
591             my $download_url = $expat->download_url;
592              
593             Returns the libexpat download URL.
594              
595             =cut
596              
597 1     1 1 5 sub download_url { 'http://sourceforge.net/projects/expat/' }
598              
599             ##############################################################################
600              
601             =head3 search_lib_names
602              
603             my @seach_lib_names = $self->search_lib_nams
604              
605             Returns a list of possible names for library files. Used by C to
606             search for library files. By default, the list is:
607              
608             =over
609              
610             =item libexpat.a
611              
612             =item libexpat.la
613              
614             =item libexpat.so
615              
616             =item libexpat.so.0
617              
618             =item libexpat.so.0.0.1
619              
620             =item libexpat.dylib
621              
622             =item libexpat.0.dylib
623              
624             =item libexpat.0.0.1.dylib
625              
626             =back
627              
628             =cut
629              
630             sub search_lib_names {
631 3     3 1 8 my $self = shift;
632 24         54 return $self->SUPER::search_lib_names,
633 3         24 map { "libexpat.$_"} qw(a la so so.0 so.0.0.1 dylib 0.dylib 0.0.1.dylib);
634             }
635              
636             ##############################################################################
637              
638             =head3 search_so_lib_names
639              
640             my @seach_so_lib_names = $self->search_so_lib_nams
641              
642             Returns a list of possible names for shared object library files. Used by
643             C to search for library files. By default, the list is:
644              
645             =over
646              
647             =item libexpat.so
648              
649             =item libexpat.so.0
650              
651             =item libexpat.so.0.0.1
652              
653             =item libexpat.dylib
654              
655             =item libexpat.0.dylib
656              
657             =item libexpat.0.0.1.dylib
658              
659             =back
660              
661             =cut
662              
663             sub search_so_lib_names {
664 1     1 1 1 my $self = shift;
665 6         14 return $self->SUPER::search_so_lib_names,
666 1         11 map { "libexpat.$_"} qw(so so.0 so.0.0.1 dylib 0.dylib 0.0.1.dylib);
667             }
668              
669             ##############################################################################
670              
671             =head3 search_lib_dirs
672              
673             my @search_lib_dirs = $expat->search_lib_dirs;
674              
675             Returns a list of possible directories in which to search for libraries. By
676             default, it returns all of the paths in the C and C
677             attributes defined by the Perl L module -- plus F (in
678             support of all you Fink users out there).
679              
680             =cut
681              
682 4     4 1 32 sub search_lib_dirs { shift->SUPER::search_lib_dirs, $u->lib_dirs, '/sw/lib' }
683              
684             ##############################################################################
685              
686             =head3 search_inc_names
687              
688             my @search_inc_names = $expat->search_inc_names;
689              
690             Returns a list of include file names to search for. Used by C to
691             search for an include file. By default, the only name returned is F.
692              
693             =cut
694              
695             sub search_inc_names {
696 1     1 1 1 my $self = shift;
697 1         9 return $self->SUPER::search_inc_names, "expat.h";
698             }
699              
700             ##############################################################################
701              
702             =head3 search_inc_dirs
703              
704             my @search_inc_dirs = $expat->search_inc_dirs;
705              
706             Returns a list of possible directories in which to search for include files.
707             Used by C to search for an include file. By default, the
708             directories are:
709              
710             =over 4
711              
712             =item /usr/local/include
713              
714             =item /usr/include
715              
716             =item /sw/include
717              
718             =back
719              
720             =cut
721              
722             sub search_inc_dirs {
723             shift->SUPER::search_inc_dirs,
724 1     1 1 6 qw(/usr/local/include
725             /usr/include
726             /sw/include);
727             }
728              
729             1;
730             __END__