xref: /openbsd-src/gnu/usr.bin/perl/win32/config_sh.PL (revision 3d61058aa5c692477b6d18acfbbdb653a9930ff9)
1#!perl -w
2use strict;
3use FindExt;
4
5# take a semicolon separated path list and turn it into a quoted
6# list of paths that Text::Parsewords will grok
7sub mungepath {
8    my $p = shift;
9    # remove leading/trailing semis/spaces
10    $p =~ s/^[ ;]+//;
11    $p =~ s/[ ;]+$//;
12    $p =~ s/'/"/g;
13    my @p = map { $_ = "\"$_\"" if /\s/ and !/^".*"$/; $_ } split /;/, $p;
14    return wantarray ? @p : join(' ', @p);
15}
16
17# check that the directories in the provided var exist
18sub check_path {
19    my $opt = shift;
20    my $p = shift;
21    my @paths = mungepath($p);
22    my $header_seen = 0;
23    foreach my $path (@paths) {
24        $path =~ s/^"(.*)"$/$1/;
25        next, if -d $path;
26
27        if (not $header_seen++) {
28            print STDERR "'$opt' contains the following non-existing paths:\n";
29        }
30        print STDERR "\t$path\n";
31    }
32    if ($header_seen) {
33        print STDERR <<EOF;
34Did you provide a correct value for the 'CCHOME' option?
35
36(This check can be skipped by using the SKIP_CCHOME_CHECK=1 option)
37EOF
38        exit 1;
39    }
40}
41
42# generate an array of option strings from command-line args
43# or an option file
44#    -- added by BKS, 10-17-1999 to fix command-line overflow problems
45sub loadopts {
46    if ($ARGV[0] =~ /--cfgsh-option-file/) {
47	shift @ARGV;
48	my $optfile = shift @ARGV;
49	local (*OPTF);
50	open OPTF, '<', $optfile or die "Can't open $optfile: $!\n";
51	my @opts;
52	chomp(my $line = <OPTF>);
53	my @vars = split(/\t+~\t+/, $line);
54	for (@vars) {
55	    push(@opts, $_) unless (/^\s*$/);
56	}
57	close OPTF;
58	return \@opts;
59    }
60    else {
61	return \@ARGV;
62    }
63}
64
65sub replace_template {
66    my ($template, %opt) = @_;
67
68    open my $fh, "<", $template
69        or die "$0: Cannot open $template: $!\n";
70    my $result = '';
71    local $_;
72    while (<$fh>) {
73        s/~([\w_]+)~/exists $opt{$1} ? $opt{$1} : ''/eg;
74        if (/^([\w_]+)=(.*)$/) {
75            my($k,$v) = ($1,$2);
76            # this depends on cf_time being empty in the template (or we'll
77            # get a loop)
78            if (exists $opt{$k}) {
79                $_ = "$k='$opt{$k}'\n";
80            }
81        }
82        $result .= $_;
83    }
84    close $fh;
85
86    $result;
87}
88
89my $out = '-';
90if (@ARGV >= 2 && $ARGV[0] eq '-o') {
91    shift;
92    $out = shift;
93}
94
95my $prebuilt; # are we making the prebuilt config used to bootstrap?
96if (@ARGV && $ARGV[0] eq '--prebuilt') {
97    ++$prebuilt;
98    shift;
99}
100
101my %opt;
102
103my $optref = loadopts();
104while (@{$optref} && $optref->[0] =~ /^([\w_]+)=(.*)$/) {
105    $opt{$1}=$2;
106    shift(@{$optref});
107}
108
109FindExt::scan_ext("../cpan");
110FindExt::scan_ext("../dist");
111FindExt::scan_ext("../ext");
112FindExt::set_static_extensions(split ' ', $opt{static_ext});
113
114$opt{nonxs_ext}        = join(' ',FindExt::nonxs_ext()) || ' ';
115$opt{static_ext}       = join(' ',FindExt::static_ext()) || ' ';
116$opt{dynamic_ext}      = join(' ',FindExt::dynamic_ext()) || ' ';
117$opt{extensions}       = join(' ',FindExt::extensions()) || ' ';
118$opt{known_extensions} = join(' ',FindExt::known_extensions()) || ' ';
119
120my $pl_h = '../patchlevel.h';
121
122if (-e $pl_h) {
123    open PL, "<", $pl_h or die "Can't open $pl_h: $!";
124    while (<PL>) {
125	if (/^#\s*define\s+(PERL_\w+)\s+([\d.]+)/) {
126	    $opt{$1} = $2;
127	}
128    }
129    close PL;
130}
131else {
132    die "Can't find $pl_h: $!";
133}
134
135my $patch_file = '../.patch';
136
137if (-e $patch_file) {
138    open my $fh, "<", $patch_file or die "Can't open $patch_file: $!";
139    chomp($opt{PERL_PATCHLEVEL} = <$fh>);
140    close $fh;
141}
142
143$opt{version} = "$opt{PERL_REVISION}.$opt{PERL_VERSION}.$opt{PERL_SUBVERSION}";
144$opt{version_patchlevel_string} = "version $opt{PERL_VERSION} subversion $opt{PERL_SUBVERSION}";
145$opt{version_patchlevel_string} .= " patch $opt{PERL_PATCHLEVEL}" if exists $opt{PERL_PATCHLEVEL};
146
147my $ver = `ver 2>nul`;
148$opt{osvers} = $ver =~ /\b(\d+(?:\.\d+)+)\b/ ? $1 : '4.0';
149
150if (exists $opt{cc}) {
151    # cl version detection borrowed from Test::Smoke's configsmoke.pl
152    if ($opt{cc} =~ /\b(?:cl|icl)/) { #MSVC can come as clarm.exe, icl=Intel C
153        my $output = `$opt{cc} 2>&1`;
154        $opt{ccversion} = $output =~ /\b(\d+(?:\.\d+)+)\b/ ? $1 : '?';
155    }
156    elsif ($opt{cc} =~ /\bgcc\b/) {
157        chomp($opt{gccversion} = `$opt{cc} -dumpversion`);
158        chomp($opt{libc} = `$opt{cc} -o rt.exe configure/rt.c 1>nul 2>&1 && rt`);
159        if(-e 'rt.exe') { unlink 'rt.exe' } # rt.exe no longer needed
160        else { die "Failed to identify default runtime" }
161    }
162}
163
164$opt{cf_by} = $ENV{USERNAME} unless $opt{cf_by};
165if (!$opt{cf_email}) {
166    my $computername = eval{(gethostbyname('localhost'))[0]};
167# gethostbyname might not be implemented in miniperl
168    $computername = $ENV{COMPUTERNAME} if $@;
169    $opt{cf_email} = $opt{cf_by} . '@' . $computername;
170}
171$opt{usemymalloc} = 'y' if $opt{d_mymalloc} eq 'define';
172
173unless ($opt{SKIP_CCHOME_CHECK}) {
174    check_path('CCLIBDIR', $opt{libpth});
175    check_path('CCINCDIR', $opt{incpath});
176}
177
178$opt{libpth} = mungepath($opt{libpth}) if exists $opt{libpth};
179$opt{incpath} = mungepath($opt{incpath}) if exists $opt{incpath};
180
181my $int64;
182if ($opt{cc} =~ /\b(?:cl|icl)/) {
183    $int64  = '__int64';
184}
185elsif ($opt{cc} =~ /\bgcc\b/) {
186    $int64  = 'long long';
187}
188
189# set 64-bit options
190if ($opt{WIN64} eq 'define') {
191    $opt{d_atoll} = 'define';
192    $opt{d_strtoll} = 'define';
193    $opt{d_strtoull} = 'define';
194    $opt{ptrsize} = 8;
195    $opt{sizesize} = 8;
196    $opt{ssizetype} = $int64;
197    $opt{st_ino_size} = 8;
198}
199else {
200    $opt{d_atoll} = 'undef';
201    $opt{d_strtoll} = 'undef';
202    $opt{d_strtoull} = 'undef';
203    $opt{ptrsize} = 4;
204    $opt{sizesize} = 4;
205    $opt{ssizetype} = 'int';
206    $opt{st_ino_size} = 4;
207}
208
209# set 64-bit-int options
210if ($opt{use64bitint} eq 'define') {
211    if ($opt{uselongdouble} eq 'define' || $opt{usequadmath} eq 'define') {
212        $opt{d_nv_preserves_uv} = 'define';
213        $opt{nv_preserves_uv_bits} = 64;
214    }
215    else {
216        $opt{d_nv_preserves_uv} = 'undef';
217        $opt{nv_preserves_uv_bits} = 53;
218    }
219    $opt{ivdformat} = qq{"I64d"};
220    $opt{ivsize} = 8;
221    $opt{ivtype} = $int64;
222    $opt{sPRIXU64} = qq{"I64X"};
223    $opt{sPRId64} = qq{"I64d"};
224    $opt{sPRIi64} = qq{"I64i"};
225    $opt{sPRIo64} = qq{"I64o"};
226    $opt{sPRIu64} = qq{"I64u"};
227    $opt{sPRIx64} = qq{"I64x"};
228    $opt{uvXUformat} = qq{"I64X"};
229    $opt{uvoformat} = qq{"I64o"};
230    $opt{uvsize} = 8;
231    $opt{uvtype} = qq{unsigned $int64};
232    $opt{uvuformat} = qq{"I64u"};
233    $opt{uvxformat} = qq{"I64x"};
234}
235else {
236    $opt{d_nv_preserves_uv} = 'define';
237    $opt{ivdformat} = '"ld"';
238    $opt{ivsize} = 4;
239    $opt{ivtype} = 'long';
240    $opt{nv_preserves_uv_bits} = 32;
241    $opt{sPRIXU64} = '"lX"';
242    $opt{sPRId64} = '"ld"';
243    $opt{sPRIi64} = '"li"';
244    $opt{sPRIo64} = '"lo"';
245    $opt{sPRIu64} = '"lu"';
246    $opt{sPRIx64} = '"lx"';
247    $opt{uvXUformat} = '"lX"';
248    $opt{uvoformat} = '"lo"';
249    $opt{uvsize} = 4;
250    $opt{uvtype} = 'unsigned long';
251    $opt{uvuformat} = '"lu"';
252    $opt{uvxformat} = '"lx"';
253}
254
255unless ($opt{cc} =~ /\bcl/) {
256    if ($opt{WIN64} eq 'define') {
257        $opt{longdblsize} = 16;
258        $opt{longdblinfbytes} = '0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00';
259        $opt{longdblnanbytes} = '0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00';
260    }
261    else {
262        $opt{longdblsize} = 12;
263        $opt{longdblinfbytes} = '0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x7f, 0x00, 0x00';
264        $opt{longdblnanbytes} = '0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x00, 0x00';
265    }
266}
267
268# set long double options
269if ($opt{uselongdouble} eq 'define') {
270    $opt{d_Gconvert} = 'sprintf((b),"%.*""Lg",(n),(x))';
271    $opt{d_PRIEUldbl} = 'define';
272    $opt{d_PRIFUldbl} = 'define';
273    $opt{d_PRIGUldbl} = 'define';
274    $opt{d_modflproto} = 'define';
275    $opt{d_strtold} = 'define';
276    $opt{d_PRIeldbl} = 'define';
277    $opt{d_PRIfldbl} = 'define';
278    $opt{d_PRIgldbl} = 'define';
279    $opt{d_SCNfldbl} = 'define';
280    $opt{nvsize} = $opt{longdblsize};
281    $opt{nvtype} = 'long double';
282    $opt{nv_overflows_integers_at} = '256.0*256.0*256.0*256.0*256.0*256.0*256.0*2.0*2.0*2.0*2.0*2.0*2.0*2.0*2.0';
283    $opt{nvEUformat} = '"LE"';
284    $opt{nvFUformat} = '"LF"';
285    $opt{nvGUformat} = '"LG"';
286    $opt{nveformat} = '"Le"';
287    $opt{nvfformat} = '"Lf"';
288    $opt{nvgformat} = '"Lg"';
289    $opt{nvmantbits} = 64;
290    $opt{longdblkind} = 3;
291    $opt{longdblmantbits} = 64;
292}
293# set __float128 options
294elsif ($opt{usequadmath} eq 'define') {
295    $opt{d_Gconvert} = 'sprintf((b),"%.*""Lg",(n),(x))';
296    $opt{d_PRIEUldbl} = 'define';
297    $opt{d_PRIFUldbl} = 'define';
298    $opt{d_PRIGUldbl} = 'define';
299    $opt{d_modflproto} = 'define';
300    $opt{d_strtold} = 'define';
301    $opt{d_PRIeldbl} = 'define';
302    $opt{d_PRIfldbl} = 'define';
303    $opt{d_PRIgldbl} = 'define';
304    $opt{d_SCNfldbl} = 'define';
305    $opt{nv_overflows_integers_at} = '256.0*256.0*256.0*256.0*256.0*256.0*256.0*256.0*256.0*256.0*256.0*256.0*256.0*256.0*2.0';
306    $opt{nvsize} = 16;
307    $opt{nvtype} = '__float128';
308    $opt{nvEUformat} = '"QE"';
309    $opt{nvFUformat} = '"QF"';
310    $opt{nvGUformat} = '"QG"';
311    $opt{nveformat} = '"Qe"';
312    $opt{nvfformat} = '"Qf"';
313    $opt{nvgformat} = '"Qg"';
314    $opt{nvmantbits} = 112;
315    $opt{longdblkind} = 3;
316    $opt{longdblmantbits} = 64;
317    $opt{i_quadmath} = 'define';
318}
319else {
320    $opt{d_Gconvert} = 'sprintf((b),"%.*g",(n),(x))';
321    $opt{d_PRIEUldbl} = 'undef';
322    $opt{d_PRIFUldbl} = 'undef';
323    $opt{d_PRIGUldbl} = 'undef';
324
325    if($opt{cc} =~ /\b(?:cl|icl)/) {
326        $opt{d_modflproto} = 'undef';
327    }
328    else {
329        $opt{d_modflproto} = 'define';
330    }
331
332    $opt{d_strtold} = 'undef';
333    $opt{d_PRIeldbl} = 'undef';
334    $opt{d_PRIfldbl} = 'undef';
335    $opt{d_PRIgldbl} = 'undef';
336    $opt{d_SCNfldbl} = 'undef';
337    $opt{nvsize} = 8;
338    $opt{nvtype} = 'double';
339    $opt{nv_overflows_integers_at} = '256.0*256.0*256.0*256.0*256.0*256.0*2.0*2.0*2.0*2.0*2.0';
340    $opt{nvEUformat} = '"E"';
341    $opt{nvFUformat} = '"F"';
342    $opt{nvGUformat} = '"G"';
343    $opt{nveformat} = '"e"';
344    $opt{nvfformat} = '"f"';
345    $opt{nvgformat} = '"g"';
346}
347
348# change some configuration variables based on compiler version
349if ($opt{cc} =~ /\bcl/ and $opt{ccversion} =~ /^(\d+)/) {
350    my $ccversion = $1;
351    if ($ccversion >= 14) { # VC8+
352	$opt{sGMTIME_max} = 32535291599;
353	$opt{sLOCALTIME_max} = 32535244799;
354    }
355    if ($ccversion >= 16 && !$prebuilt) { # VC10+
356	$opt{i_stdint} = 'define';
357    }
358    if ($ccversion >= 19) { # VC14+
359	$opt{i_stdbool} = 'define' unless $prebuilt;
360    }
361}
362# find out which MSVC this ICC is using
363elsif ($opt{cc} =~ /\bicl/) {
364    my $output = `cl 2>&1`;
365    my $num_ver = $output =~ /\b(\d+(?:\.\d+)+)\b/ ? $1 : '?';
366    if ($num_ver =~ /^(\d+)/ && $1 >= 14) { # VC8+
367	$opt{sGMTIME_max} = 32535291599;
368	$opt{sLOCALTIME_max} = 32535244799;
369    }
370    if ($num_ver =~ /^(\d+)/ && $1 >= 16) { # VC10+
371	$opt{i_stdint} = 'define';
372    }
373    if ($num_ver =~ /^(\d+)/ && $1 >= 19) { # VC14+
374	$opt{i_stdbool} = 'define';
375    }
376    $opt{ar} ='xilib';
377}
378
379# win32.h always defines these, and those definitions
380# depend on the current CRT
381$opt{stdio_base} = 'PERLIO_FILE_base(fp)';
382$opt{stdio_bufsiz} = '(PERLIO_FILE_cnt(fp) + PERLIO_FILE_ptr(fp) - PERLIO_FILE_base(fp))';
383$opt{stdio_cnt} = 'PERLIO_FILE_cnt(fp)';
384$opt{stdio_ptr} = 'PERLIO_FILE_ptr(fp)';
385
386if ($opt{useithreads} eq 'define' && $opt{ccflags} =~ /-DPERL_IMPLICIT_SYS\b/) {
387    $opt{d_pseudofork} = 'define';
388}
389
390if ($opt{usecplusplus} eq 'define') {
391    $opt{d_cplusplus} = 'define';
392    $opt{extern_C} = 'extern "C"';
393}
394
395#if the fields above are defined, they override the defaults in the premade
396#config file
397my $template = shift
398    or die "$0: No template supplied\n";
399if ($out ne '-') {
400    # preserve cf_time to avoid generating a new config.sh with no changes
401    my $cf_time;
402    if (open my $fh, "<", $out) {
403        my $old = '';
404        # scan for cf_time while reading in the whole file
405        while (<$fh>) {
406            $old .= $_;
407            if (/^cf_time='(.*)'/) {
408                $cf_time = $1;
409            }
410        }
411        close $fh;
412
413        my $replaced = replace_template($template, %opt, cf_time => $cf_time);
414        if ($replaced eq $old) {
415            # no configuration change, skip updating
416            print "$0: No changes for $out\n";
417            exit;
418        }
419    }
420    open my $fh, ">", $out
421        or die "$0: Cannot create $out: $!\n";
422    print $fh replace_template($template, %opt, cf_time => scalar localtime);
423    close $fh
424        or die "$0: Failed to close $template: $!\n";
425}
426else {
427    print replace_template($template, %opt, cf_time => scalar localtime);
428}
429