File Coverage

blib/lib/Config/Perl/V.pm
Criterion Covered Total %
statement 113 118 95.7
branch 44 54 81.4
condition 34 58 58.6
subroutine 10 10 100.0
pod 4 4 100.0
total 205 244 84.0


line stmt bran cond sub pod time code
1             package Config::Perl::V;
2              
3 29     29   2030487 use strict;
  29         373  
  29         863  
4 29     29   165 use warnings;
  29         61  
  29         662  
5              
6 29     29   144 use Config;
  29         47  
  29         1056  
7 29     29   137 use Exporter;
  29         84  
  29         1077  
8 29     29   187 use vars qw($VERSION @ISA @EXPORT_OK %EXPORT_TAGS);
  29         76  
  29         71883  
9             $VERSION = "0.36";
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_RC_STACK
63             PERL_RELOCATABLE_INCPUSH
64             PERL_USE_DEVEL
65             PERL_USE_SAFE_PUTENV
66             PERL_USE_UNSHARED_KEYS_IN_LARGE_HASHES
67             SILENT_NO_TAINT_SUPPORT
68             UNLINK_ALL_VERSIONS
69             USE_ATTRIBUTES_FOR_PERLIO
70             USE_FAST_STDIO
71             USE_HASH_SEED_EXPLICIT
72             USE_LOCALE
73             USE_LOCALE_CTYPE
74             USE_NO_REGISTRY
75             USE_PERL_ATOF
76             USE_SITECUSTOMIZE
77             USE_THREAD_SAFE_LOCALE
78              
79             DEBUG_LEAKING_SCALARS
80             DEBUG_LEAKING_SCALARS_FORK_DUMP
81             DECCRTL_SOCKETS
82             FAKE_THREADS
83             FCRYPT
84             HAS_TIMES
85             HAVE_INTERP_INTERN
86             MULTIPLICITY
87             MYMALLOC
88             NO_HASH_SEED
89             PERL_DEBUG_READONLY_COW
90             PERL_DEBUG_READONLY_OPS
91             PERL_GLOBAL_STRUCT
92             PERL_GLOBAL_STRUCT_PRIVATE
93             PERL_HASH_NO_SBOX32
94             PERL_HASH_USE_SBOX32
95             PERL_IMPLICIT_CONTEXT
96             PERL_IMPLICIT_SYS
97             PERLIO_LAYERS
98             PERL_MAD
99             PERL_MICRO
100             PERL_NEED_APPCTX
101             PERL_NEED_TIMESBASE
102             PERL_OLD_COPY_ON_WRITE
103             PERL_POISON
104             PERL_SAWAMPERSAND
105             PERL_TRACK_MEMPOOL
106             PERL_USES_PL_PIDSTATUS
107             PL_OP_SLAB_ALLOC
108             THREADS_HAVE_PIDS
109             USE_64_BIT_ALL
110             USE_64_BIT_INT
111             USE_IEEE
112             USE_ITHREADS
113             USE_LARGE_FILES
114             USE_LOCALE_COLLATE
115             USE_LOCALE_NUMERIC
116             USE_LOCALE_TIME
117             USE_LONG_DOUBLE
118             USE_PERLIO
119             USE_QUADMATH
120             USE_REENTRANT_API
121             USE_SFIO
122             USE_SOCKS
123             VMS_DO_SOCKETS
124             VMS_SHORTEN_LONG_SYMBOLS
125             VMS_SYMBOL_CASE_AS_IS
126             );
127              
128             # These are all the keys that are
129             # 1. Always present in %Config - lib/Config.pm #87 tie %Config
130             # 2. Reported by 'perl -V' (the rest)
131             my @config_vars = qw(
132              
133             api_subversion
134             api_version
135             api_versionstring
136             archlibexp
137             dont_use_nlink
138             d_readlink
139             d_symlink
140             exe_ext
141             inc_version_list
142             ldlibpthname
143             patchlevel
144             path_sep
145             perl_patchlevel
146             privlibexp
147             scriptdir
148             sitearchexp
149             sitelibexp
150             subversion
151             usevendorprefix
152             version
153              
154             git_commit_id
155             git_describe
156             git_branch
157             git_uncommitted_changes
158             git_commit_id_title
159             git_snapshot_date
160              
161             package revision version_patchlevel_string
162              
163             osname osvers archname
164             myuname
165             config_args
166             hint useposix d_sigaction
167             useithreads usemultiplicity
168             useperlio d_sfio uselargefiles usesocks
169             use64bitint use64bitall uselongdouble
170             usemymalloc default_inc_excludes_dot bincompat5005
171              
172             cc ccflags
173             optimize
174             cppflags
175             ccversion gccversion gccosandvers
176             intsize longsize ptrsize doublesize byteorder
177             d_longlong longlongsize d_longdbl longdblsize
178             ivtype ivsize nvtype nvsize lseektype lseeksize
179             alignbytes prototype
180              
181             ld ldflags
182             libpth
183             libs
184             perllibs
185             libc so useshrplib libperl
186             gnulibc_version
187              
188             dlsrc dlext d_dlsymun ccdlflags
189             cccdlflags lddlflags
190             );
191              
192             my %empty_build = (
193             'osname' => "",
194             'stamp' => 0,
195             'options' => { %BTD },
196             'patches' => [],
197             );
198              
199             sub _make_derived {
200 69     69   171 my $conf = shift;
201              
202 69         353 for ( [ 'lseektype' => "Off_t" ],
203             [ 'myuname' => "uname" ],
204             [ 'perl_patchlevel' => "patch" ],
205             ) {
206 207         343 my ($official, $derived) = @{$_};
  207         457  
207 207   100     985 $conf->{'config'}{$derived} ||= $conf->{'config'}{$official};
208 207   100     1047 $conf->{'config'}{$official} ||= $conf->{'config'}{$derived};
209 207         702 $conf->{'derived'}{$derived} = delete $conf->{'config'}{$derived};
210             }
211              
212 69 100 100     449 if (exists $conf->{'config'}{'version_patchlevel_string'} &&
213             !exists $conf->{'config'}{'api_version'}) {
214 33         107 my $vps = $conf->{'config'}{'version_patchlevel_string'};
215             $vps =~ s{\b revision \s+ (\S+) }{}x and
216 33 50 0     199 $conf->{'config'}{'revision'} ||= $1;
217              
218             $vps =~ s{\b version \s+ (\S+) }{}x and
219 33 50 33     653 $conf->{'config'}{'api_version'} ||= $1;
220             $vps =~ s{\b subversion \s+ (\S+) }{}x and
221 33 50 66     638 $conf->{'config'}{'subversion'} ||= $1;
222             $vps =~ s{\b patch \s+ (\S+) }{}x and
223 33 50 0     170 $conf->{'config'}{'perl_patchlevel'} ||= $1;
224             }
225              
226             ($conf->{'config'}{'version_patchlevel_string'} ||= join " ",
227 0         0 map { ($_, $conf->{'config'}{$_} ) }
228 69   66     392 grep { $conf->{'config'}{$_} }
  84         285  
229             qw( api_version subversion perl_patchlevel )) =~ s/\bperl_//;
230              
231 69   50     466 $conf->{'config'}{'perl_patchlevel'} ||= ""; # 0 is not a valid patchlevel
232              
233 69 50       202 if ($conf->{'config'}{'perl_patchlevel'} =~ m{^git\w*-([^-]+)}i) {
234 0   0     0 $conf->{'config'}{'git_branch'} ||= $1;
235 0   0     0 $conf->{'config'}{'git_describe'} ||= $conf->{'config'}{'perl_patchlevel'};
236             }
237              
238 69   100     3238 $conf->{'config'}{$_} ||= "undef" for grep m{^(?:use|def)} => @config_vars;
239              
240 69         1029 $conf;
241             } # _make_derived
242              
243             sub plv2hash {
244 61     61 1 83065 my %config;
245              
246 61         899 my $pv = join "\n" => @_;
247              
248 61 100       712 if ($pv =~ m{^Summary of my\s+(\S+)\s+\(\s*(.*?)\s*\)}m) {
249 33         282 $config{'package'} = $1;
250 33         182 my $rev = $2;
251 33 50       354 $rev =~ s/^ revision \s+ (\S+) \s*//x and $config{'revision'} = $1;
252 33 50       187 $rev and $config{'version_patchlevel_string'} = $rev;
253 33         332 my ($rel) = $config{'package'} =~ m{perl(\d)};
254 33         301 my ($vers, $subvers) = $rev =~ m{version\s+(\d+)\s+subversion\s+(\d+)};
255             defined $vers && defined $subvers && defined $rel and
256 33 50 33     599 $config{'version'} = "$rel.$vers.$subvers";
      33        
257             }
258              
259 61 50       333 if ($pv =~ m{^\s+(Snapshot of:)\s+(\S+)}) {
260 0         0 $config{'git_commit_id_title'} = $1;
261 0         0 $config{'git_commit_id'} = $2;
262             }
263              
264             # these are always last on line and can have multiple quotation styles
265 61         198 for my $k (qw( ccflags ldflags lddlflags )) {
266 183 100       4053 $pv =~ s{, \s* $k \s*=\s* (.*) \s*$}{}mx or next;
267 45         536 my $v = $1;
268 45         269 $v =~ s/\s*,\s*$//;
269 45         247 $v =~ s/^(['"])(.*)\1$/$2/;
270 45         171 $config{$k} = $v;
271             }
272              
273 61         497 my %kv;
274 61 100       1622 if ($pv =~ m{\S,? (?:osvers|archname)=}) { # attr is not the first on the line
275             # up to and including 5.24, a line could have multiple kv pairs
276 15         5128 %kv = ($pv =~ m{\b
277             (\w+) # key
278             \s*= # assign
279             ( '\s*[^']*?\s*' # quoted value
280             | \S+[^=]*?\s*\n # unquoted running till end of line
281             | \S+ # unquoted value
282             | \s*\n # empty
283             )
284             (?:,?\s+|\s*\n)? # optional separator (5.8.x reports did
285             }gx); # not have a ',' between every kv pair)
286             }
287             else {
288             # as of 5.25, each kv pair is listed on its own line
289 46         9947 %kv = ($pv =~ m{^
290             \s+
291             (\w+) # key
292             \s*=\s* # assign
293             (.*?) # value
294             \s*,?\s*$
295             }gmx);
296             }
297              
298 61         526 while (my ($k, $v) = each %kv) {
299 1899         3170 $k =~ s{\s+$} {};
300 1899         2752 $v =~ s{\s*\n\z} {};
301 1899         2923 $v =~ s{,$} {};
302 1899 100       4398 $v =~ m{^'(.*)'$} and $v = $1;
303 1899         3405 $v =~ s{\s+$} {};
304 1899         5938 $config{$k} = $v;
305             }
306              
307 61         511 my $build = { %empty_build };
308              
309             $pv =~ m{^\s+Compiled at\s+(.*)}m
310 61 100       3229 and $build->{'stamp'} = $1;
311             $pv =~ m{^\s+Locally applied patches:(?:\s+|\n)(.*?)(?:[\s\n]+Buil[td] under)}ms
312 61 100       686 and $build->{'patches'} = [ split m{\n+\s*}, $1 ];
313             $pv =~ m{^\s+Compile-time options:(?:\s+|\n)(.*?)(?:[\s\n]+(?:Locally applied|Buil[td] under))}ms
314 61 100       5945 and map { $build->{'options'}{$_} = 1 } split m{\s+|\n} => $1;
  626         1221  
315              
316 61         194 $build->{'osname'} = $config{'osname'};
317             $pv =~ m{^\s+Built under\s+(.*)}m
318 61 100       3276 and $build->{'osname'} = $1;
319 61   66     324 $config{'osname'} ||= $build->{'osname'};
320              
321 61         536 return _make_derived ({
322             'build' => $build,
323             'environment' => {},
324             'config' => \%config,
325             'derived' => {},
326             'inc' => [],
327             });
328             } # plv2hash
329              
330             sub summary {
331 50   66 50 1 168163 my $conf = shift || myconfig ();
332             ref $conf eq "HASH"
333             && exists $conf->{'config'}
334             && exists $conf->{'build'}
335             && ref $conf->{'config'} eq "HASH"
336 50 100 66     879 && ref $conf->{'build'} eq "HASH" or return;
      100        
      100        
      100        
337              
338             my %info = map {
339 46 100       225 exists $conf->{'config'}{$_} ? ( $_ => $conf->{'config'}{$_} ) : () }
  1380         4003  
340             qw( archname osname osvers revision patchlevel subversion version
341             cc ccversion gccversion config_args inc_version_list
342             d_longdbl d_longlong use64bitall use64bitint useithreads
343             uselongdouble usemultiplicity usemymalloc useperlio useshrplib
344             doublesize intsize ivsize nvsize longdblsize longlongsize lseeksize
345             default_inc_excludes_dot
346             );
347 46         169 $info{$_}++ for grep { $conf->{'build'}{'options'}{$_} } keys %{$conf->{'build'}{'options'}};
  3494         4923  
  46         559  
348              
349 46         436 return \%info;
350             } # summary
351              
352             sub signature {
353 34     34 1 1345647 my $no_md5 = "0" x 32;
354 34 100       167 my $conf = summary (shift) or return $no_md5;
355              
356 30         87 eval { require Digest::MD5 };
  30         343  
357 30 100       202 $@ and return $no_md5;
358              
359 29         120 $conf->{'cc'} =~ s{.*\bccache\s+}{};
360 29         134 $conf->{'cc'} =~ s{.*[/\\]}{};
361              
362 29         79 delete $conf->{'config_args'};
363             return Digest::MD5::md5_hex (join "\xFF" => map {
364 802 50       2889 "$_=".(defined $conf->{$_} ? $conf->{$_} : "\xFE");
365 29         80 } sort keys %{$conf});
  29         416  
366             } # signature
367              
368             sub myconfig {
369 8     8 1 8375 my $args = shift;
370 1         5 my %args = ref $args eq "HASH" ? %{$args} :
371 8 100       58 ref $args eq "ARRAY" ? @{$args} : ();
  1 100       10  
372              
373 8         43 my $build = { %empty_build };
374              
375             # 5.14.0 and later provide all the information without shelling out
376 8         19 my $stamp = eval { Config::compile_date () };
  8         215  
377 8 100       38 if (defined $stamp) {
378 3         15 $stamp =~ s/^Compiled at //;
379 3         10 $build->{'osname'} = $^O;
380 3         6 $build->{'stamp'} = $stamp;
381 3         18 $build->{'patches'} = [ Config::local_patches () ];
382 3         58 $build->{'options'}{$_} = 1 for Config::bincompat_options (),
383             Config::non_bincompat_options ();
384             }
385             else {
386             #y $pv = qx[$^X -e"sub Config::myconfig{};" -V];
387 5         68010 my $cnf = plv2hash (qx[$^X -V]);
388              
389 5         137 $build->{$_} = $cnf->{'build'}{$_} for qw( osname stamp patches options );
390             }
391              
392 8         195 my @KEYS = keys %ENV;
393             my %env =
394 8         119 map {( $_ => $ENV{$_} )} grep m{^PERL} => @KEYS;
  24         76  
395 8 100       42 if ($args{'env'}) {
396 2         75 $env{$_} = $ENV{$_} for grep m{$args{'env'}} => @KEYS;
397             }
398              
399 8         33 my %config = map { $_ => $Config{$_} } @config_vars;
  712         7510  
400              
401 8         84 return _make_derived ({
402             'build' => $build,
403             'environment' => \%env,
404             'config' => \%config,
405             'derived' => {},
406             'inc' => \@INC,
407             });
408             } # myconfig
409              
410             1;
411              
412             __END__