File Coverage

lib/App/Info/Lib/Iconv.pm
Criterion Covered Total %
statement 102 116 87.9
branch 33 50 66.0
condition 0 3 0.0
subroutine 29 34 85.2
pod 22 22 100.0
total 186 225 82.6


line stmt bran cond sub pod time code
1             package App::Info::Lib::Iconv;
2              
3             =head1 NAME
4              
5             App::Info::Lib::Iconv - Information about libiconv
6              
7             =head1 SYNOPSIS
8              
9             use App::Info::Lib::Iconv;
10              
11             my $iconv = App::Info::Lib::Iconv->new;
12              
13             if ($iconv->installed) {
14             print "App name: ", $iconv->name, "\n";
15             print "Version: ", $iconv->version, "\n";
16             print "Bin dir: ", $iconv->bin_dir, "\n";
17             } else {
18             print "libiconv is not installed. :-(\n";
19             }
20              
21             =head1 DESCRIPTION
22              
23             App::Info::Lib::Iconv supplies information about the libiconv library
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 libiconv) construct
28             a new App::Info::Lib::Iconv 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 'iconv.h'" is
33             documented for the methods C, C, and
34             C, rest assured that it will only be triggered once, by
35             whichever of those four methods is called first.
36              
37             =cut
38              
39 3     3   42610 use strict;
  3         6  
  3         115  
40 3     3   21 use File::Basename ();
  3         7  
  3         52  
41 3     3   1220 use App::Info::Util;
  3         8  
  3         81  
42 3     3   1613 use App::Info::Lib;
  3         9  
  3         95  
43 3     3   16 use vars qw(@ISA $VERSION);
  3         5  
  3         247  
44             @ISA = qw(App::Info::Lib);
45             $VERSION = '0.57';
46 3     3   17 use constant WIN32 => $^O eq 'MSWin32';
  3         7  
  3         6731  
47              
48             my $u = App::Info::Util->new;
49              
50             ##############################################################################
51              
52             =head1 INTERFACE
53              
54             =head2 Constructor
55              
56             =head3 new
57              
58             my $iconv = App::Info::Lib::Iconv->new(@params);
59              
60             Returns an App::Info::Lib::Iconv object. See L for a
61             complete description of argument parameters.
62              
63             When called, C searches the the list of directories returned by the
64             C method for an executable file with a name returned by the
65             C method. If the executable is found, libiconv will be
66             assumed to be installed. Otherwise, most of the object methods will return
67             C.
68              
69             B
70              
71             =over 4
72              
73             =item info
74              
75             Searching for iconv
76              
77             =item unknown
78              
79             Path to iconv executable?
80              
81             =item confirm
82              
83             Path to iconv executable?
84              
85             =back
86              
87             =cut
88              
89             sub new {
90 6     6 1 1700 my $self = shift->SUPER::new(@_);
91             # Find iconv.
92 6         37 $self->info("Searching for iconv");
93              
94 6 50       39 if (my $exe = $u->first_cat_exe([$self->search_exe_names],
95             $self->search_bin_dirs)) {
96             # We found it. Confirm.
97             $self->{executable} = $self->confirm(
98             key => 'path to iconv',
99             prompt => 'Path to iconv executable?',
100             value => $exe,
101 1     1   11 callback => sub { -x },
102 6         48 error => 'Not an executable'
103             );
104             } else {
105             # No luck. Ask 'em for it.
106             $self->{executable} = $self->unknown(
107             key => 'path to iconv',
108             prompt => 'Path to iconv executable?',
109 0     0   0 callback => sub { -x },
110 0         0 error => 'Not an executable'
111             );
112             }
113              
114 6         53 return $self;
115             }
116              
117             ##############################################################################
118              
119             =head2 Class Method
120              
121             =head3 key_name
122              
123             my $key_name = App::Info::Lib::Iconv->key_name;
124              
125             Returns the unique key name that describes this class. The value returned is
126             the string "libiconv".
127              
128             =cut
129              
130 7     7 1 36 sub key_name { 'libiconv' }
131              
132             ##############################################################################
133              
134             =head2 Object Methods
135              
136             =head3 installed
137              
138             print "libiconv is ", ($iconv->installed ? '' : 'not '),
139             "installed.\n";
140              
141             Returns true if libiconv is installed, and false if it is not.
142             App::Info::Lib::Iconv determines whether libiconv is installed based on the
143             presence or absence of the F application, as found when C
144             constructed the object. If libiconv does not appear to be installed, then most
145             of the other object methods will return empty values.
146              
147             =cut
148              
149 2 50   2 1 13 sub installed { $_[0]->{executable} ? 1 : undef }
150              
151             ##############################################################################
152              
153             =head3 name
154              
155             my $name = $iconv->name;
156              
157             Returns the name of the application. In this case, C simply returns
158             the string "libiconv".
159              
160             =cut
161              
162 2     2 1 11 sub name { 'libiconv' }
163              
164             ##############################################################################
165              
166             =head3 version
167              
168             my $version = $iconv->version;
169              
170             Returns the full version number for libiconv. App::Info::Lib::Iconv attempts
171             to parse the version number from the F file, if it exists.
172              
173             B
174              
175             =over 4
176              
177             =item info
178              
179             Searching for 'iconv.h'
180              
181             Searching for include directory
182              
183             =item error
184              
185             Cannot find include directory
186              
187             Cannot find 'iconv.h'
188              
189             Cannot parse version number from file 'iconv.h'
190              
191             =item unknown
192              
193             Enter a valid libiconv include directory
194              
195             Enter a valid libiconv version number
196              
197             =back
198              
199             =cut
200              
201             # This code reference is called by version(), major_version(), and
202             # minor_version() to get the version numbers.
203             my $get_version = sub {
204             my $self = shift;
205             $self->{version} = undef;
206             $self->info("Searching for 'iconv.h'");
207             # Let inc_dir() do the work.
208             unless ($self->inc_dir && $self->{inc_file}) {
209             # No point in continuing if there's no include file.
210             $self->error("Cannot find 'iconv.h'");
211             return;
212             }
213              
214             # This is the line we're looking for:
215             # #define _LIBICONV_VERSION 0x0107 /* version number: (major<<8) + minor */
216             my $regex = qr/_LIBICONV_VERSION\s+([^\s]+)\s/;
217             if (my $ver = $u->search_file($self->{inc_file}, $regex)) {
218             # Convert the version number from hex.
219             $ver = hex $ver;
220             # Shift 8.
221             my $major = $ver >> 8;
222             # Left shift 8 and subtract from version.
223             my $minor = $ver - ($major << 8);
224             # Store 'em!
225             @{$self}{qw(version major minor)} =
226             ("$major.$minor", $major, $minor);
227             } else {
228             $self->error("Cannot parse version number from file '$self->{inc_file}'");
229             }
230             };
231              
232              
233             sub version {
234 3     3 1 6 my $self = shift;
235 3 50       13 return unless $self->{executable};
236              
237             # Get data.
238 3 100       15 $get_version->($self) unless exists $self->{version};
239              
240             # Handle an unknown value.
241 3 100       11 unless ($self->{version}) {
242             # Create a validation code reference.
243             my $chk_version = sub {
244             # Try to get the version number parts.
245 0     0   0 my ($x, $y) = /^(\d+)\.(\d+)$/;
246             # Return false if we didn't get all three.
247 0 0 0     0 return unless $x and defined $y;
248             # Save both parts.
249 0         0 @{$self}{qw(major minor)} = ($x, $y);
  0         0  
250             # Return true.
251 0         0 return 1;
252 2         7 };
253 2         12 $self->{version} = $self->unknown( key => 'iconv version number',
254             callback => $chk_version);
255             }
256              
257 3         9 return $self->{version};
258             }
259              
260             ##############################################################################
261              
262             =head3 major_version
263              
264             my $major_version = $iconv->major_version;
265              
266             Returns the libiconv major version number. App::Info::Lib::Iconv attempts to
267             parse the version number from the F file, if it exists. For example,
268             if C returns "1.7", then this method returns "1".
269              
270             B
271              
272             =over 4
273              
274             =item info
275              
276             Searching for 'iconv.h'
277              
278             Searching for include directory
279              
280             =item error
281              
282             Cannot find include directory
283              
284             Cannot find 'iconv.h'
285              
286             Cannot parse version number from file 'iconv.h'
287              
288             =item unknown
289              
290             Enter a valid libiconv include directory
291              
292             Enter a valid libiconv version number
293              
294             =back
295              
296             =cut
297              
298             # This code reference is used by major_version() and minor_version() to
299             # validate a version number entered by a user.
300             my $is_int = sub { /^\d+$/ };
301              
302             sub major_version {
303 3     3 1 321 my $self = shift;
304 3 50       12 return unless $self->{executable};
305              
306             # Get data.
307 3 100       12 $get_version->($self) unless exists $self->{version};
308              
309             # Handle an unknown value.
310 3 100       21 $self->{major} = $self->unknown( key => 'iconv major version number',
311             callback => $is_int)
312             unless $self->{major};
313              
314 3         10 return $self->{major};
315             }
316              
317             ##############################################################################
318              
319             =head3 minor_version
320              
321             my $minor_version = $iconv->minor_version;
322              
323             Returns the libiconv minor version number. App::Info::Lib::Iconv attempts to
324             parse the version number from the F file, if it exists. For example,
325             if C returns "1.7", then this method returns "7".
326              
327             B
328              
329             =over 4
330              
331             =item info
332              
333             Searching for 'iconv.h'
334              
335             Searching for include directory
336              
337             =item error
338              
339             Cannot find include directory
340              
341             Cannot find 'iconv.h'
342              
343             Cannot parse version number from file 'iconv.h'
344              
345             =item unknown
346              
347             Enter a valid libiconv include directory
348              
349             Enter a valid libiconv version number
350              
351             =back
352              
353             =cut
354              
355             sub minor_version {
356 2     2 1 5 my $self = shift;
357 2 50       8 return unless $self->{executable};
358              
359             # Get data.
360 2 100       11 $get_version->($self) unless exists $self->{version};
361              
362             # Handle an unknown value.
363 2 100       14 $self->{minor} = $self->unknown( key => 'iconv minor version number',
364             callback => $is_int)
365             unless $self->{minor};
366              
367 2         7 return $self->{minor};
368             }
369              
370             ##############################################################################
371              
372             =head3 patch_version
373              
374             my $patch_version = $iconv->patch_version;
375              
376             Since libiconv has no patch number in its version number, this method will
377             always return false.
378              
379             =cut
380              
381 1     1 1 4 sub patch_version { return }
382              
383             ##############################################################################
384              
385             =head3 executable
386              
387             my $executable = $iconv->executable;
388              
389             Returns the path to the Iconv executable, which will be defined by one of the
390             names returned by C. The executable is searched for in
391             C, so there are no events for this method.
392              
393             =cut
394              
395 1     1 1 7 sub executable { shift->{executable} }
396              
397             ##############################################################################
398              
399             =head3 bin_dir
400              
401             my $bin_dir = $iconv->bin_dir;
402              
403             Returns the path of the directory in which the F application was found
404             when the object was constructed by C.
405              
406             B
407              
408             =over 4
409              
410             =item info
411              
412             Searching for bin directory
413              
414             =item error
415              
416             Cannot find bin directory
417              
418             =item unknown
419              
420             Enter a valid libiconv bin directory
421              
422             =back
423              
424             =cut
425              
426             # This code reference is used by inc_dir() and so_lib_dir() to validate a
427             # directory entered by the user.
428             my $is_dir = sub { -d };
429              
430             sub bin_dir {
431 2     2 1 6 my $self = shift;
432 2 50       10 return unless $self->{executable};
433 2 50       10 unless (exists $self->{bin_dir}) {
434             # This is all probably redundant, but let's do the drill, anyway.
435 2         10 $self->info("Searching for bin directory");
436 2 50       121 if (my $bin = File::Basename::dirname($self->{executable})) {
437             # We found it!
438 2         6 $self->{bin_dir} = $bin;
439             } else {
440 0         0 $self->{bin_dir} = $self->unknown(
441             key => 'iconv bin dir',
442             callback => $is_dir
443             );
444             }
445             }
446 2         7 return $self->{bin_dir};
447             }
448              
449             ##############################################################################
450              
451             =head3 inc_dir
452              
453             my $inc_dir = $iconv->inc_dir;
454              
455             Returns the directory path in which the file F was found.
456             App::Info::Lib::Iconv searches for F in the following directories:
457              
458             =over 4
459              
460             =item /usr/local/include
461              
462             =item /usr/include
463              
464             =item /sw/include
465              
466             =back
467              
468             B
469              
470             =over 4
471              
472             =item info
473              
474             Searching for include directory
475              
476             =item error
477              
478             Cannot find include directory
479              
480             =item unknown
481              
482             Enter a valid libiconv include directory
483              
484             =back
485              
486             =cut
487              
488             sub inc_dir {
489 6     6 1 44 my $self = shift;
490 6 50       19 return unless $self->{executable};
491 6 100       18 unless (exists $self->{inc_dir}) {
492 5         14 $self->info("Searching for include directory");
493 5         25 my @incs = $self->search_inc_names;
494 5 50       20 if (my $dir = $u->first_cat_dir(\@incs, $self->search_inc_dirs)) {
495 5         12 $self->{inc_dir} = $dir;
496             } else {
497 0         0 $self->error("Cannot find include directory");
498 0     0   0 my $cb = sub { $u->first_cat_dir(\@incs, $_) };
  0         0  
499 0         0 $self->{inc_dir} =
500             $self->unknown( key => 'iconv inc dir',
501             callback => $cb,
502             error => "Iconv include file not found in " .
503             "directory");
504             }
505             # So which is the include file? Needed for the version number.
506 5         54 $self->{inc_file} = $u->first_file(
507 5 50       21 map { $u->catfile($self->{inc_dir}, $_) } @incs
508             ) if $self->{inc_dir};
509             }
510 6         44 return $self->{inc_dir};
511             }
512              
513             ##############################################################################
514              
515             =head3 lib_dir
516              
517             my $lib_dir = $iconv->lib_dir;
518              
519             Returns the directory path in which a libiconv library was found. The search
520             looks for a file with a name returned by C in a directory
521             returned by C.
522              
523             B
524              
525             =over 4
526              
527             =item info
528              
529             Searching for library directory
530              
531             =item error
532              
533             Cannot find library directory
534              
535             =item unknown
536              
537             Enter a valid libiconv library directory
538              
539             =back
540              
541             =cut
542              
543             sub lib_dir {
544 2     2 1 5 my $self = shift;
545 2 50       8 return unless $self->{executable};
546 2 50       9 unless (exists $self->{lib_dir}) {
547 2         9 $self->info("Searching for library directory");
548 2         14 my @files = $self->search_lib_names;
549              
550 2 100       12 if (my $dir = $u->first_cat_dir(\@files, $self->search_lib_dirs)) {
551             # Success!
552 1         4 $self->{lib_dir} = $dir;
553             } else {
554 1         9 $self->error("Cannot not find library direcory");
555 1     0   10 my $cb = sub { $u->first_cat_dir(\@files, $_) };
  0         0  
556 1         8 $self->{lib_dir} = $self->unknown(
557             key => 'iconv lib dir',
558             callback => $cb,
559             error => "Library files not found in directory"
560             );
561             }
562             }
563 2         21 return $self->{lib_dir};
564             }
565              
566             ##############################################################################
567              
568             =head3 so_lib_dir
569              
570             my $so_lib_dir = $iconv->so_lib_dir;
571              
572             Returns the directory path in which a libiconv shared object library was
573             found. The search looks for a file with a name returned by
574             C in a directory returned by C.
575              
576             Returns the directory path in which a libiconv shared object library was
577             found. App::Info::Lib::Iconv searches for these files:
578              
579            
580              
581             =over 4
582              
583             =item info
584              
585             Searching for shared object library directory
586              
587             =item error
588              
589             Cannot find shared object library directory
590              
591             =item unknown
592              
593             Enter a valid libiconv shared object library directory
594              
595             =back
596              
597             =cut
598              
599             sub so_lib_dir {
600 2     2 1 5 my $self = shift;
601 2 50       10 return unless $self->{executable};
602 2 50       14 unless (exists $self->{so_lib_dir}) {
603 2         18 $self->info("Searching for shared object library directory");
604 2         12 my @files = $self->search_so_lib_names;
605              
606 2 100       9 if (my $dir = $u->first_cat_dir(\@files, $self->search_lib_dirs)) {
607 1         3 $self->{so_lib_dir} = $dir;
608             } else {
609 1         5 $self->error("Cannot find shared object library directory");
610 1     0   7 my $cb = sub { $u->first_cat_dir(\@files, $_) };
  0         0  
611 1         5 $self->{so_lib_dir} =
612             $self->unknown( key => 'iconv so dir',
613             callback => $cb,
614             error => "Shared object libraries not " .
615             "found in directory");
616             }
617             }
618 2         12 return $self->{so_lib_dir};
619             }
620              
621             ##############################################################################
622              
623             =head3 home_url
624              
625             my $home_url = $iconv->home_url;
626              
627             Returns the libiconv home page URL.
628              
629             =cut
630              
631 1     1 1 5 sub home_url { 'http://www.gnu.org/software/libiconv/' }
632              
633             ##############################################################################
634              
635             =head3 download_url
636              
637             my $download_url = $iconv->download_url;
638              
639             Returns the libiconv download URL.
640              
641             =cut
642              
643 1     1 1 4 sub download_url { 'ftp://ftp.gnu.org/pub/gnu/libiconv/' }
644              
645             ##############################################################################
646              
647             =head3 search_exe_names
648              
649             my @search_exe_names = $iconv->search_exe_names;
650              
651             Returns a list of possible names for the Iconv executable. By default, the
652             only name returned is F (F on Win32).
653              
654             =cut
655              
656             sub search_exe_names {
657 6     6 1 11 my $self = shift;
658 6         49 my @exes = qw(iconv);
659 6         8 if (WIN32) { $_ .= ".exe" for @exes }
660 6         38 return ($self->SUPER::search_exe_names, @exes);
661             }
662              
663             ##############################################################################
664              
665             =head3 search_bin_dirs
666              
667             my @search_bin_dirs = $iconv->search_bin_dirs;
668              
669             Returns a list of possible directories in which to search an executable. Used
670             by the C constructor to find an executable to execute and collect
671             application info. The found directory will also be returned by the C
672             method. By default, the directories returned are those in your path, followed
673             by these:
674              
675             =over 4
676              
677             =item F
678              
679             =item F
680              
681             =item F
682              
683             =item F
684              
685             =item F
686              
687             =item F
688              
689             =item F
690              
691             =item F
692              
693             =back
694              
695             =cut
696              
697             sub search_bin_dirs {
698             return (
699             shift->SUPER::search_bin_dirs,
700 6     6 1 26 $u->path,
701             qw(/usr/local/bin
702             /usr/bin
703             /bin
704             /sw/bin
705             /usr/local/sbin
706             /usr/sbin/
707             /sbin
708             /sw/sbin)
709             );
710             }
711              
712              
713             ##############################################################################
714              
715             =head3 search_lib_names
716              
717             my @seach_lib_names = $self->search_lib_nams
718              
719             Returns a list of possible names for library files. Used by C to
720             search for library files. By default, the list is:
721              
722             =over
723              
724             =item libiconv3.a
725              
726             =item libiconv3.la
727              
728             =item libiconv3.so
729              
730             =item libiconv3.so.0
731              
732             =item libiconv3.so.0.0.1
733              
734             =item libiconv3.dylib
735              
736             =item libiconv3.0.dylib
737              
738             =item libiconv3.0.0.1.dylib
739              
740             =item libiconv.a
741              
742             =item libiconv.la
743              
744             =item libiconv.so
745              
746             =item libiconv.so.0
747              
748             =item libiconv.so.0.0.1
749              
750             =item libiconv.dylib
751              
752             =item libiconv.2.dylib
753              
754             =item libiconv.2.0.4.dylib
755              
756             =item libiconv.0.dylib
757              
758             =item libiconv.0.0.1.dylib
759              
760             =back
761              
762             =cut
763              
764             sub search_lib_names {
765 2     2 1 4 my $self = shift;
766 20         48 return $self->SUPER::search_lib_names,
767 2         19 map { "libiconv.$_"} qw(a la so so.0 so.0.0.1 dylib 2.dylib 2.0.4.dylib
768             0.dylib 0.0.1.dylib);
769             }
770              
771             ##############################################################################
772              
773             =head3 search_so_lib_names
774              
775             my @seach_so_lib_names = $self->search_so_lib_nams
776              
777             Returns a list of possible names for shared object library files. Used by
778             C to search for library files. By default, the list is:
779              
780             =over
781              
782             =item libiconv3.so
783              
784             =item libiconv3.so.0
785              
786             =item libiconv3.so.0.0.1
787              
788             =item libiconv3.dylib
789              
790             =item libiconv3.0.dylib
791              
792             =item libiconv3.0.0.1.dylib
793              
794             =item libiconv.so
795              
796             =item libiconv.so.0
797              
798             =item libiconv.so.0.0.1
799              
800             =item libiconv.dylib
801              
802             =item libiconv.0.dylib
803              
804             =item libiconv.0.0.1.dylib
805              
806             =back
807              
808             =cut
809              
810             sub search_so_lib_names {
811 2     2 1 4 my $self = shift;
812 16         28 return $self->SUPER::search_so_lib_names,
813 2         22 map { "libiconv.$_"} qw(so so.0 so.0.0.1 dylib 2.dylib 2.0.4.dylib
814             0.dylib 0.0.1.dylib);
815             }
816              
817             ##############################################################################
818              
819             =head3 search_lib_dirs
820              
821             my @search_lib_dirs = $iconv->search_lib_dirs;
822              
823             Returns a list of possible directories in which to search for libraries. By
824             default, it returns all of the paths in the C and C
825             attributes defined by the Perl L module -- plus F (in
826             support of all you Fink users out there).
827              
828             =cut
829              
830 4     4 1 21 sub search_lib_dirs { shift->SUPER::search_lib_dirs, $u->lib_dirs, '/sw/lib' }
831              
832             ##############################################################################
833              
834             =head3 search_inc_names
835              
836             my @search_inc_names = $iconv->search_inc_names;
837              
838             Returns a list of include file names to search for. Used by C to
839             search for an include file. By default, the only name returned is F.
840              
841             =cut
842              
843             sub search_inc_names {
844 5     5 1 7 my $self = shift;
845 5         26 return $self->SUPER::search_inc_names, "iconv.h";
846             }
847              
848             ##############################################################################
849              
850             =head3 search_inc_dirs
851              
852             my @search_inc_dirs = $iconv->search_inc_dirs;
853              
854             Returns a list of possible directories in which to search for include files.
855             Used by C to search for an include file. By default, the
856             directories are:
857              
858             =over 4
859              
860             =item /usr/local/include
861              
862             =item /usr/include
863              
864             =item /sw/include
865              
866             =back
867              
868             =cut
869              
870             sub search_inc_dirs {
871             shift->SUPER::search_inc_dirs,
872 5     5 1 21 qw(/usr/local/include
873             /usr/include
874             /sw/include);
875             }
876              
877             1;
878             __END__