Add MIME::Base 2.12 from Gisle Aas, version number bumped to 2.13.
[p5sagit/p5-mst-13.2.git] / t / pragma / locale.t
1 #!./perl -wT
2
3 BEGIN {
4     chdir 't' if -d 't';
5     @INC = '../lib';
6     unshift @INC, '.';
7     require Config; import Config;
8     if (!$Config{d_setlocale} || $Config{ccflags} =~ /\bD?NO_LOCALE\b/) {
9         print "1..0\n";
10         exit;
11     }
12 }
13
14 use strict;
15
16 my $debug = 1;
17
18 use Dumpvalue;
19
20 my $dumper = Dumpvalue->new(
21                             tick => qq{"},
22                             quoteHighBit => 0,
23                             unctrl => "quote"
24                            );
25 sub debug {
26   return unless $debug;
27   my($mess) = join "", @_;
28   chop $mess;
29   print $dumper->stringify($mess,1), "\n";
30 }
31
32 sub debugf {
33     printf @_ if $debug;
34 }
35
36 my $have_setlocale = 0;
37 eval {
38     require POSIX;
39     import POSIX ':locale_h';
40     $have_setlocale++;
41 };
42
43 # Visual C's CRT goes silly on strings of the form "en_US.ISO8859-1"
44 # and mingw32 uses said silly CRT
45 $have_setlocale = 0 if $^O eq 'MSWin32' && $Config{cc} =~ /^(cl|gcc)/i;
46
47 my $last = $have_setlocale ? 116 : 98;
48
49 print "1..$last\n";
50
51 use vars qw(&LC_ALL);
52
53 my $a = 'abc %';
54
55 sub ok {
56     my ($n, $result) = @_;
57
58     print 'not ' unless ($result);
59     print "ok $n\n";
60 }
61
62 # First we'll do a lot of taint checking for locales.
63 # This is the easiest to test, actually, as any locale,
64 # even the default locale will taint under 'use locale'.
65
66 sub is_tainted { # hello, camel two.
67     no warnings 'uninitialized' ;
68     my $dummy;
69     not eval { $dummy = join("", @_), kill 0; 1 }
70 }
71
72 sub check_taint ($$) {
73     ok $_[0], is_tainted($_[1]);
74 }
75
76 sub check_taint_not ($$) {
77     ok $_[0], not is_tainted($_[1]);
78 }
79
80 use locale;     # engage locale and therefore locale taint.
81
82 check_taint_not   1, $a;
83
84 check_taint       2, uc($a);
85 check_taint       3, "\U$a";
86 check_taint       4, ucfirst($a);
87 check_taint       5, "\u$a";
88 check_taint       6, lc($a);
89 check_taint       7, "\L$a";
90 check_taint       8, lcfirst($a);
91 check_taint       9, "\l$a";
92
93 check_taint_not  10, sprintf('%e', 123.456);
94 check_taint_not  11, sprintf('%f', 123.456);
95 check_taint_not  12, sprintf('%g', 123.456);
96 check_taint_not  13, sprintf('%d', 123.456);
97 check_taint_not  14, sprintf('%x', 123.456);
98
99 $_ = $a;        # untaint $_
100
101 $_ = uc($a);    # taint $_
102
103 check_taint      15, $_;
104
105 /(\w)/; # taint $&, $`, $', $+, $1.
106 check_taint      16, $&;
107 check_taint      17, $`;
108 check_taint      18, $';
109 check_taint      19, $+;
110 check_taint      20, $1;
111 check_taint_not  21, $2;
112
113 /(.)/;  # untaint $&, $`, $', $+, $1.
114 check_taint_not  22, $&;
115 check_taint_not  23, $`;
116 check_taint_not  24, $';
117 check_taint_not  25, $+;
118 check_taint_not  26, $1;
119 check_taint_not  27, $2;
120
121 /(\W)/; # taint $&, $`, $', $+, $1.
122 check_taint      28, $&;
123 check_taint      29, $`;
124 check_taint      30, $';
125 check_taint      31, $+;
126 check_taint      32, $1;
127 check_taint_not  33, $2;
128
129 /(\s)/; # taint $&, $`, $', $+, $1.
130 check_taint      34, $&;
131 check_taint      35, $`;
132 check_taint      36, $';
133 check_taint      37, $+;
134 check_taint      38, $1;
135 check_taint_not  39, $2;
136
137 /(\S)/; # taint $&, $`, $', $+, $1.
138 check_taint      40, $&;
139 check_taint      41, $`;
140 check_taint      42, $';
141 check_taint      43, $+;
142 check_taint      44, $1;
143 check_taint_not  45, $2;
144
145 $_ = $a;        # untaint $_
146
147 check_taint_not  46, $_;
148
149 /(b)/;          # this must not taint
150 check_taint_not  47, $&;
151 check_taint_not  48, $`;
152 check_taint_not  49, $';
153 check_taint_not  50, $+;
154 check_taint_not  51, $1;
155 check_taint_not  52, $2;
156
157 $_ = $a;        # untaint $_
158
159 check_taint_not  53, $_;
160
161 $b = uc($a);    # taint $b
162 s/(.+)/$b/;     # this must taint only the $_
163
164 check_taint      54, $_;
165 check_taint_not  55, $&;
166 check_taint_not  56, $`;
167 check_taint_not  57, $';
168 check_taint_not  58, $+;
169 check_taint_not  59, $1;
170 check_taint_not  60, $2;
171
172 $_ = $a;        # untaint $_
173
174 s/(.+)/b/;      # this must not taint
175 check_taint_not  61, $_;
176 check_taint_not  62, $&;
177 check_taint_not  63, $`;
178 check_taint_not  64, $';
179 check_taint_not  65, $+;
180 check_taint_not  66, $1;
181 check_taint_not  67, $2;
182
183 $b = $a;        # untaint $b
184
185 ($b = $a) =~ s/\w/$&/;
186 check_taint      68, $b;        # $b should be tainted.
187 check_taint_not  69, $a;        # $a should be not.
188
189 $_ = $a;        # untaint $_
190
191 s/(\w)/\l$1/;   # this must taint
192 check_taint      70, $_;
193 check_taint      71, $&;
194 check_taint      72, $`;
195 check_taint      73, $';
196 check_taint      74, $+;
197 check_taint      75, $1;
198 check_taint_not  76, $2;
199
200 $_ = $a;        # untaint $_
201
202 s/(\w)/\L$1/;   # this must taint
203 check_taint      77, $_;
204 check_taint      78, $&;
205 check_taint      79, $`;
206 check_taint      80, $';
207 check_taint      81, $+;
208 check_taint      82, $1;
209 check_taint_not  83, $2;
210
211 $_ = $a;        # untaint $_
212
213 s/(\w)/\u$1/;   # this must taint
214 check_taint      84, $_;
215 check_taint      85, $&;
216 check_taint      86, $`;
217 check_taint      87, $';
218 check_taint      88, $+;
219 check_taint      89, $1;
220 check_taint_not  90, $2;
221
222 $_ = $a;        # untaint $_
223
224 s/(\w)/\U$1/;   # this must taint
225 check_taint      91, $_;
226 check_taint      92, $&;
227 check_taint      93, $`;
228 check_taint      94, $';
229 check_taint      95, $+;
230 check_taint      96, $1;
231 check_taint_not  97, $2;
232
233 # After all this tainting $a should be cool.
234
235 check_taint_not  98, $a;
236
237 # I think we've seen quite enough of taint.
238 # Let us do some *real* locale work now,
239 # unless setlocale() is missing (i.e. minitest).
240
241 exit unless $have_setlocale;
242
243 # Find locales.
244
245 debug "# Scanning for locales...\n";
246
247 # Note that it's okay that some languages have their native names
248 # capitalized here even though that's not "right".  They are lowercased
249 # anyway later during the scanning process (and besides, some clueless
250 # vendor might have them capitalized errorneously anyway).
251
252 my $locales = <<EOF;
253 Afrikaans:af:za:1 15
254 Arabic:ar:dz eg sa:6 arabic8
255 Brezhoneg Breton:br:fr:1 15
256 Bulgarski Bulgarian:bg:bg:5
257 Chinese:zh:cn tw:cn.EUC eucCN eucTW euc.CN euc.TW Big5 GB2312 tw.EUC
258 Hrvatski Croatian:hr:hr:2
259 Cymraeg Welsh:cy:cy:1 14 15
260 Czech:cs:cz:2
261 Dansk Danish:dk:da:1 15
262 Nederlands Dutch:nl:be nl:1 15
263 English American British:en:au ca gb ie nz us uk zw:1 15 cp850
264 Esperanto:eo:eo:3
265 Eesti Estonian:et:ee:4 6 13
266 Suomi Finnish:fi:fi:1 15
267 Flamish::fl:1 15
268 Deutsch German:de:at be ch de lu:1 15
269 Euskaraz Basque:eu:es fr:1 15
270 Galego Galician:gl:es:1 15
271 Ellada Greek:el:gr:7 g8
272 Frysk:fy:nl:1 15
273 Greenlandic:kl:gl:4 6
274 Hebrew:iw:il:8 hebrew8
275 Hungarian:hu:hu:2
276 Indonesian:in:id:1 15
277 Gaeilge Irish:ga:IE:1 14 15
278 Italiano Italian:it:ch it:1 15
279 Nihongo Japanese:ja:jp:euc eucJP jp.EUC sjis
280 Korean:ko:kr:
281 Latine Latin:la:va:1 15
282 Latvian:lv:lv:4 6 13
283 Lithuanian:lt:lt:4 6 13
284 Macedonian:mk:mk:1 15
285 Maltese:mt:mt:3
286 Moldovan:mo:mo:2
287 Norsk Norwegian:no no\@nynorsk:no:1 15
288 Occitan:oc:es:1 15
289 Polski Polish:pl:pl:2
290 Rumanian:ro:ro:2
291 Russki Russian:ru:ru su ua:5 koi8 koi8r KOI8-R koi8u cp1251 cp866
292 Serbski Serbian:sr:yu:5
293 Slovak:sk:sk:2
294 Slovene Slovenian:sl:si:2
295 Sqhip Albanian:sq:sq:1 15
296 Svenska Swedish:sv:fi se:1 15
297 Thai:th:th:11 tis620
298 Turkish:tr:tr:9 turkish8
299 Yiddish:yi::1 15
300 EOF
301
302 if ($^O eq 'os390') {
303     # These cause heartburn.  Broken locales?
304     $locales =~ s/Svenska Swedish:sv:fi se:1 15\n//;
305     $locales =~ s/Thai:th:th:11 tis620\n//;
306 }
307
308 sub in_utf8 () { $^H & 0x08 }
309
310 if (in_utf8) {
311     require "pragma/locale/utf8";
312 } else {
313     require "pragma/locale/latin1";
314 }
315
316 my @Locale;
317 my $Locale;
318 my @Alnum_;
319
320 sub getalnum_ {
321     sort grep /\w/, map { chr } 0..255
322 }
323
324 sub trylocale {
325     my $locale = shift;
326     if (setlocale(LC_ALL, $locale)) {
327         push @Locale, $locale;
328     }
329 }
330
331 sub decode_encodings {
332     my @enc;
333
334     foreach (split(/ /, shift)) {
335         if (/^(\d+)$/) {
336             push @enc, "ISO8859-$1";
337             push @enc, "iso8859$1";     # HP
338             if ($1 eq '1') {
339                  push @enc, "roman8";   # HP
340             }
341         } else {
342             push @enc, $_;
343             push @enc, "$_.UTF-8";
344         }
345     }
346     if ($^O eq 'os390') {
347         push @enc, qw(IBM-037 IBM-819 IBM-1047);
348     }
349
350     return @enc;
351 }
352
353 trylocale("C");
354 trylocale("POSIX");
355 foreach (0..15) {
356     trylocale("ISO8859-$_");
357     trylocale("iso8859$_");
358     trylocale("iso8859-$_");
359     trylocale("iso_8859_$_");
360     trylocale("isolatin$_");
361     trylocale("isolatin-$_");
362     trylocale("iso_latin_$_");
363 }
364
365 # Sanitize the environment so that we can run the external 'locale'
366 # program without the taint mode getting grumpy.
367
368 # $ENV{PATH} is special in VMS.
369 delete $ENV{PATH} if $^O ne 'VMS' or $Config{d_setenv};
370
371 # Other subversive stuff.
372 delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
373
374 if (-x "/usr/bin/locale" && open(LOCALES, "/usr/bin/locale -a 2>/dev/null|")) {
375     while (<LOCALES>) {
376         chomp;
377         trylocale($_);
378     }
379     close(LOCALES);
380 } elsif ($^O eq 'VMS' && defined($ENV{'SYS$I18N_LOCALE'}) && -d 'SYS$I18N_LOCALE') {
381 # The SYS$I18N_LOCALE logical name search list was not present on 
382 # VAX VMS V5.5-12, but was on AXP && VAX VMS V6.2 as well as later versions.
383     opendir(LOCALES, "SYS\$I18N_LOCALE:");
384     while ($_ = readdir(LOCALES)) {
385         chomp;
386         trylocale($_);
387     }
388     close(LOCALES);
389 } else {
390
391     # This is going to be slow.
392
393     foreach my $locale (split(/\n/, $locales)) {
394         my ($locale_name, $language_codes, $country_codes, $encodings) =
395             split(/:/, $locale);
396         my @enc = decode_encodings($encodings);
397         foreach my $loc (split(/ /, $locale_name)) {
398             trylocale($loc);
399             foreach my $enc (@enc) {
400                 trylocale("$loc.$enc");
401             }
402             $loc = lc $loc;
403             foreach my $enc (@enc) {
404                 trylocale("$loc.$enc");
405             }
406         }
407         foreach my $lang (split(/ /, $language_codes)) {
408             trylocale($lang);
409             foreach my $country (split(/ /, $country_codes)) {
410                 my $lc = "${lang}_${country}";
411                 trylocale($lc);
412                 foreach my $enc (@enc) {
413                     trylocale("$lc.$enc");
414                 }
415                 my $lC = "${lang}_\U${country}";
416                 trylocale($lC);
417                 foreach my $enc (@enc) {
418                     trylocale("$lC.$enc");
419                 }
420             }
421         }
422     }
423 }
424
425 setlocale(LC_ALL, "C");
426
427 sub utf8locale { $_[0] =~ /utf-?8/i }
428
429 @Locale = sort @Locale;
430
431 debug "# Locales = @Locale\n";
432
433 my %Problem;
434 my %Okay;
435 my %Testing;
436 my @Neoalpha;
437 my %Neoalpha;
438
439 sub tryneoalpha {
440     my ($Locale, $i, $test) = @_;
441     unless ($test) {
442         $Problem{$i}{$Locale} = 1;
443         debug "# failed $i with locale '$Locale'\n";
444     } else {
445         push @{$Okay{$i}}, $Locale;
446     }
447 }
448
449 foreach $Locale (@Locale) {
450     debug "# Locale = $Locale\n";
451     @Alnum_ = getalnum_();
452     debug "# w = ", join("",@Alnum_), "\n";
453
454     unless (setlocale(LC_ALL, $Locale)) {
455         foreach (99..103) {
456             $Problem{$_}{$Locale} = -1;
457         }
458         next;
459     }
460
461     # Sieve the uppercase and the lowercase.
462     
463     my %UPPER = ();
464     my %lower = ();
465     my %BoThCaSe = ();
466     for (@Alnum_) {
467         if (/[^\d_]/) { # skip digits and the _
468             if (uc($_) eq $_) {
469                 $UPPER{$_} = $_;
470             }
471             if (lc($_) eq $_) {
472                 $lower{$_} = $_;
473             }
474         }
475     }
476     foreach (keys %UPPER) {
477         $BoThCaSe{$_}++ if exists $lower{$_};
478     }
479     foreach (keys %lower) {
480         $BoThCaSe{$_}++ if exists $UPPER{$_};
481     }
482     foreach (keys %BoThCaSe) {
483         delete $UPPER{$_};
484         delete $lower{$_};
485     }
486
487     debug "# UPPER    = ", join("", sort keys %UPPER   ), "\n";
488     debug "# lower    = ", join("", sort keys %lower   ), "\n";
489     debug "# BoThCaSe = ", join("", sort keys %BoThCaSe), "\n";
490
491     # Find the alphabets that are not alphabets in the default locale.
492
493     {
494         no locale;
495     
496         @Neoalpha = ();
497         for (keys %UPPER, keys %lower) {
498             push(@Neoalpha, $_) if (/\W/);
499             $Neoalpha{$_} = $_;
500         }
501     }
502
503     @Neoalpha = sort @Neoalpha;
504
505     debug "# Neoalpha = ", join("",@Neoalpha), "\n";
506
507     if (@Neoalpha == 0) {
508         # If we have no Neoalphas the remaining tests are no-ops.
509         debug "# no Neoalpha, skipping tests 99..102 for locale '$Locale'\n";
510         foreach (99..102) {
511             push @{$Okay{$_}}, $Locale;
512         }
513     } else {
514
515         # Test \w.
516     
517         if (utf8locale($Locale)) {
518             # Until the polymorphic regexen arrive.
519             debug "# skipping UTF-8 locale '$Locale'\n";
520         } else {
521             my $word = join('', @Neoalpha);
522
523             $word =~ /^(\w+)$/;
524
525             tryneoalpha($Locale, 99, $1 eq $word);
526         }
527
528         # Cross-check the whole 8-bit character set.
529
530         for (map { chr } 0..255) {
531             tryneoalpha($Locale, 100,
532                         (/\w/ xor /\W/) ||
533                         (/\d/ xor /\D/) ||
534                         (/\s/ xor /\S/));
535         }
536
537         # Test for read-only scalars' locale vs non-locale comparisons.
538
539         {
540             no locale;
541             $a = "qwerty";
542             {
543                 use locale;
544                 tryneoalpha($Locale, 101, ($a cmp "qwerty") == 0);
545             }
546         }
547
548         {
549             my ($from, $to, $lesser, $greater,
550                 @test, %test, $test, $yes, $no, $sign);
551
552             for (0..9) {
553                 # Select a slice.
554                 $from = int(($_*@Alnum_)/10);
555                 $to = $from + int(@Alnum_/10);
556                 $to = $#Alnum_ if ($to > $#Alnum_);
557                 $lesser  = join('', @Alnum_[$from..$to]);
558                 # Select a slice one character on.
559                 $from++; $to++;
560                 $to = $#Alnum_ if ($to > $#Alnum_);
561                 $greater = join('', @Alnum_[$from..$to]);
562                 ($yes, $no, $sign) = ($lesser lt $greater
563                                       ? ("    ", "not ", 1)
564                                       : ("not ", "    ", -1));
565                 # all these tests should FAIL (return 0).
566                 # Exact lt or gt cannot be tested because
567                 # in some locales, say, eacute and E may test equal.
568                 @test = 
569                     (
570                      $no.'    ($lesser  le $greater)',  # 1
571                      'not      ($lesser  ne $greater)', # 2
572                      '         ($lesser  eq $greater)', # 3
573                      $yes.'    ($lesser  ge $greater)', # 4
574                      $yes.'    ($lesser  ge $greater)', # 5
575                      $yes.'    ($greater le $lesser )', # 7
576                      'not      ($greater ne $lesser )', # 8
577                      '         ($greater eq $lesser )', # 9
578                      $no.'     ($greater ge $lesser )', # 10
579                      'not (($lesser cmp $greater) == -$sign)' # 12
580                      );
581                 @test{@test} = 0 x @test;
582                 $test = 0;
583                 for my $ti (@test) {
584                     $test{$ti} = eval $ti;
585                     $test ||= $test{$ti}
586                 }
587                 tryneoalpha($Locale, 102, $test == 0);
588                 if ($test) {
589                     debug "# lesser  = '$lesser'\n";
590                     debug "# greater = '$greater'\n";
591                     debug "# lesser cmp greater = ",
592                           $lesser cmp $greater, "\n";
593                     debug "# greater cmp lesser = ",
594                           $greater cmp $lesser, "\n";
595                     debug "# (greater) from = $from, to = $to\n";
596                     for my $ti (@test) {
597                         debugf("# %-40s %-4s", $ti,
598                                $test{$ti} ? 'FAIL' : 'ok');
599                         if ($ti =~ /\(\.*(\$.+ +cmp +\$[^\)]+)\.*\)/) {
600                             debugf("(%s == %4d)", $1, eval $1);
601                         }
602                         debug "\n#";
603                     }
604
605                     last;
606                 }
607             }
608         }
609     }
610
611     use locale;
612
613     my ($x, $y) = (1.23, 1.23);
614
615     my $a = "$x";
616     printf ''; # printf used to reset locale to "C"
617     my $b = "$y";
618
619     debug "# 103..107: a = $a, b = $b, Locale = $Locale\n";
620
621     tryneoalpha($Locale, 103, $a eq $b);
622
623     my $c = "$x";
624     my $z = sprintf ''; # sprintf used to reset locale to "C"
625     my $d = "$y";
626
627     debug "# 104..107: c = $c, d = $d, Locale = $Locale\n";
628
629     tryneoalpha($Locale, 104, $c eq $d); 
630
631     {
632         use warnings;
633         my $w = 0;
634         local $SIG{__WARN__} = sub { $w++ };
635
636         # the == (among other ops) used to warn for locales
637         # that had something else than "." as the radix character
638
639         tryneoalpha($Locale, 105, $c == 1.23);
640
641         tryneoalpha($Locale, 106, $c == $x);
642
643         tryneoalpha($Locale, 107, $c == $d);
644
645         {
646             no locale;
647         
648             my $e = "$x";
649
650             debug "# 108..110: e = $e, Locale = $Locale\n";
651
652             tryneoalpha($Locale, 108, $e == 1.23);
653
654             tryneoalpha($Locale, 109, $e == $x);
655             
656             tryneoalpha($Locale, 110, $e == $c);
657         }
658         
659         tryneoalpha($Locale, 111, $w == 0);
660
661         my $f = "1.23";
662
663         debug "# 112..114: f = $f, locale = $Locale\n";
664
665         tryneoalpha($Locale, 112, $f == 1.23);
666
667         tryneoalpha($Locale, 113, $f == $x);
668         
669         tryneoalpha($Locale, 114, $f == $c);
670     }
671
672     # Does taking lc separately differ from taking
673     # the lc "in-line"?  (This was the bug 19990704.002, change #3568.)
674     # The bug was in the caching of the 'o'-magic.
675     {
676         use locale;
677
678         sub lcA {
679             my $lc0 = lc $_[0];
680             my $lc1 = lc $_[1];
681             return $lc0 cmp $lc1;
682         }
683
684         sub lcB {
685             return lc($_[0]) cmp lc($_[1]);
686         }
687
688         my $x = "ab";
689         my $y = "aa";
690         my $z = "AB";
691
692         tryneoalpha($Locale, 115,
693                     lcA($x, $y) == 1 && lcB($x, $y) == 1 ||
694                     lcA($x, $z) == 0 && lcB($x, $z) == 0);
695     }
696
697     # Does lc of an UPPER (if different from the UPPER) match
698     # case-insensitively the UPPER, and does the UPPER match
699     # case-insensitively the lc of the UPPER.  And vice versa.
700     if (utf8locale($Locale)) {
701         # Until the polymorphic regexen arrive.
702         debug "# skipping UTF-8 locale '$Locale'\n";
703     } else {
704         use locale;
705
706         my @f = ();
707         foreach my $x (keys %UPPER) {
708             my $y = lc $x;
709             next unless uc $y eq $x;
710             push @f, $x unless $x =~ /$y/i && $y =~ /$x/i;
711         }
712         foreach my $x (keys %lower) {
713             my $y = uc $x;
714             next unless lc $y eq $x;
715             push @f, $x unless $x =~ /$y/i && $y =~ /$x/i;
716         }
717         tryneoalpha($Locale, 116, @f == 0);
718         if (@f) {
719             print "# failed 116 locale '$Locale' characters @f\n"
720         }
721     }
722
723 }
724
725 # Recount the errors.
726
727 foreach (99..$last) {
728     if ($Problem{$_} || !defined $Okay{$_} || !@{$Okay{$_}}) {
729         if ($_ == 102) {
730             print "# The failure of test 102 is not necessarily fatal.\n";
731             print "# It usually indicates a problem in the enviroment,\n";
732             print "# not in Perl itself.\n";
733         }
734         print "not ";
735     }
736     print "ok $_\n";
737 }
738
739 # Give final advice.
740
741 my $didwarn = 0;
742
743 foreach (99..$last) {
744     if ($Problem{$_}) {
745         my @f = sort keys %{ $Problem{$_} };
746         my $f = join(" ", @f);
747         $f =~ s/(.{50,60}) /$1\n#\t/g;
748         print
749             "#\n",
750             "# The locale ", (@f == 1 ? "definition" : "definitions"), "\n#\n",
751             "#\t", $f, "\n#\n",
752             "# on your system may have errors because the locale test $_\n",
753             "# failed in ", (@f == 1 ? "that locale" : "those locales"),
754             ".\n";
755         print <<EOW;
756 #
757 # If your users are not using these locales you are safe for the moment,
758 # but please report this failure first to perlbug\@perl.com using the
759 # perlbug script (as described in the INSTALL file) so that the exact
760 # details of the failures can be sorted out first and then your operating
761 # system supplier can be alerted about these anomalies.
762 #
763 EOW
764         $didwarn = 1;
765     }
766 }
767
768 # Tell which locales were okay and which were not.
769
770 if ($didwarn) {
771     my (@s, @F);
772     
773     foreach my $l (@Locale) {
774         my $p = 0;
775         foreach my $t (102..$last) {
776             $p++ if $Problem{$t}{$l};
777         }
778         push @s, $l if $p == 0;
779       push @F, $l unless $p == 0;
780     }
781     
782     if (@s) {
783         my $s = join(" ", @s);
784         $s =~ s/(.{50,60}) /$1\n#\t/g;
785
786         warn
787             "# The following locales\n#\n",
788             "#\t", $s, "\n#\n",
789             "# tested okay.\n#\n",
790     } else {
791         warn "# None of your locales were fully okay.\n";
792     }
793
794     if (@F) {
795         my $F = join(" ", @F);
796         $F =~ s/(.{50,60}) /$1\n#\t/g;
797
798         warn
799           "# The following locales\n#\n",
800             "#\t", $F, "\n#\n",
801           "# had problems.\n#\n",
802     } else {
803         warn "# None of your locales were broken.\n";
804     }
805 }
806
807 # eof