e75087fbce707ffbc49ca9c00c6d6d83a9bb7ff4
[perl.git] / lib / locale.t
1 #!./perl -wT
2
3 # This tests plain 'use locale' and adorned 'use locale ":not_characters"'
4 # Because these pragmas are compile time, and I (khw) am trying to test
5 # without using 'eval' as much as possible, which might cloud the issue,  the
6 # crucial parts of the code are duplicated in a block for each pragma.
7
8 binmode STDOUT, ':utf8';
9 binmode STDERR, ':utf8';
10
11 BEGIN {
12     chdir 't' if -d 't';
13     @INC = '../lib';
14     unshift @INC, '.';
15     require Config; import Config;
16     if (!$Config{d_setlocale} || $Config{ccflags} =~ /\bD?NO_LOCALE\b/) {
17         print "1..0\n";
18         exit;
19     }
20     $| = 1;
21 }
22
23 use strict;
24 use feature 'fc';
25
26 my $debug = 0;
27
28 use Dumpvalue;
29
30 my $dumper = Dumpvalue->new(
31                             tick => qq{"},
32                             quoteHighBit => 0,
33                             unctrl => "quote"
34                            );
35 sub debug {
36   return unless $debug;
37   my($mess) = join "", @_;
38   chop $mess;
39   print $dumper->stringify($mess,1), "\n";
40 }
41
42 sub debugf {
43     printf @_ if $debug;
44 }
45
46 my $have_setlocale = 0;
47 eval {
48     require POSIX;
49     import POSIX ':locale_h';
50     $have_setlocale++;
51 };
52
53 # Visual C's CRT goes silly on strings of the form "en_US.ISO8859-1"
54 # and mingw32 uses said silly CRT
55 # This doesn't seem to be an issue any more, at least on Windows XP,
56 # so re-enable the tests for Windows XP onwards.
57 my $winxp = ($^O eq 'MSWin32' && defined &Win32::GetOSVersion &&
58                 join('.', (Win32::GetOSVersion())[1..2]) >= 5.1);
59 $have_setlocale = 0 if ((($^O eq 'MSWin32' && !$winxp) || $^O eq 'NetWare') &&
60                 $Config{cc} =~ /^(cl|gcc)/i);
61
62 # UWIN seems to loop after taint tests, just skip for now
63 $have_setlocale = 0 if ($^O =~ /^uwin/);
64
65 sub LC_ALL ();
66
67 $a = 'abc %';
68
69 my $test_num = 0;
70
71 sub ok {
72     my ($result, $message) = @_;
73     $message = "" unless defined $message;
74
75     print 'not ' unless ($result);
76     print "ok " . ++$test_num;
77     print " $message";
78     print "\n";
79 }
80
81 # First we'll do a lot of taint checking for locales.
82 # This is the easiest to test, actually, as any locale,
83 # even the default locale will taint under 'use locale'.
84
85 sub is_tainted { # hello, camel two.
86     no warnings 'uninitialized' ;
87     my $dummy;
88     local $@;
89     not eval { $dummy = join("", @_), kill 0; 1 }
90 }
91
92 sub check_taint ($;$) {
93     my $message_tail = $_[1] // "";
94     $message_tail = ": $message_tail" if $message_tail;
95     ok is_tainted($_[0]), "verify that is tainted$message_tail";
96 }
97
98 sub check_taint_not ($;$) {
99     my $message_tail = $_[1] // "";
100     $message_tail = ": $message_tail" if $message_tail;
101     ok((not is_tainted($_[0])), "verify that isn't tainted$message_tail");
102 }
103
104 use locale;     # engage locale and therefore locale taint.
105
106 check_taint_not   $a;
107
108 check_taint       uc($a);
109 check_taint       "\U$a";
110 check_taint       ucfirst($a);
111 check_taint       "\u$a";
112 check_taint       lc($a);
113 check_taint       fc($a);
114 check_taint       "\L$a";
115 check_taint       "\F$a";
116 check_taint       lcfirst($a);
117 check_taint       "\l$a";
118
119 check_taint_not  sprintf('%e', 123.456);
120 check_taint_not  sprintf('%f', 123.456);
121 check_taint_not  sprintf('%g', 123.456);
122 check_taint_not  sprintf('%d', 123.456);
123 check_taint_not  sprintf('%x', 123.456);
124
125 $_ = $a;        # untaint $_
126
127 $_ = uc($a);    # taint $_
128
129 check_taint      $_;
130
131 /(\w)/; # taint $&, $`, $', $+, $1.
132 check_taint      $&;
133 check_taint      $`;
134 check_taint      $';
135 check_taint      $+;
136 check_taint      $1;
137 check_taint_not  $2;
138
139 /(.)/;  # untaint $&, $`, $', $+, $1.
140 check_taint_not  $&;
141 check_taint_not  $`;
142 check_taint_not  $';
143 check_taint_not  $+;
144 check_taint_not  $1;
145 check_taint_not  $2;
146
147 /(\W)/; # taint $&, $`, $', $+, $1.
148 check_taint      $&;
149 check_taint      $`;
150 check_taint      $';
151 check_taint      $+;
152 check_taint      $1;
153 check_taint_not  $2;
154
155 /(\s)/; # taint $&, $`, $', $+, $1.
156 check_taint      $&;
157 check_taint      $`;
158 check_taint      $';
159 check_taint      $+;
160 check_taint      $1;
161 check_taint_not  $2;
162
163 /(\S)/; # taint $&, $`, $', $+, $1.
164 check_taint      $&;
165 check_taint      $`;
166 check_taint      $';
167 check_taint      $+;
168 check_taint      $1;
169 check_taint_not  $2;
170
171 $_ = $a;        # untaint $_
172
173 check_taint_not  $_;
174
175 /(b)/;          # this must not taint
176 check_taint_not  $&;
177 check_taint_not  $`;
178 check_taint_not  $';
179 check_taint_not  $+;
180 check_taint_not  $1;
181 check_taint_not  $2;
182
183 $_ = $a;        # untaint $_
184
185 check_taint_not  $_;
186
187 $b = uc($a);    # taint $b
188 s/(.+)/$b/;     # this must taint only the $_
189
190 check_taint      $_;
191 check_taint_not  $&;
192 check_taint_not  $`;
193 check_taint_not  $';
194 check_taint_not  $+;
195 check_taint_not  $1;
196 check_taint_not  $2;
197
198 $_ = $a;        # untaint $_
199
200 s/(.+)/b/;      # this must not taint
201 check_taint_not  $_;
202 check_taint_not  $&;
203 check_taint_not  $`;
204 check_taint_not  $';
205 check_taint_not  $+;
206 check_taint_not  $1;
207 check_taint_not  $2;
208
209 $b = $a;        # untaint $b
210
211 ($b = $a) =~ s/\w/$&/;
212 check_taint      $b;    # $b should be tainted.
213 check_taint_not  $a;    # $a should be not.
214
215 $_ = $a;        # untaint $_
216
217 s/(\w)/\l$1/;   # this must taint
218 check_taint      $_;
219 check_taint      $&;
220 check_taint      $`;
221 check_taint      $';
222 check_taint      $+;
223 check_taint      $1;
224 check_taint_not  $2;
225
226 $_ = $a;        # untaint $_
227
228 s/(\w)/\L$1/;   # this must taint
229 check_taint      $_;
230 check_taint      $&;
231 check_taint      $`;
232 check_taint      $';
233 check_taint      $+;
234 check_taint      $1;
235 check_taint_not  $2;
236
237 $_ = $a;        # untaint $_
238
239 s/(\w)/\u$1/;   # this must taint
240 check_taint      $_;
241 check_taint      $&;
242 check_taint      $`;
243 check_taint      $';
244 check_taint      $+;
245 check_taint      $1;
246 check_taint_not  $2;
247
248 $_ = $a;        # untaint $_
249
250 s/(\w)/\U$1/;   # this must taint
251 check_taint      $_;
252 check_taint      $&;
253 check_taint      $`;
254 check_taint      $';
255 check_taint      $+;
256 check_taint      $1;
257 check_taint_not  $2;
258
259 # After all this tainting $a should be cool.
260
261 check_taint_not  $a;
262
263 {   # This is just the previous tests copied here with a different
264     # compile-time pragma.
265
266     use locale ':not_characters'; # engage restricted locale with different
267                                   # tainting rules
268
269     check_taint_not   $a;
270
271     check_taint_not     uc($a);
272     check_taint_not     "\U$a";
273     check_taint_not     ucfirst($a);
274     check_taint_not     "\u$a";
275     check_taint_not     lc($a);
276     check_taint_not     fc($a);
277     check_taint_not     "\L$a";
278     check_taint_not     "\F$a";
279     check_taint_not     lcfirst($a);
280     check_taint_not     "\l$a";
281
282     check_taint_not  sprintf('%e', 123.456);
283     check_taint_not  sprintf('%f', 123.456);
284     check_taint_not  sprintf('%g', 123.456);
285     check_taint_not  sprintf('%d', 123.456);
286     check_taint_not  sprintf('%x', 123.456);
287
288     $_ = $a;    # untaint $_
289
290     $_ = uc($a);        # taint $_
291
292     check_taint_not     $_;
293
294     /(\w)/;     # taint $&, $`, $', $+, $1.
295     check_taint_not     $&;
296     check_taint_not     $`;
297     check_taint_not     $';
298     check_taint_not     $+;
299     check_taint_not     $1;
300     check_taint_not  $2;
301
302     /(.)/;      # untaint $&, $`, $', $+, $1.
303     check_taint_not  $&;
304     check_taint_not  $`;
305     check_taint_not  $';
306     check_taint_not  $+;
307     check_taint_not  $1;
308     check_taint_not  $2;
309
310     /(\W)/;     # taint $&, $`, $', $+, $1.
311     check_taint_not     $&;
312     check_taint_not     $`;
313     check_taint_not     $';
314     check_taint_not     $+;
315     check_taint_not     $1;
316     check_taint_not  $2;
317
318     /(\s)/;     # taint $&, $`, $', $+, $1.
319     check_taint_not     $&;
320     check_taint_not     $`;
321     check_taint_not     $';
322     check_taint_not     $+;
323     check_taint_not     $1;
324     check_taint_not  $2;
325
326     /(\S)/;     # taint $&, $`, $', $+, $1.
327     check_taint_not     $&;
328     check_taint_not     $`;
329     check_taint_not     $';
330     check_taint_not     $+;
331     check_taint_not     $1;
332     check_taint_not  $2;
333
334     $_ = $a;    # untaint $_
335
336     check_taint_not  $_;
337
338     /(b)/;              # this must not taint
339     check_taint_not  $&;
340     check_taint_not  $`;
341     check_taint_not  $';
342     check_taint_not  $+;
343     check_taint_not  $1;
344     check_taint_not  $2;
345
346     $_ = $a;    # untaint $_
347
348     check_taint_not  $_;
349
350     $b = uc($a);        # taint $b
351     s/(.+)/$b/; # this must taint only the $_
352
353     check_taint_not     $_;
354     check_taint_not  $&;
355     check_taint_not  $`;
356     check_taint_not  $';
357     check_taint_not  $+;
358     check_taint_not  $1;
359     check_taint_not  $2;
360
361     $_ = $a;    # untaint $_
362
363     s/(.+)/b/;  # this must not taint
364     check_taint_not  $_;
365     check_taint_not  $&;
366     check_taint_not  $`;
367     check_taint_not  $';
368     check_taint_not  $+;
369     check_taint_not  $1;
370     check_taint_not  $2;
371
372     $b = $a;    # untaint $b
373
374     ($b = $a) =~ s/\w/$&/;
375     check_taint_not     $b;     # $b should be tainted.
376     check_taint_not  $a;        # $a should be not.
377
378     $_ = $a;    # untaint $_
379
380     s/(\w)/\l$1/;       # this must taint
381     check_taint_not     $_;
382     check_taint_not     $&;
383     check_taint_not     $`;
384     check_taint_not     $';
385     check_taint_not     $+;
386     check_taint_not     $1;
387     check_taint_not  $2;
388
389     $_ = $a;    # untaint $_
390
391     s/(\w)/\L$1/;       # this must taint
392     check_taint_not     $_;
393     check_taint_not     $&;
394     check_taint_not     $`;
395     check_taint_not     $';
396     check_taint_not     $+;
397     check_taint_not     $1;
398     check_taint_not  $2;
399
400     $_ = $a;    # untaint $_
401
402     s/(\w)/\u$1/;       # this must taint
403     check_taint_not     $_;
404     check_taint_not     $&;
405     check_taint_not     $`;
406     check_taint_not     $';
407     check_taint_not     $+;
408     check_taint_not     $1;
409     check_taint_not  $2;
410
411     $_ = $a;    # untaint $_
412
413     s/(\w)/\U$1/;       # this must taint
414     check_taint_not     $_;
415     check_taint_not     $&;
416     check_taint_not     $`;
417     check_taint_not     $';
418     check_taint_not     $+;
419     check_taint_not     $1;
420     check_taint_not  $2;
421
422     # After all this tainting $a should be cool.
423
424     check_taint_not  $a;
425 }
426
427 # Here are in scope of 'use locale'
428
429 # I think we've seen quite enough of taint.
430 # Let us do some *real* locale work now,
431 # unless setlocale() is missing (i.e. minitest).
432
433 unless ($have_setlocale) {
434     print "1..$test_num\n";
435     exit;
436 }
437
438 # The test number before our first setlocale()
439 my $final_without_setlocale = $test_num;
440
441 # Find locales.
442
443 debug "# Scanning for locales...\n";
444
445 # Note that it's okay that some languages have their native names
446 # capitalized here even though that's not "right".  They are lowercased
447 # anyway later during the scanning process (and besides, some clueless
448 # vendor might have them capitalized erroneously anyway).
449
450 my $locales = <<EOF;
451 Afrikaans:af:za:1 15
452 Arabic:ar:dz eg sa:6 arabic8
453 Brezhoneg Breton:br:fr:1 15
454 Bulgarski Bulgarian:bg:bg:5
455 Chinese:zh:cn tw:cn.EUC eucCN eucTW euc.CN euc.TW Big5 GB2312 tw.EUC
456 Hrvatski Croatian:hr:hr:2
457 Cymraeg Welsh:cy:cy:1 14 15
458 Czech:cs:cz:2
459 Dansk Danish:da:dk:1 15
460 Nederlands Dutch:nl:be nl:1 15
461 English American British:en:au ca gb ie nz us uk zw:1 15 cp850
462 Esperanto:eo:eo:3
463 Eesti Estonian:et:ee:4 6 13
464 Suomi Finnish:fi:fi:1 15
465 Flamish::fl:1 15
466 Deutsch German:de:at be ch de lu:1 15
467 Euskaraz Basque:eu:es fr:1 15
468 Galego Galician:gl:es:1 15
469 Ellada Greek:el:gr:7 g8
470 Frysk:fy:nl:1 15
471 Greenlandic:kl:gl:4 6
472 Hebrew:iw:il:8 hebrew8
473 Hungarian:hu:hu:2
474 Indonesian:id:id:1 15
475 Gaeilge Irish:ga:IE:1 14 15
476 Italiano Italian:it:ch it:1 15
477 Nihongo Japanese:ja:jp:euc eucJP jp.EUC sjis
478 Korean:ko:kr:
479 Latine Latin:la:va:1 15
480 Latvian:lv:lv:4 6 13
481 Lithuanian:lt:lt:4 6 13
482 Macedonian:mk:mk:1 15
483 Maltese:mt:mt:3
484 Moldovan:mo:mo:2
485 Norsk Norwegian:no no\@nynorsk nb nn:no:1 15
486 Occitan:oc:es:1 15
487 Polski Polish:pl:pl:2
488 Rumanian:ro:ro:2
489 Russki Russian:ru:ru su ua:5 koi8 koi8r KOI8-R koi8u cp1251 cp866
490 Serbski Serbian:sr:yu:5
491 Slovak:sk:sk:2
492 Slovene Slovenian:sl:si:2
493 Sqhip Albanian:sq:sq:1 15
494 Svenska Swedish:sv:fi se:1 15
495 Thai:th:th:11 tis620
496 Turkish:tr:tr:9 turkish8
497 Yiddish:yi::1 15
498 EOF
499
500 if ($^O eq 'os390') {
501     # These cause heartburn.  Broken locales?
502     $locales =~ s/Svenska Swedish:sv:fi se:1 15\n//;
503     $locales =~ s/Thai:th:th:11 tis620\n//;
504 }
505
506 sub in_utf8 () { $^H & 0x08 || (${^OPEN} || "") =~ /:utf8/ }
507
508 if (in_utf8) {
509     require "lib/locale/utf8";
510 } else {
511     require "lib/locale/latin1";
512 }
513
514 my @Locale;
515 my $Locale;
516 my @Alnum_;
517
518 sub trylocale {
519     my $locale = shift;
520     return if grep { $locale eq $_ } @Locale;
521     return unless setlocale(LC_ALL, $locale);
522     my $badutf8;
523     {
524         local $SIG{__WARN__} = sub {
525             $badutf8 = $_[0] =~ /Malformed UTF-8/;
526         };
527         $Locale =~ /UTF-?8/i;
528     }
529
530     if ($badutf8) {
531         ok(0, "Locale name contains malformed utf8");
532         return;
533     }
534     push @Locale, $locale;
535 }
536
537 sub decode_encodings {
538     my @enc;
539
540     foreach (split(/ /, shift)) {
541         if (/^(\d+)$/) {
542             push @enc, "ISO8859-$1";
543             push @enc, "iso8859$1";     # HP
544             if ($1 eq '1') {
545                  push @enc, "roman8";   # HP
546             }
547         } else {
548             push @enc, $_;
549             push @enc, "$_.UTF-8";
550         }
551     }
552     if ($^O eq 'os390') {
553         push @enc, qw(IBM-037 IBM-819 IBM-1047);
554     }
555
556     return @enc;
557 }
558
559 trylocale("C");
560 trylocale("POSIX");
561 foreach (0..15) {
562     trylocale("ISO8859-$_");
563     trylocale("iso8859$_");
564     trylocale("iso8859-$_");
565     trylocale("iso_8859_$_");
566     trylocale("isolatin$_");
567     trylocale("isolatin-$_");
568     trylocale("iso_latin_$_");
569 }
570
571 # Sanitize the environment so that we can run the external 'locale'
572 # program without the taint mode getting grumpy.
573
574 # $ENV{PATH} is special in VMS.
575 delete $ENV{PATH} if $^O ne 'VMS' or $Config{d_setenv};
576
577 # Other subversive stuff.
578 delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
579
580 if (-x "/usr/bin/locale" && open(LOCALES, "/usr/bin/locale -a 2>/dev/null|")) {
581     while (<LOCALES>) {
582         # It seems that /usr/bin/locale steadfastly outputs 8 bit data, which
583         # ain't great when we're running this testPERL_UNICODE= so that utf8
584         # locales will cause all IO hadles to default to (assume) utf8
585         next unless utf8::valid($_);
586         chomp;
587         trylocale($_);
588     }
589     close(LOCALES);
590 } elsif ($^O eq 'VMS' && defined($ENV{'SYS$I18N_LOCALE'}) && -d 'SYS$I18N_LOCALE') {
591 # The SYS$I18N_LOCALE logical name search list was not present on
592 # VAX VMS V5.5-12, but was on AXP && VAX VMS V6.2 as well as later versions.
593     opendir(LOCALES, "SYS\$I18N_LOCALE:");
594     while ($_ = readdir(LOCALES)) {
595         chomp;
596         trylocale($_);
597     }
598     close(LOCALES);
599 } elsif ($^O eq 'openbsd' && -e '/usr/share/locale') {
600
601    # OpenBSD doesn't have a locale executable, so reading /usr/share/locale
602    # is much easier and faster than the last resort method.
603
604     opendir(LOCALES, '/usr/share/locale');
605     while ($_ = readdir(LOCALES)) {
606         chomp;
607         trylocale($_);
608     }
609     close(LOCALES);
610 } else {
611
612     # This is going to be slow.
613
614     foreach my $locale (split(/\n/, $locales)) {
615         my ($locale_name, $language_codes, $country_codes, $encodings) =
616             split(/:/, $locale);
617         my @enc = decode_encodings($encodings);
618         foreach my $loc (split(/ /, $locale_name)) {
619             trylocale($loc);
620             foreach my $enc (@enc) {
621                 trylocale("$loc.$enc");
622             }
623             $loc = lc $loc;
624             foreach my $enc (@enc) {
625                 trylocale("$loc.$enc");
626             }
627         }
628         foreach my $lang (split(/ /, $language_codes)) {
629             trylocale($lang);
630             foreach my $country (split(/ /, $country_codes)) {
631                 my $lc = "${lang}_${country}";
632                 trylocale($lc);
633                 foreach my $enc (@enc) {
634                     trylocale("$lc.$enc");
635                 }
636                 my $lC = "${lang}_\U${country}";
637                 trylocale($lC);
638                 foreach my $enc (@enc) {
639                     trylocale("$lC.$enc");
640                 }
641             }
642         }
643     }
644 }
645
646 setlocale(LC_ALL, "C");
647
648 if ($^O eq 'darwin') {
649     # Darwin 8/Mac OS X 10.4 and 10.5 have bad Basque locales: perl bug #35895,
650     # Apple bug ID# 4139653. It also has a problem in Byelorussian.
651     (my $v) = $Config{osvers} =~ /^(\d+)/;
652     if ($v >= 8 and $v < 10) {
653         debug "# Skipping eu_ES, be_BY locales -- buggy in Darwin\n";
654         @Locale = grep ! m/^(eu_ES(?:\..*)?|be_BY\.CP1131)$/, @Locale;
655     } elsif ($v < 12) {
656         debug "# Skipping be_BY locales -- buggy in Darwin\n";
657         @Locale = grep ! m/^be_BY\.CP1131$/, @Locale;
658     }
659 }
660
661 @Locale = sort @Locale;
662
663 debug "# Locales =\n";
664 for ( @Locale ) {
665     debug "# $_\n";
666 }
667
668 my %Problem;
669 my %Okay;
670 my %Testing;
671 my @Neoalpha;   # Alnums that aren't in the C locale.
672 my %test_names;
673
674 sub tryneoalpha {
675     my ($Locale, $i, $test) = @_;
676     unless ($test) {
677         $Problem{$i}{$Locale} = 1;
678         debug "# failed $i with locale '$Locale'\n";
679     } else {
680         push @{$Okay{$i}}, $Locale;
681     }
682 }
683
684 my $first_locales_test_number = $final_without_setlocale + 1;
685 my $locales_test_number;
686 my $not_necessarily_a_problem_test_number;
687 my %setlocale_failed;   # List of locales that setlocale() didn't work on
688
689 foreach $Locale (@Locale) {
690     $locales_test_number = $first_locales_test_number - 1;
691     debug "# Locale = $Locale\n";
692
693     unless (setlocale(LC_ALL, $Locale)) {
694         $setlocale_failed{$Locale} = $Locale;
695         next;
696     }
697
698     # We test UTF-8 locales only under ':not_characters'; otherwise they have
699     # documented deficiencies.  Non- UTF-8 locales are tested only under plain
700     # 'use locale', as otherwise we would have to convert everything in them
701     # to Unicode.
702     my $is_utf8_locale = $Locale =~ /UTF-?8/i;
703
704     my %UPPER = ();
705     my %lower = ();
706     my %BoThCaSe = ();
707
708     if (! $is_utf8_locale) {
709         use locale;
710         @Alnum_ = sort grep /\w/, map { chr } 0..255;
711
712         debug "# w = ", join("",@Alnum_), "\n";
713
714         # Sieve the uppercase and the lowercase.
715
716         for (@Alnum_) {
717             if (/[^\d_]/) { # skip digits and the _
718                 if (uc($_) eq $_) {
719                     $UPPER{$_} = $_;
720                 }
721                 if (lc($_) eq $_) {
722                     $lower{$_} = $_;
723                 }
724             }
725         }
726     }
727     else {
728         use locale ':not_characters';
729         @Alnum_ = sort grep /\w/, map { chr } 0..255;
730         debug "# w = ", join("",@Alnum_), "\n";
731         for (@Alnum_) {
732             if (/[^\d_]/) { # skip digits and the _
733                 if (uc($_) eq $_) {
734                     $UPPER{$_} = $_;
735                 }
736                 if (lc($_) eq $_) {
737                     $lower{$_} = $_;
738                 }
739             }
740         }
741     }
742     foreach (keys %UPPER) {
743         $BoThCaSe{$_}++ if exists $lower{$_};
744     }
745     foreach (keys %lower) {
746         $BoThCaSe{$_}++ if exists $UPPER{$_};
747     }
748     foreach (keys %BoThCaSe) {
749         delete $UPPER{$_};
750         delete $lower{$_};
751     }
752
753     debug "# UPPER    = ", join("", sort keys %UPPER   ), "\n";
754     debug "# lower    = ", join("", sort keys %lower   ), "\n";
755     debug "# BoThCaSe = ", join("", sort keys %BoThCaSe), "\n";
756
757     {   # Find the alphabetic characters that are not considered alphabetics
758         # in the default (C) locale.
759
760         no locale;
761
762         @Neoalpha = ();
763         for (keys %UPPER, keys %lower) {
764             push(@Neoalpha, $_) if (/\W/);
765         }
766     }
767
768     @Neoalpha = sort @Neoalpha;
769
770     debug "# Neoalpha = ", join("",@Neoalpha), "\n";
771
772     my $first_Neoalpha_test_number =  $locales_test_number;
773     my $final_Neoalpha_test_number =  $first_Neoalpha_test_number + 4;
774     if (@Neoalpha == 0) {
775         # If we have no Neoalphas the remaining tests are no-ops.
776         debug "# no Neoalpha, skipping tests $locales_test_number..$final_Neoalpha_test_number for locale '$Locale'\n";
777         foreach ($locales_test_number+1..$final_Neoalpha_test_number) {
778             push @{$Okay{$_}}, $Locale;
779             $locales_test_number++;
780         }
781     } else {
782
783         # Test \w.
784
785         my $word = join('', @Neoalpha);
786
787         ++$locales_test_number;
788         $test_names{$locales_test_number} = 'Verify that alnums outside the C locale match \w';
789         my $ok;
790         if ($is_utf8_locale) {
791             use locale ':not_characters';
792             $ok = $word =~ /^(\w+)$/;
793         }
794         else {
795             # Already in 'use locale'; this tests that exiting scopes works
796             $ok = $word =~ /^(\w+)$/;
797         }
798         tryneoalpha($Locale, $locales_test_number, $ok);
799
800         # Cross-check the whole 8-bit character set.
801
802         ++$locales_test_number;
803         $test_names{$locales_test_number} = 'Verify that \w and \W are mutually exclusive, as are \d, \D; \s, \S';
804         for (map { chr } 0..255) {
805             if ($is_utf8_locale) {
806                 use locale ':not_characters';
807                 $ok =   (/\w/ xor /\W/) ||
808                         (/\d/ xor /\D/) ||
809                         (/\s/ xor /\S/);
810             }
811             else {
812                 $ok =   (/\w/ xor /\W/) ||
813                         (/\d/ xor /\D/) ||
814                         (/\s/ xor /\S/);
815             }
816             tryneoalpha($Locale, $locales_test_number, $ok);
817         }
818
819         # Test for read-only scalars' locale vs non-locale comparisons.
820
821         {
822             no locale;
823             $a = "qwerty";
824             if ($is_utf8_locale) {
825                 use locale ':not_characters';
826                 $ok = ($a cmp "qwerty") == 0;
827             }
828             else {
829                 use locale;
830                 $ok = ($a cmp "qwerty") == 0;
831             }
832             tryneoalpha($Locale, ++$locales_test_number, $ok);
833             $test_names{$locales_test_number} = 'Verify that cmp works with a read-only scalar; no- vs locale';
834         }
835
836         {
837             my ($from, $to, $lesser, $greater,
838                 @test, %test, $test, $yes, $no, $sign);
839
840             ++$locales_test_number;
841             $test_names{$locales_test_number} = 'Verify that "le", "ne", etc work';
842             $not_necessarily_a_problem_test_number = $locales_test_number;
843             for (0..9) {
844                 # Select a slice.
845                 $from = int(($_*@Alnum_)/10);
846                 $to = $from + int(@Alnum_/10);
847                 $to = $#Alnum_ if ($to > $#Alnum_);
848                 $lesser  = join('', @Alnum_[$from..$to]);
849                 # Select a slice one character on.
850                 $from++; $to++;
851                 $to = $#Alnum_ if ($to > $#Alnum_);
852                 $greater = join('', @Alnum_[$from..$to]);
853                 if ($is_utf8_locale) {
854                     use locale ':not_characters';
855                     ($yes, $no, $sign) = ($lesser lt $greater
856                                       ? ("    ", "not ", 1)
857                                       : ("not ", "    ", -1));
858                 }
859                 else {
860                     use locale;
861                     ($yes, $no, $sign) = ($lesser lt $greater
862                                       ? ("    ", "not ", 1)
863                                       : ("not ", "    ", -1));
864                 }
865                 # all these tests should FAIL (return 0).
866                 # Exact lt or gt cannot be tested because
867                 # in some locales, say, eacute and E may test equal.
868                 @test =
869                     (
870                      $no.'    ($lesser  le $greater)',  # 1
871                      'not      ($lesser  ne $greater)', # 2
872                      '         ($lesser  eq $greater)', # 3
873                      $yes.'    ($lesser  ge $greater)', # 4
874                      $yes.'    ($lesser  ge $greater)', # 5
875                      $yes.'    ($greater le $lesser )', # 7
876                      'not      ($greater ne $lesser )', # 8
877                      '         ($greater eq $lesser )', # 9
878                      $no.'     ($greater ge $lesser )', # 10
879                      'not (($lesser cmp $greater) == -($sign))' # 11
880                      );
881                 @test{@test} = 0 x @test;
882                 $test = 0;
883                 for my $ti (@test) {
884                     if ($is_utf8_locale) {
885                         use locale ':not_characters';
886                         $test{$ti} = eval $ti;
887                     }
888                     else {
889                         # Already in 'use locale';
890                         $test{$ti} = eval $ti;
891                     }
892                     $test ||= $test{$ti}
893                 }
894                 tryneoalpha($Locale, $locales_test_number, $test == 0);
895                 if ($test) {
896                     debug "# lesser  = '$lesser'\n";
897                     debug "# greater = '$greater'\n";
898                     debug "# lesser cmp greater = ",
899                           $lesser cmp $greater, "\n";
900                     debug "# greater cmp lesser = ",
901                           $greater cmp $lesser, "\n";
902                     debug "# (greater) from = $from, to = $to\n";
903                     for my $ti (@test) {
904                         debugf("# %-40s %-4s", $ti,
905                                $test{$ti} ? 'FAIL' : 'ok');
906                         if ($ti =~ /\(\.*(\$.+ +cmp +\$[^\)]+)\.*\)/) {
907                             debugf("(%s == %4d)", $1, eval $1);
908                         }
909                         debug "\n#";
910                     }
911
912                     last;
913                 }
914             }
915         }
916     }
917
918     if ($locales_test_number != $final_Neoalpha_test_number) {
919         die("The delta for \$final_Neoalpha needs to be updated from "
920             . ($final_Neoalpha_test_number - $first_Neoalpha_test_number)
921             . " to "
922             . ($locales_test_number - $first_Neoalpha_test_number)
923             );
924     }
925
926     my $ok1;
927     my $ok2;
928     my $ok3;
929     my $ok4;
930     my $ok5;
931     my $ok6;
932     my $ok7;
933     my $ok8;
934     my $ok9;
935     my $ok10;
936     my $ok11;
937     my $ok12;
938     my $ok13;
939
940     my $c;
941     my $d;
942     my $e;
943     my $f;
944     my $g;
945
946     if (! $is_utf8_locale) {
947         use locale;
948
949         my ($x, $y) = (1.23, 1.23);
950
951         $a = "$x";
952         printf ''; # printf used to reset locale to "C"
953         $b = "$y";
954         $ok1 = $a eq $b;
955
956         $c = "$x";
957         my $z = sprintf ''; # sprintf used to reset locale to "C"
958         $d = "$y";
959         $ok2 = $c eq $d;
960         {
961
962             use warnings;
963             my $w = 0;
964             local $SIG{__WARN__} =
965                 sub {
966                     print "# @_\n";
967                     $w++;
968                 };
969
970             # The == (among other ops) used to warn for locales
971             # that had something else than "." as the radix character.
972
973             $ok3 = $c == 1.23;
974             $ok4 = $c == $x;
975             $ok5 = $c == $d;
976             {
977                 no locale;
978
979                 # The earlier test was $e = "$x".  But this fails [perl
980                 # #108378], and the "no locale" was commented out.  But doing
981                 # that made all the tests in the block after this one
982                 # meaningless, as originally it was testing the nesting of a
983                 # "no locale" scope, and how it recovers after that scope is
984                 # done.  So I (khw) filed a bug report and changed this so it
985                 # wouldn't fail.  It seemed too much work to add TODOs
986                 # instead.  Should this be fixed, the following test names
987                 # would need to be revised; they mostly don't really test
988                 # anything currently.
989                 $e = $x;
990
991                 $ok6 = $e == 1.23;
992                 $ok7 = $e == $x;
993                 $ok8 = $e == $c;
994             }
995
996             $f = "1.23";
997             $g = 2.34;
998
999             $ok9 = $f == 1.23;
1000             $ok10 = $f == $x;
1001             $ok11 = $f == $c;
1002             $ok12 = abs(($f + $g) - 3.57) < 0.01;
1003             $ok13 = $w == 0;
1004         }
1005     }
1006     else {
1007         use locale ':not_characters';
1008
1009         my ($x, $y) = (1.23, 1.23);
1010         $a = "$x";
1011         printf ''; # printf used to reset locale to "C"
1012         $b = "$y";
1013         $ok1 = $a eq $b;
1014
1015         $c = "$x";
1016         my $z = sprintf ''; # sprintf used to reset locale to "C"
1017         $d = "$y";
1018         $ok2 = $c eq $d;
1019         {
1020             use warnings;
1021             my $w = 0;
1022             local $SIG{__WARN__} =
1023                 sub {
1024                     print "# @_\n";
1025                     $w++;
1026                 };
1027             $ok3 = $c == 1.23;
1028             $ok4 = $c == $x;
1029             $ok5 = $c == $d;
1030             {
1031                 no locale;
1032                 $e = $x;
1033
1034                 $ok6 = $e == 1.23;
1035                 $ok7 = $e == $x;
1036                 $ok8 = $e == $c;
1037             }
1038
1039             $f = "1.23";
1040             $g = 2.34;
1041
1042             $ok9 = $f == 1.23;
1043             $ok10 = $f == $x;
1044             $ok11 = $f == $c;
1045             $ok12 = abs(($f + $g) - 3.57) < 0.01;
1046             $ok13 = $w == 0;
1047         }
1048     }
1049
1050     tryneoalpha($Locale, ++$locales_test_number, $ok1);
1051     $test_names{$locales_test_number} = 'Verify that an intervening printf doesn\'t change assignment results';
1052     my $first_a_test = $locales_test_number;
1053
1054     debug "# $first_a_test..$locales_test_number: \$a = $a, \$b = $b, Locale = $Locale\n";
1055
1056     tryneoalpha($Locale, ++$locales_test_number, $ok2);
1057     $test_names{$locales_test_number} = 'Verify that an intervening sprintf doesn\'t change assignment results';
1058
1059     my $first_c_test = $locales_test_number;
1060
1061     tryneoalpha($Locale, ++$locales_test_number, $ok3);
1062     $test_names{$locales_test_number} = 'Verify that a different locale radix works when doing "==" with a constant';
1063
1064     tryneoalpha($Locale, ++$locales_test_number, $ok4);
1065     $test_names{$locales_test_number} = 'Verify that a different locale radix works when doing "==" with a scalar';
1066
1067     tryneoalpha($Locale, ++$locales_test_number, $ok5);
1068     $test_names{$locales_test_number} = 'Verify that a different locale radix works when doing "==" with a scalar and an intervening sprintf';
1069
1070     debug "# $first_c_test..$locales_test_number: \$c = $c, \$d = $d, Locale = $Locale\n";
1071
1072     tryneoalpha($Locale, ++$locales_test_number, $ok6);
1073     $test_names{$locales_test_number} = 'Verify that can assign numerically under inner no-locale block';
1074     my $first_e_test = $locales_test_number;
1075
1076     tryneoalpha($Locale, ++$locales_test_number, $ok7);
1077     $test_names{$locales_test_number} = 'Verify that "==" with a scalar still works in inner no locale';
1078
1079     tryneoalpha($Locale, ++$locales_test_number, $ok8);
1080     $test_names{$locales_test_number} = 'Verify that "==" with a scalar and an intervening sprintf still works in inner no locale';
1081
1082     debug "# $first_e_test..$locales_test_number: \$e = $e, no locale\n";
1083
1084     tryneoalpha($Locale, ++$locales_test_number, $ok9);
1085     $test_names{$locales_test_number} = 'Verify that after a no-locale block, a different locale radix still works when doing "==" with a constant';
1086     my $first_f_test = $locales_test_number;
1087
1088     tryneoalpha($Locale, ++$locales_test_number, $ok10);
1089     $test_names{$locales_test_number} = 'Verify that after a no-locale block, a different locale radix still works when doing "==" with a scalar';
1090
1091     tryneoalpha($Locale, ++$locales_test_number, $ok11);
1092     $test_names{$locales_test_number} = 'Verify that after a no-locale block, a different locale radix still works when doing "==" with a scalar and an intervening sprintf';
1093
1094     tryneoalpha($Locale, ++$locales_test_number, $ok12);
1095     $test_names{$locales_test_number} = 'Verify that after a no-locale block, a different locale radix can participate in an addition and function call as numeric';
1096
1097     tryneoalpha($Locale, ++$locales_test_number, $ok13);
1098     $test_names{$locales_test_number} = 'Verify that don\'t get warning under "==" even if radix is not a dot';
1099
1100     debug "# $first_f_test..$locales_test_number: \$f = $f, \$g = $g, back to locale = $Locale\n";
1101
1102     # Does taking lc separately differ from taking
1103     # the lc "in-line"?  (This was the bug 19990704.002, change #3568.)
1104     # The bug was in the caching of the 'o'-magic.
1105     if (! $is_utf8_locale) {
1106         use locale;
1107
1108         sub lcA {
1109             my $lc0 = lc $_[0];
1110             my $lc1 = lc $_[1];
1111             return $lc0 cmp $lc1;
1112         }
1113
1114         sub lcB {
1115             return lc($_[0]) cmp lc($_[1]);
1116         }
1117
1118         my $x = "ab";
1119         my $y = "aa";
1120         my $z = "AB";
1121
1122         tryneoalpha($Locale, ++$locales_test_number,
1123                     lcA($x, $y) == 1 && lcB($x, $y) == 1 ||
1124                     lcA($x, $z) == 0 && lcB($x, $z) == 0);
1125     }
1126     else {
1127         use locale ':not_characters';
1128
1129         sub lcC {
1130             my $lc0 = lc $_[0];
1131             my $lc1 = lc $_[1];
1132             return $lc0 cmp $lc1;
1133         }
1134
1135         sub lcD {
1136             return lc($_[0]) cmp lc($_[1]);
1137         }
1138
1139         my $x = "ab";
1140         my $y = "aa";
1141         my $z = "AB";
1142
1143         tryneoalpha($Locale, ++$locales_test_number,
1144                     lcC($x, $y) == 1 && lcD($x, $y) == 1 ||
1145                     lcC($x, $z) == 0 && lcD($x, $z) == 0);
1146     }
1147     $test_names{$locales_test_number} = 'Verify "lc(foo) cmp lc(bar)" is the same as using intermediaries for the cmp';
1148
1149     # Does lc of an UPPER (if different from the UPPER) match
1150     # case-insensitively the UPPER, and does the UPPER match
1151     # case-insensitively the lc of the UPPER.  And vice versa.
1152     {
1153         use locale;
1154         no utf8;
1155         my $re = qr/[\[\(\{\*\+\?\|\^\$\\]/;
1156
1157         my @f = ();
1158         ++$locales_test_number;
1159         $test_names{$locales_test_number} = 'Verify case insensitive matching works';
1160         foreach my $x (sort keys %UPPER) {
1161             if (! $is_utf8_locale) {
1162                 my $y = lc $x;
1163                 next unless uc $y eq $x;
1164                 print "# UPPER $x lc $y ",
1165                         $x =~ /$y/i ? 1 : 0, " ",
1166                         $y =~ /$x/i ? 1 : 0, "\n" if 0;
1167                 #
1168                 # If $x and $y contain regular expression characters
1169                 # AND THEY lowercase (/i) to regular expression characters,
1170                 # regcomp() will be mightily confused.  No, the \Q doesn't
1171                 # help here (maybe regex engine internal lowercasing
1172                 # is done after the \Q?)  An example of this happening is
1173                 # the bg_BG (Bulgarian) locale under EBCDIC (OS/390 USS):
1174                 # the chr(173) (the "[") is the lowercase of the chr(235).
1175                 #
1176                 # Similarly losing EBCDIC locales include cs_cz, cs_CZ,
1177                 # el_gr, el_GR, en_us.IBM-037 (!), en_US.IBM-037 (!),
1178                 # et_ee, et_EE, hr_hr, hr_HR, hu_hu, hu_HU, lt_LT,
1179                 # mk_mk, mk_MK, nl_nl.IBM-037, nl_NL.IBM-037,
1180                 # pl_pl, pl_PL, ro_ro, ro_RO, ru_ru, ru_RU,
1181                 # sk_sk, sk_SK, sl_si, sl_SI, tr_tr, tr_TR.
1182                 #
1183                 # Similar things can happen even under (bastardised)
1184                 # non-EBCDIC locales: in many European countries before the
1185                 # advent of ISO 8859-x nationally customised versions of
1186                 # ISO 646 were devised, reusing certain punctuation
1187                 # characters for modified characters needed by the
1188                 # country/language.  For example, the "|" might have
1189                 # stood for U+00F6 or LATIN SMALL LETTER O WITH DIAERESIS.
1190                 #
1191                 if ($x =~ $re || $y =~ $re) {
1192                     print "# Regex characters in '$x' or '$y', skipping test $locales_test_number for locale '$Locale'\n";
1193                     next;
1194                 }
1195                 # With utf8 both will fail since the locale concept
1196                 # of upper/lower does not work well in Unicode.
1197                 push @f, $x unless $x =~ /$y/i == $y =~ /$x/i;
1198
1199                 # fc is not a locale concept, so Perl uses lc for it.
1200                 push @f, $x unless lc $x eq fc $x;
1201             }
1202             else {
1203                 use locale ':not_characters';
1204                 my $y = lc $x;
1205                 next unless uc $y eq $x;
1206                 print "# UPPER $x lc $y ",
1207                         $x =~ /$y/i ? 1 : 0, " ",
1208                         $y =~ /$x/i ? 1 : 0, "\n" if 0;
1209
1210                 # Here, we can fully test things, unlike plain 'use locale',
1211                 # because this form does work well with Unicode
1212                 push @f, $x unless $x =~ /$y/i && $y =~ /$x/i;
1213
1214                 # The places where Unicode's lc is different from fc are
1215                 # skipped here by virtue of the 'next unless uc...' line above
1216                 push @f, $x unless lc $x eq fc $x;
1217             }
1218         }
1219
1220         foreach my $x (sort keys %lower) {
1221             if (! $is_utf8_locale) {
1222                 my $y = uc $x;
1223                 next unless lc $y eq $x;
1224                 print "# lower $x uc $y ",
1225                     $x =~ /$y/i ? 1 : 0, " ",
1226                     $y =~ /$x/i ? 1 : 0, "\n" if 0;
1227                 if ($x =~ $re || $y =~ $re) { # See above.
1228                     print "# Regex characters in '$x' or '$y', skipping test $locales_test_number for locale '$Locale'\n";
1229                     next;
1230                 }
1231                 # With utf8 both will fail since the locale concept
1232                 # of upper/lower does not work well in Unicode.
1233                 push @f, $x unless $x =~ /$y/i == $y =~ /$x/i;
1234
1235                 push @f, $x unless lc $x eq fc $x;
1236             }
1237             else {
1238                 use locale ':not_characters';
1239                 my $y = uc $x;
1240                 next unless lc $y eq $x;
1241                 print "# lower $x uc $y ",
1242                         $x =~ /$y/i ? 1 : 0, " ",
1243                         $y =~ /$x/i ? 1 : 0, "\n" if 0;
1244                 push @f, $x unless $x =~ /$y/i && $y =~ /$x/i;
1245
1246                 push @f, $x unless lc $x eq fc $x;
1247             }
1248         }
1249         tryneoalpha($Locale, $locales_test_number, @f == 0);
1250         if (@f) {
1251             print "# failed $locales_test_number locale '$Locale' characters @f\n"
1252         }
1253     }
1254
1255     # [perl #109318]
1256     {
1257         my @f = ();
1258         ++$locales_test_number;
1259         $test_names{$locales_test_number} = 'Verify atof with locale radix and negative exponent';
1260
1261         my $radix = POSIX::localeconv()->{decimal_point};
1262         my @nums = (
1263              "3.14e+9",  "3${radix}14e+9",  "3.14e-9",  "3${radix}14e-9",
1264             "-3.14e+9", "-3${radix}14e+9", "-3.14e-9", "-3${radix}14e-9",
1265         );
1266
1267         if (! $is_utf8_locale) {
1268             use locale;
1269             for my $num (@nums) {
1270                 push @f, $num
1271                     unless sprintf("%g", $num) =~ /3.+14/;
1272             }
1273         }
1274         else {
1275             use locale ':not_characters';
1276             for my $num (@nums) {
1277                 push @f, $num
1278                     unless sprintf("%g", $num) =~ /3.+14/;
1279             }
1280         }
1281
1282         tryneoalpha($Locale, $locales_test_number, @f == 0);
1283         if (@f) {
1284             print "# failed $locales_test_number locale '$Locale' numbers @f\n"
1285         }
1286     }
1287 }
1288
1289 my $final_locales_test_number = $locales_test_number;
1290
1291 # Recount the errors.
1292
1293 foreach ($first_locales_test_number..$final_locales_test_number) {
1294     if (%setlocale_failed) {
1295         print "not ";
1296     }
1297     elsif ($Problem{$_} || !defined $Okay{$_} || !@{$Okay{$_}}) {
1298         if (defined $not_necessarily_a_problem_test_number
1299             && $_ == $not_necessarily_a_problem_test_number)
1300         {
1301             print "# The failure of test $not_necessarily_a_problem_test_number is not necessarily fatal.\n";
1302             print "# It usually indicates a problem in the environment,\n";
1303             print "# not in Perl itself.\n";
1304         }
1305         print "not ";
1306     }
1307     print "ok $_";
1308     print " $test_names{$_}" if defined $test_names{$_};
1309     print "\n";
1310 }
1311
1312 # Give final advice.
1313
1314 my $didwarn = 0;
1315
1316 foreach ($first_locales_test_number..$final_locales_test_number) {
1317     if ($Problem{$_}) {
1318         my @f = sort keys %{ $Problem{$_} };
1319         my $f = join(" ", @f);
1320         $f =~ s/(.{50,60}) /$1\n#\t/g;
1321         print
1322             "#\n",
1323             "# The locale ", (@f == 1 ? "definition" : "definitions"), "\n#\n",
1324             "#\t", $f, "\n#\n",
1325             "# on your system may have errors because the locale test $_\n",
1326             "# failed in ", (@f == 1 ? "that locale" : "those locales"),
1327             ".\n";
1328         print <<EOW;
1329 #
1330 # If your users are not using these locales you are safe for the moment,
1331 # but please report this failure first to perlbug\@perl.com using the
1332 # perlbug script (as described in the INSTALL file) so that the exact
1333 # details of the failures can be sorted out first and then your operating
1334 # system supplier can be alerted about these anomalies.
1335 #
1336 EOW
1337         $didwarn = 1;
1338     }
1339 }
1340
1341 # Tell which locales were okay and which were not.
1342
1343 if ($didwarn) {
1344     my (@s, @F);
1345
1346     foreach my $l (@Locale) {
1347         my $p = 0;
1348         if ($setlocale_failed{$l}) {
1349             $p++;
1350         }
1351         else {
1352             foreach my $t
1353                         ($first_locales_test_number..$final_locales_test_number)
1354             {
1355                 $p++ if $Problem{$t}{$l};
1356             }
1357         }
1358         push @s, $l if $p == 0;
1359         push @F, $l unless $p == 0;
1360     }
1361
1362     if (@s) {
1363         my $s = join(" ", @s);
1364         $s =~ s/(.{50,60}) /$1\n#\t/g;
1365
1366         warn
1367             "# The following locales\n#\n",
1368             "#\t", $s, "\n#\n",
1369             "# tested okay.\n#\n",
1370     } else {
1371         warn "# None of your locales were fully okay.\n";
1372     }
1373
1374     if (@F) {
1375         my $F = join(" ", @F);
1376         $F =~ s/(.{50,60}) /$1\n#\t/g;
1377
1378         warn
1379           "# The following locales\n#\n",
1380           "#\t", $F, "\n#\n",
1381           "# had problems.\n#\n",
1382     } else {
1383         warn "# None of your locales were broken.\n";
1384     }
1385 }
1386
1387 $test_num = $final_locales_test_number;
1388
1389 # Test that tainting and case changing works on utf8 strings.  These tests are
1390 # placed last to avoid disturbing the hard-coded test numbers that existed at
1391 # the time these were added above this in this file.
1392 # This also tests that locale overrides unicode_strings in the same scope for
1393 # non-utf8 strings.
1394 setlocale(LC_ALL, "C");
1395 {
1396     use locale;
1397     use feature 'unicode_strings';
1398
1399     foreach my $function ("uc", "ucfirst", "lc", "lcfirst", "fc") {
1400         my @list;   # List of code points to test for $function
1401
1402         # Used to calculate the changed case for ASCII characters by using the
1403         # ord, instead of using one of the functions under test.
1404         my $ascii_case_change_delta;
1405         my $above_latin1_case_change_delta; # Same for the specific ords > 255
1406                                             # that we use
1407
1408         # We test an ASCII character, which should change case and be tainted;
1409         # a Latin1 character, which shouldn't change case under this C locale,
1410         #   and is tainted.
1411         # an above-Latin1 character that when the case is changed would cross
1412         #   the 255/256 boundary, so doesn't change case and isn't tainted
1413         # (the \x{149} is one of these, but changes into 2 characters, the
1414         #   first one of which doesn't cross the boundary.
1415         # the final one in each list is an above-Latin1 character whose case
1416         #   does change, and shouldn't be tainted.  The code below uses its
1417         #   position in its list as a marker to indicate that it, unlike the
1418         #   other code points above ASCII, has a successful case change
1419         if ($function =~ /^u/) {
1420             @list = ("", "a", "\xe0", "\xff", "\x{fb00}", "\x{149}", "\x{101}");
1421             $ascii_case_change_delta = -32;
1422             $above_latin1_case_change_delta = -1;
1423         }
1424         else {
1425             @list = ("", "A", "\xC0", "\x{1E9E}", "\x{100}");
1426             $ascii_case_change_delta = +32;
1427             $above_latin1_case_change_delta = +1;
1428         }
1429         foreach my $is_utf8_locale (0 .. 1) {
1430             foreach my $j (0 .. $#list) {
1431                 my $char = $list[$j];
1432
1433                 for my $encoded_in_utf8 (0 .. 1) {
1434                     my $should_be;
1435                     my $changed;
1436                     if (! $is_utf8_locale) {
1437                         $should_be = ($j == $#list)
1438                             ? chr(ord($char) + $above_latin1_case_change_delta)
1439                             : (length $char == 0 || ord($char) > 127)
1440                             ? $char
1441                             : chr(ord($char) + $ascii_case_change_delta);
1442
1443                         # This monstrosity is in order to avoid using an eval,
1444                         # which might perturb the results
1445                         $changed = ($function eq "uc")
1446                                     ? uc($char)
1447                                     : ($function eq "ucfirst")
1448                                       ? ucfirst($char)
1449                                       : ($function eq "lc")
1450                                         ? lc($char)
1451                                         : ($function eq "lcfirst")
1452                                           ? lcfirst($char)
1453                                           : ($function eq "fc")
1454                                             ? fc($char)
1455                                             : die("Unexpected function \"$function\"");
1456                     }
1457                     else {
1458                         {
1459                             no locale;
1460
1461                             # For utf8-locales the case changing functions
1462                             # should work just like they do outside of locale.
1463                             # Can use eval here because not testing it when
1464                             # not in locale.
1465                             $should_be = eval "$function('$char')";
1466                             die "Unexpected eval error $@ from 'eval \"$function('$char')\"'" if  $@;
1467
1468                         }
1469                         use locale ':not_characters';
1470                         $changed = ($function eq "uc")
1471                                     ? uc($char)
1472                                     : ($function eq "ucfirst")
1473                                       ? ucfirst($char)
1474                                       : ($function eq "lc")
1475                                         ? lc($char)
1476                                         : ($function eq "lcfirst")
1477                                           ? lcfirst($char)
1478                                           : ($function eq "fc")
1479                                             ? fc($char)
1480                                             : die("Unexpected function \"$function\"");
1481                     }
1482                     ok($changed eq $should_be,
1483                         "$function(\"$char\") in C locale "
1484                         . (($is_utf8_locale)
1485                             ? "(use locale ':not_characters'"
1486                             : "(use locale")
1487                         . (($encoded_in_utf8)
1488                             ? "; encoded in utf8)"
1489                             : "; not encoded in utf8)")
1490                         . " should be \"$should_be\", got \"$changed\"");
1491
1492                     # Tainting shouldn't happen for utf8 locales, empty
1493                     # strings, or those characters above 255.
1494                     (! $is_utf8_locale && length($char) > 0 && ord($char) < 256)
1495                     ? check_taint($changed)
1496                     : check_taint_not($changed);
1497
1498                     # Use UTF-8 next time through the loop
1499                     utf8::upgrade($char);
1500                 }
1501             }
1502         }
1503     }
1504 }
1505
1506 print "1..$test_num\n";
1507
1508 # eof