File Coverage

blib/lib/Config/Perl/V.pm
Criterion Covered Total %
statement 110 115 95.6
branch 44 54 81.4
condition 34 58 58.6
subroutine 10 10 100.0
pod 4 4 100.0
total 202 241 83.8


line stmt bran cond sub pod time code
1             package Config::Perl::V;
2              
3 28     28   1723440 use strict;
  28         292  
  28         708  
4 28     28   129 use warnings;
  28         46  
  28         608  
5              
6 28     28   117 use Config;
  28         41  
  28         869  
7 28     28   122 use Exporter;
  28         41  
  28         922  
8 28     28   189 use vars qw($VERSION @ISA @EXPORT_OK %EXPORT_TAGS);
  28         107  
  28         58738  
9             $VERSION = "0.34";
10             @ISA = qw( Exporter );
11             @EXPORT_OK = qw( plv2hash summary myconfig signature );
12             %EXPORT_TAGS = (
13             'all' => [ @EXPORT_OK ],
14             'sig' => [ "signature" ],
15             );
16              
17             # Characteristics of this binary (from libperl):
18             # Compile-time options: DEBUGGING PERL_DONT_CREATE_GVSV PERL_MALLOC_WRAP
19             # USE_64_BIT_INT USE_LARGE_FILES USE_PERLIO
20              
21             # The list are as the perl binary has stored it in PL_bincompat_options
22             # search for it in
23             # perl.c line 1643 S_Internals_V ()
24             # perl -ne'(/^S_Internals_V/../^}/)&&s/^\s+"( .*)"/$1/ and print' perl.c
25             # perl.h line 4566 PL_bincompat_options
26             # perl -ne'(/^\w.*PL_bincompat/../^\w}/)&&s/^\s+"( .*)"/$1/ and print' perl.h
27             my %BTD = map {( $_ => 0 )} qw(
28              
29             DEBUGGING
30             NO_HASH_SEED
31             NO_MATHOMS
32             NO_PERL_INTERNAL_RAND_SEED
33             NO_PERL_RAND_SEED
34             NO_TAINT_SUPPORT
35             PERL_BOOL_AS_CHAR
36             PERL_COPY_ON_WRITE
37             PERL_DISABLE_PMC
38             PERL_DONT_CREATE_GVSV
39             PERL_EXTERNAL_GLOB
40             PERL_HASH_FUNC_DJB2
41             PERL_HASH_FUNC_MURMUR3
42             PERL_HASH_FUNC_ONE_AT_A_TIME
43             PERL_HASH_FUNC_ONE_AT_A_TIME_HARD
44             PERL_HASH_FUNC_ONE_AT_A_TIME_OLD
45             PERL_HASH_FUNC_SDBM
46             PERL_HASH_FUNC_SIPHASH
47             PERL_HASH_FUNC_SUPERFAST
48             PERL_IS_MINIPERL
49             PERL_MALLOC_WRAP
50             PERL_MEM_LOG
51             PERL_MEM_LOG_ENV
52             PERL_MEM_LOG_ENV_FD
53             PERL_MEM_LOG_NOIMPL
54             PERL_MEM_LOG_STDERR
55             PERL_MEM_LOG_TIMESTAMP
56             PERL_NEW_COPY_ON_WRITE
57             PERL_OP_PARENT
58             PERL_PERTURB_KEYS_DETERMINISTIC
59             PERL_PERTURB_KEYS_DISABLED
60             PERL_PERTURB_KEYS_RANDOM
61             PERL_PRESERVE_IVUV
62             PERL_RELOCATABLE_INCPUSH
63             PERL_USE_DEVEL
64             PERL_USE_SAFE_PUTENV
65             PERL_USE_UNSHARED_KEYS_IN_LARGE_HASHES
66             SILENT_NO_TAINT_SUPPORT
67             UNLINK_ALL_VERSIONS
68             USE_ATTRIBUTES_FOR_PERLIO
69             USE_FAST_STDIO
70             USE_HASH_SEED_EXPLICIT
71             USE_LOCALE
72             USE_LOCALE_CTYPE
73             USE_NO_REGISTRY
74             USE_PERL_ATOF
75             USE_SITECUSTOMIZE
76             USE_THREAD_SAFE_LOCALE
77              
78             DEBUG_LEAKING_SCALARS
79             DEBUG_LEAKING_SCALARS_FORK_DUMP
80             DECCRTL_SOCKETS
81             FAKE_THREADS
82             FCRYPT
83             HAS_TIMES
84             HAVE_INTERP_INTERN
85             MULTIPLICITY
86             MYMALLOC
87             NO_HASH_SEED
88             PERL_DEBUG_READONLY_COW
89             PERL_DEBUG_READONLY_OPS
90             PERL_GLOBAL_STRUCT
91             PERL_GLOBAL_STRUCT_PRIVATE
92             PERL_HASH_NO_SBOX32
93             PERL_HASH_USE_SBOX32
94             PERL_IMPLICIT_CONTEXT
95             PERL_IMPLICIT_SYS
96             PERLIO_LAYERS
97             PERL_MAD
98             PERL_MICRO
99             PERL_NEED_APPCTX
100             PERL_NEED_TIMESBASE
101             PERL_OLD_COPY_ON_WRITE
102             PERL_POISON
103             PERL_SAWAMPERSAND
104             PERL_TRACK_MEMPOOL
105             PERL_USES_PL_PIDSTATUS
106             PL_OP_SLAB_ALLOC
107             THREADS_HAVE_PIDS
108             USE_64_BIT_ALL
109             USE_64_BIT_INT
110             USE_IEEE
111             USE_ITHREADS
112             USE_LARGE_FILES
113             USE_LOCALE_COLLATE
114             USE_LOCALE_NUMERIC
115             USE_LOCALE_TIME
116             USE_LONG_DOUBLE
117             USE_PERLIO
118             USE_QUADMATH
119             USE_REENTRANT_API
120             USE_SFIO
121             USE_SOCKS
122             VMS_DO_SOCKETS
123             VMS_SHORTEN_LONG_SYMBOLS
124             VMS_SYMBOL_CASE_AS_IS
125             );
126              
127             # These are all the keys that are
128             # 1. Always present in %Config - lib/Config.pm #87 tie %Config
129             # 2. Reported by 'perl -V' (the rest)
130             my @config_vars = qw(
131              
132             api_subversion
133             api_version
134             api_versionstring
135             archlibexp
136             dont_use_nlink
137             d_readlink
138             d_symlink
139             exe_ext
140             inc_version_list
141             ldlibpthname
142             patchlevel
143             path_sep
144             perl_patchlevel
145             privlibexp
146             scriptdir
147             sitearchexp
148             sitelibexp
149             subversion
150             usevendorprefix
151             version
152              
153             git_commit_id
154             git_describe
155             git_branch
156             git_uncommitted_changes
157             git_commit_id_title
158             git_snapshot_date
159              
160             package revision version_patchlevel_string
161              
162             osname osvers archname
163             myuname
164             config_args
165             hint useposix d_sigaction
166             useithreads usemultiplicity
167             useperlio d_sfio uselargefiles usesocks
168             use64bitint use64bitall uselongdouble
169             usemymalloc default_inc_excludes_dot bincompat5005
170              
171             cc ccflags
172             optimize
173             cppflags
174             ccversion gccversion gccosandvers
175             intsize longsize ptrsize doublesize byteorder
176             d_longlong longlongsize d_longdbl longdblsize
177             ivtype ivsize nvtype nvsize lseektype lseeksize
178             alignbytes prototype
179              
180             ld ldflags
181             libpth
182             libs
183             perllibs
184             libc so useshrplib libperl
185             gnulibc_version
186              
187             dlsrc dlext d_dlsymun ccdlflags
188             cccdlflags lddlflags
189             );
190              
191             my %empty_build = (
192             'osname' => "",
193             'stamp' => 0,
194             'options' => { %BTD },
195             'patches' => [],
196             );
197              
198             sub _make_derived {
199 67     67   142 my $conf = shift;
200              
201 67         274 for ( [ 'lseektype' => "Off_t" ],
202             [ 'myuname' => "uname" ],
203             [ 'perl_patchlevel' => "patch" ],
204             ) {
205 201         243 my ($official, $derived) = @{$_};
  201         375  
206 201   100     760 $conf->{'config'}{$derived} ||= $conf->{'config'}{$official};
207 201   100     918 $conf->{'config'}{$official} ||= $conf->{'config'}{$derived};
208 201         479 $conf->{'derived'}{$derived} = delete $conf->{'config'}{$derived};
209             }
210              
211 67 100 100     394 if (exists $conf->{'config'}{'version_patchlevel_string'} &&
212             !exists $conf->{'config'}{'api_version'}) {
213 32         105 my $vps = $conf->{'config'}{'version_patchlevel_string'};
214             $vps =~ s{\b revision \s+ (\S+) }{}x and
215 32 50 0     190 $conf->{'config'}{'revision'} ||= $1;
216              
217             $vps =~ s{\b version \s+ (\S+) }{}x and
218 32 50 33     535 $conf->{'config'}{'api_version'} ||= $1;
219             $vps =~ s{\b subversion \s+ (\S+) }{}x and
220 32 50 66     422 $conf->{'config'}{'subversion'} ||= $1;
221             $vps =~ s{\b patch \s+ (\S+) }{}x and
222 32 50 0     135 $conf->{'config'}{'perl_patchlevel'} ||= $1;
223             }
224              
225             ($conf->{'config'}{'version_patchlevel_string'} ||= join " ",
226 0         0 map { ($_, $conf->{'config'}{$_} ) }
227 67   66     313 grep { $conf->{'config'}{$_} }
  81         213  
228             qw( api_version subversion perl_patchlevel )) =~ s/\bperl_//;
229              
230 67   50     336 $conf->{'config'}{'perl_patchlevel'} ||= ""; # 0 is not a valid patchlevel
231              
232 67 50       216 if ($conf->{'config'}{'perl_patchlevel'} =~ m{^git\w*-([^-]+)}i) {
233 0   0     0 $conf->{'config'}{'git_branch'} ||= $1;
234 0   0     0 $conf->{'config'}{'git_describe'} ||= $conf->{'config'}{'perl_patchlevel'};
235             }
236              
237 67   100     2677 $conf->{'config'}{$_} ||= "undef" for grep m{^(?:use|def)} => @config_vars;
238              
239 67         806 $conf;
240             } # _make_derived
241              
242             sub plv2hash {
243 59     59 1 70079 my %config;
244              
245 59         743 my $pv = join "\n" => @_;
246              
247 59 100       630 if ($pv =~ m{^Summary of my\s+(\S+)\s+\(\s*(.*?)\s*\)}m) {
248 32         284 $config{'package'} = $1;
249 32         225 my $rev = $2;
250 32 50       299 $rev =~ s/^ revision \s+ (\S+) \s*//x and $config{'revision'} = $1;
251 32 50       150 $rev and $config{'version_patchlevel_string'} = $rev;
252 32         259 my ($rel) = $config{'package'} =~ m{perl(\d)};
253 32         252 my ($vers, $subvers) = $rev =~ m{version\s+(\d+)\s+subversion\s+(\d+)};
254             defined $vers && defined $subvers && defined $rel and
255 32 50 33     488 $config{'version'} = "$rel.$vers.$subvers";
      33        
256             }
257              
258 59 50       300 if ($pv =~ m{^\s+(Snapshot of:)\s+(\S+)}) {
259 0         0 $config{'git_commit_id_title'} = $1;
260 0         0 $config{'git_commit_id'} = $2;
261             }
262              
263             # these are always last on line and can have multiple quotation styles
264 59         170 for my $k (qw( ccflags ldflags lddlflags )) {
265 177 100       3439 $pv =~ s{, \s* $k \s*=\s* (.*) \s*$}{}mx or next;
266 45         429 my $v = $1;
267 45         178 $v =~ s/\s*,\s*$//;
268 45         200 $v =~ s/^(['"])(.*)\1$/$2/;
269 45         156 $config{$k} = $v;
270             }
271              
272 59 100       8371 if (my %kv = ($pv =~ m{\b
273             (\w+) # key
274             \s*= # assign
275             ( '\s*[^']*?\s*' # quoted value
276             | \S+[^=]*?\s*\n # unquoted running till end of line
277             | \S+ # unquoted value
278             | \s*\n # empty
279             )
280             (?:,?\s+|\s*\n)? # separator (5.8.x reports did not have a ','
281             }gx)) { # between every kv pair
282              
283 32         245 while (my ($k, $v) = each %kv) {
284 1835         2493 $k =~ s{\s+$} {};
285 1835         3388 $v =~ s{\s*\n\z} {};
286 1835         2533 $v =~ s{,$} {};
287 1835 100       3521 $v =~ m{^'(.*)'$} and $v = $1;
288 1835         2588 $v =~ s{\s+$} {};
289 1835         4897 $config{$k} = $v;
290             }
291             }
292              
293 59         426 my $build = { %empty_build };
294              
295             $pv =~ m{^\s+Compiled at\s+(.*)}m
296 59 100       2442 and $build->{'stamp'} = $1;
297             $pv =~ m{^\s+Locally applied patches:(?:\s+|\n)(.*?)(?:[\s\n]+Buil[td] under)}ms
298 59 100       461 and $build->{'patches'} = [ split m{\n+\s*}, $1 ];
299             $pv =~ m{^\s+Compile-time options:(?:\s+|\n)(.*?)(?:[\s\n]+(?:Locally applied|Buil[td] under))}ms
300 59 100       4105 and map { $build->{'options'}{$_} = 1 } split m{\s+|\n} => $1;
  597         997  
301              
302 59         167 $build->{'osname'} = $config{'osname'};
303             $pv =~ m{^\s+Built under\s+(.*)}m
304 59 100       2348 and $build->{'osname'} = $1;
305 59   66     264 $config{'osname'} ||= $build->{'osname'};
306              
307 59         467 return _make_derived ({
308             'build' => $build,
309             'environment' => {},
310             'config' => \%config,
311             'derived' => {},
312             'inc' => [],
313             });
314             } # plv2hash
315              
316             sub summary {
317 48   66 48 1 135331 my $conf = shift || myconfig ();
318             ref $conf eq "HASH"
319             && exists $conf->{'config'}
320             && exists $conf->{'build'}
321             && ref $conf->{'config'} eq "HASH"
322 48 100 66     763 && ref $conf->{'build'} eq "HASH" or return;
      100        
      100        
      100        
323              
324             my %info = map {
325 44 100       200 exists $conf->{'config'}{$_} ? ( $_ => $conf->{'config'}{$_} ) : () }
  1320         3341  
326             qw( archname osname osvers revision patchlevel subversion version
327             cc ccversion gccversion config_args inc_version_list
328             d_longdbl d_longlong use64bitall use64bitint useithreads
329             uselongdouble usemultiplicity usemymalloc useperlio useshrplib
330             doublesize intsize ivsize nvsize longdblsize longlongsize lseeksize
331             default_inc_excludes_dot
332             );
333 44         141 $info{$_}++ for grep { $conf->{'build'}{'options'}{$_} } keys %{$conf->{'build'}{'options'}};
  3316         3712  
  44         474  
334              
335 44         320 return \%info;
336             } # summary
337              
338             sub signature {
339 33     33 1 1081549 my $no_md5 = "0" x 32;
340 33 100       141 my $conf = summary (shift) or return $no_md5;
341              
342 29         64 eval { require Digest::MD5 };
  29         296  
343 29 100       137 $@ and return $no_md5;
344              
345 28         84 $conf->{'cc'} =~ s{.*\bccache\s+}{};
346 28         113 $conf->{'cc'} =~ s{.*[/\\]}{};
347              
348 28         69 delete $conf->{'config_args'};
349             return Digest::MD5::md5_hex (join "\xFF" => map {
350 775 50       2496 "$_=".(defined $conf->{$_} ? $conf->{$_} : "\xFE");
351 28         67 } sort keys %{$conf});
  28         1203  
352             } # signature
353              
354             sub myconfig {
355 8     8 1 7993 my $args = shift;
356 1         6 my %args = ref $args eq "HASH" ? %{$args} :
357 8 100       55 ref $args eq "ARRAY" ? @{$args} : ();
  1 100       8  
358              
359 8         36 my $build = { %empty_build };
360              
361             # 5.14.0 and later provide all the information without shelling out
362 8         15 my $stamp = eval { Config::compile_date () };
  8         186  
363 8 100       37 if (defined $stamp) {
364 3         39 $stamp =~ s/^Compiled at //;
365 3         10 $build->{'osname'} = $^O;
366 3         4 $build->{'stamp'} = $stamp;
367 3         14 $build->{'patches'} = [ Config::local_patches () ];
368 3         47 $build->{'options'}{$_} = 1 for Config::bincompat_options (),
369             Config::non_bincompat_options ();
370             }
371             else {
372             #y $pv = qx[$^X -e"sub Config::myconfig{};" -V];
373 5         62719 my $cnf = plv2hash (qx[$^X -V]);
374              
375 5         98 $build->{$_} = $cnf->{'build'}{$_} for qw( osname stamp patches options );
376             }
377              
378 8         465 my @KEYS = keys %ENV;
379             my %env =
380 8         100 map {( $_ => $ENV{$_} )} grep m{^PERL} => @KEYS;
  24         75  
381 8 100       27 if ($args{'env'}) {
382 2         65 $env{$_} = $ENV{$_} for grep m{$args{'env'}} => @KEYS;
383             }
384              
385 8         19 my %config = map { $_ => $Config{$_} } @config_vars;
  712         5871  
386              
387 8         74 return _make_derived ({
388             'build' => $build,
389             'environment' => \%env,
390             'config' => \%config,
391             'derived' => {},
392             'inc' => \@INC,
393             });
394             } # myconfig
395              
396             1;
397              
398             __END__